diff --git a/src/app/api/mapa/puntos/route.ts b/src/app/api/mapa/puntos/route.ts new file mode 100644 index 00000000..18f49049 --- /dev/null +++ b/src/app/api/mapa/puntos/route.ts @@ -0,0 +1,33 @@ +import { NextRequest } from 'next/server'; +import { createServerRoleClient } from '@/lib/supabase/serverrole'; + +export async function GET(req: NextRequest) { + const url = new URL(req.url); + const searchParams: any = url.searchParams; + + const accepted_items = searchParams.get('accepted') || 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('collection_points') + .select('*') + + if (accepted_items !== null) { + query.contains('accepted_items', [accepted_items]); + } + + const { data, error } = await query.order('created_at', { ascending: false }); + + + if (error) { + return Response.json({ error }); + } else { + return Response.json({ data }); + } + return Response.json({ message: 'Error' }); +} \ No newline at end of file diff --git a/src/app/api/mapa/route.ts b/src/app/api/mapa/route.ts index dceb6093..82e98372 100644 --- a/src/app/api/mapa/route.ts +++ b/src/app/api/mapa/route.ts @@ -2,43 +2,5 @@ import { NextRequest } from 'next/server'; import { createServerRoleClient } from '@/lib/supabase/serverrole'; 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' }); + return Response.json({ message: '' }); } \ No newline at end of file diff --git a/src/app/api/mapa/solicitudes/route.ts b/src/app/api/mapa/solicitudes/route.ts new file mode 100644 index 00000000..90cd9e5e --- /dev/null +++ b/src/app/api/mapa/solicitudes/route.ts @@ -0,0 +1,39 @@ +import { NextRequest } from 'next/server'; +import { createServerRoleClient } from '@/lib/supabase/serverrole'; + +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 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, created_at, longitude, resources, help_type, urgency, name,location, description, people_needed, additional_info->special_situations, status,other_help') + .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 (error) { + return Response.json({ error }); + } else { + return Response.json({ data }); + } + return Response.json({ message: 'Error' }); +} \ No newline at end of file diff --git a/src/app/api/ofertas/[id]/route.ts b/src/app/api/ofertas/[id]/route.ts new file mode 100644 index 00000000..36ccb4c2 --- /dev/null +++ b/src/app/api/ofertas/[id]/route.ts @@ -0,0 +1,28 @@ +import { createServerRoleClient } from '@/lib/supabase/serverrole'; +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('type', 'ofrece') + .eq('id', id) + .limit(1) + .select(); + + if (error) { + return Response.json({ error }); + } + return Response.json({ data }); +} diff --git a/src/app/api/ofertas/route.ts b/src/app/api/ofertas/route.ts index c79aae69..cab48598 100644 --- a/src/app/api/ofertas/route.ts +++ b/src/app/api/ofertas/route.ts @@ -2,41 +2,41 @@ import { NextRequest } from 'next/server'; import { createServerRoleClient } from '@/lib/supabase/serverrole'; 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') + // 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, 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 }); + '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 }); } \ No newline at end of file diff --git a/src/app/api/ofertas/usuario/route.ts b/src/app/api/ofertas/usuario/route.ts new file mode 100644 index 00000000..9b686da6 --- /dev/null +++ b/src/app/api/ofertas/usuario/route.ts @@ -0,0 +1,25 @@ + +import { createServerRoleClient } from '@/lib/supabase/serverrole'; +import { NextRequest } from 'next/server'; + +export async function GET(request: NextRequest) { + 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, count, error } = await supabase + .from('help_requests') + .select('', + { count: 'exact' }, + ) + .eq('type', 'ofrece') + .eq('user_id', dataUser?.user.id) + .select(); + + if (error) { + return Response.json({ error }); + } + return Response.json({ count }); +} diff --git a/src/app/api/solicitudes/[id]/route.ts b/src/app/api/solicitudes/[id]/route.ts index 3f4fbe16..a436d7ce 100644 --- a/src/app/api/solicitudes/[id]/route.ts +++ b/src/app/api/solicitudes/[id]/route.ts @@ -2,26 +2,27 @@ import { createServerRoleClient } from '@/lib/supabase/serverrole'; import { NextRequest } from 'next/server'; export async function GET(request: NextRequest, { params }: { params: { id: string } }) { - const id = params.id; + 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 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(); + 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) + .eq('type', 'necesita') + .limit(1) + .select(); - if (error) { - return Response.json({ error }); - } - return Response.json({ data }); + 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 45de0f78..ee5f01c0 100644 --- a/src/app/api/solicitudes/route.ts +++ b/src/app/api/solicitudes/route.ts @@ -1,51 +1,88 @@ import { NextRequest, NextResponse } from 'next/server'; -import { createClient } from '@/lib/supabase/server'; +import { createServerRoleClient } from '@/lib/supabase/serverrole'; 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, 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 }); + try { + // Acceder a los parámetros de búsqueda + const url = new URL(req.url); + const searchParams = url.searchParams; + + const help_type = searchParams.get('type'); + const town_id = searchParams.get('town'); + const urgency = searchParams.get('urgency'); + const currentPage = parseInt(searchParams.get('page') ?? '1'); + const itemsPerPage = 10; + + const supabase = await createServerRoleClient(); + + // Primero verificamos que el cliente se creó correctamente + if (!supabase) { + console.error('Error creating Supabase client'); + return NextResponse.json({ error: 'Database connection error' }, { status: 500 }); + } + + // Iniciamos la query base + let 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' } + ); + + // Agregamos los filtros solo si los valores no son null + if (help_type) { + console.log('Filtering by help_type:', help_type); + query = query.contains('help_type', [help_type]); + } + + if (town_id) { + console.log('Filtering by town_id:', town_id); + query = query.eq('town_id', town_id); + } + + if (urgency) { + console.log('Filtering by urgency:', urgency); + query = query.eq('urgency', urgency); + } + + // Aplicamos el filtro de status + query = query.neq('status', 'finished'); + + // Calculamos el rango + const from = (currentPage - 1) * itemsPerPage; + const to = from + itemsPerPage - 1; + + console.log(`Fetching range: ${from} to ${to}`); + + // Ejecutamos la query + const { data, count, error } = await query + .range(from, to) + .order('created_at', { ascending: false }); + + // Manejamos los errores específicamente + if (error) { + console.error('Supabase error:', error); + return NextResponse.json({ error: error.message }, { status: 500 }); + } + + // Verificamos si tenemos datos + if (!data || data.length === 0) { + console.log('No data found with current filters'); + return NextResponse.json({ data: [], count: 0 }); + } + + return NextResponse.json({ + data, + count: count ?? 0, + page: currentPage, + totalPages: Math.ceil((count ?? 0) / itemsPerPage) + }); + + } catch (error) { + console.error('Unexpected error:', error); + return NextResponse.json( + { error: 'An unexpected error occurred' }, + { status: 500 } + ); + } } \ No newline at end of file diff --git a/src/app/api/solicitudes/usuario/route.ts b/src/app/api/solicitudes/usuario/route.ts new file mode 100644 index 00000000..865beb3e --- /dev/null +++ b/src/app/api/solicitudes/usuario/route.ts @@ -0,0 +1,25 @@ + +import { createServerRoleClient } from '@/lib/supabase/serverrole'; +import { NextRequest } from 'next/server'; + +export async function GET(request: NextRequest) { + 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, count, error } = await supabase + .from('help_requests') + .select('', + { count: 'exact' }, + ) + .eq('type', 'necesita') + .eq('user_id', dataUser?.user.id) + .select(); + + if (error) { + return Response.json({ error }); + } + return Response.json({ count }); +} diff --git a/src/app/casos-activos/mapa/page.tsx b/src/app/casos-activos/mapa/page.tsx index 23822f74..6e028605 100644 --- a/src/app/casos-activos/mapa/page.tsx +++ b/src/app/casos-activos/mapa/page.tsx @@ -11,164 +11,166 @@ import PickupPoint from '@/components/PickupPoint'; export const dynamic = 'force-dynamic'; export default function MapaPage() { - return ( - - - - ); + return ( + + + + ); } function Mapa() { - const searchParams = useSearchParams(); - const router = useRouter(); - - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - - const [data, setData] = useState([]); - - const updateFilter = (filter: any, value: any) => { - const params = new URLSearchParams(searchParams.toString()); - params.set(filter, value); - router.push(`?${params.toString()}`); - }; - - const [filtroData, setFiltroData] = useState({ - urgencia: searchParams.get('urgencia') || 'todas', - tipoAyuda: searchParams.get('tipoAyuda') || 'todas', - pueblo: searchParams.get('pueblo') || 'todos', - acepta: searchParams.get('acepta') || 'todos', - }); - - const changeDataFilter = (type: any, newFilter: any) => { - setFiltroData((prev) => ({ - ...prev, - [type]: newFilter, - })); - updateFilter(type, newFilter); - }; - - useEffect(() => { - function transformHelpRequestToMarker(request: any): PinMapa { - return { - urgency: request.urgency, - latitude: request.latitude ?? 0, - longitude: request.longitude ?? 0, - id: request.id, - popup: , - }; - } - - function transformPickupRequestToMarker(point: any): PinMapa { - return { - urgency: point.urgency || 'baja', - latitude: point.latitude ?? 0, - longitude: point.longitude ?? 0, - id: point.id, - popup: , - }; - } - - async function fetchData() { - try { - setLoading(true); - setError(null); - - // 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); - } - - 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]); - } - - const { data: pickupData, error: pickupError } = await pickupQuery.order('created_at', { ascending: false }); - - let allData = []; - if (error) { - console.log('Error fetching solicitudes:', error); - } else { - 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(allData); - } catch (err) { - console.log('Error general:', err); - setError('Error de conexión.'); - } finally { - setLoading(false); - } - } - - fetchData(); - }, [filtroData]); - - if (loading) { - return ( -
-
-
- ); - } - - if (error) { - return ( -
-

{error}

-
- ); - } - - return ( - <> - {/* FILTROS */} -
-

Filtros

-
- - -
-
- -
- -
- - ); + const searchParams = useSearchParams(); + const router = useRouter(); + + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + const [data, setData] = useState([]); + + const updateFilter = (filter: any, value: any) => { + const params = new URLSearchParams(searchParams.toString()); + params.set(filter, value); + router.push(`?${params.toString()}`); + }; + + const [filtroData, setFiltroData] = useState({ + urgencia: searchParams.get('urgencia') || 'todas', + tipoAyuda: searchParams.get('tipoAyuda') || 'todas', + pueblo: searchParams.get('pueblo') || 'todos', + acepta: searchParams.get('acepta') || 'todos', + }); + + const changeDataFilter = (type: any, newFilter: any) => { + setFiltroData((prev) => ({ + ...prev, + [type]: newFilter, + })); + updateFilter(type, newFilter); + }; + + useEffect(() => { + function transformHelpRequestToMarker(request: any): PinMapa { + return { + urgency: request.urgency, + latitude: request.latitude ?? 0, + longitude: request.longitude ?? 0, + id: request.id, + popup: , + }; + } + + function transformPickupRequestToMarker(point: any): PinMapa { + return { + urgency: point.urgency || 'baja', + latitude: point.latitude ?? 0, + longitude: point.longitude ?? 0, + id: point.id, + popup: , + }; + } + + async function fetchData() { + const urlRequests = process.env.NEXT_PUBLIC_BASE_URL + '/api/mapa/solicitudes/?'; + const urlPoints = process.env.NEXT_PUBLIC_BASE_URL + '/api/mapa/puntos/?' + let allData = []; + try { + setLoading(true); + setError(null); + const filter = []; + if (filtroData.tipoAyuda !== 'todas') { + filter.push('type=' + filtroData.tipoAyuda); + } + if (filtroData.urgencia !== 'todas') { + filter.push('urgency=' + filtroData.urgencia); + } + const filterRequestsUrl = urlRequests + filter.join('&'); + const responseRequests = await fetch(filterRequestsUrl); + if (!responseRequests.ok) { + console.log(`Error fetching solicitudes: ${responseRequests.status}`); + } + else { + const { data, count } = await responseRequests.json(); + const markers = data.map(transformHelpRequestToMarker); + allData.push(...(markers || [])); + } + + filter.splice(0, filter.length); + + if (filtroData.acepta !== 'todos') { + filter.push('accepted=' + filtroData.acepta); + } + const filterPointsUrl = urlPoints + filter.join('&'); + const responsePoints = await fetch(filterPointsUrl); + if (!responsePoints.ok) { + console.log(`Error fetching solicitudes: ${responsePoints.status}`); + } + else { + const { data, count } = await responsePoints.json(); + const pickupMarkers = data.map(transformPickupRequestToMarker); + allData.push(...(pickupMarkers || [])); + } + setData(allData); + } catch (err) { + console.log('Error general:', err); + setError('Error de conexión.'); + } finally { + setLoading(false); + } + } + + fetchData(); + }, [filtroData]); + + if (loading) { + return ( +
+
+
+ ); + } + + if (error) { + return ( +
+

{error}

+
+ ); + } + + return ( + <> + {/* FILTROS */} +
+

Filtros

+
+ + +
+
+ +
+ +
+ + ); } diff --git a/src/app/casos-activos/solicitudes/page.tsx b/src/app/casos-activos/solicitudes/page.tsx index 7d4c19b6..ac55357f 100644 --- a/src/app/casos-activos/solicitudes/page.tsx +++ b/src/app/casos-activos/solicitudes/page.tsx @@ -12,174 +12,171 @@ import { HelpRequestData } from '@/types/Requests'; export const dynamic = 'force-dynamic'; export default function SolicitudesPage() { - return ( - - - - ); + return ( + + + + ); } function Solicitudes() { - const { towns } = useTowns(); - const searchParams = useSearchParams(); - const router = useRouter(); - - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - - const [data, setData] = useState([]); - const [currentPage, setCurrentPage] = useState(Number(searchParams.get('page')) || 1); - const [currentCount, setCurrentCount] = useState(0); - - const itemsPerPage = 10; - const numPages = (count: number) => { - return Math.ceil(count / itemsPerPage) || 0; - }; - - const updateFilter = (filter: 'urgencia' | 'tipoAyuda' | 'pueblo' | 'page', value: string | number) => { - const params = new URLSearchParams(searchParams.toString()); - params.set(filter, value.toString()); - router.push(`?${params.toString()}`); - }; - - const [filtroData, setFiltroData] = useState({ - urgencia: searchParams.get('urgencia') || 'todas', - tipoAyuda: searchParams.get('tipoAyuda') || 'todas', - pueblo: searchParams.get('pueblo') || 'todos', - }); - - const changeDataFilter = (type: 'urgencia' | 'tipoAyuda' | 'pueblo', newFilter: string) => { - setFiltroData((prev) => ({ - ...prev, - [type]: newFilter, - })); - updateFilter(type, newFilter); - }; - - function changePage(newPage: number) { - setCurrentPage(newPage); - updateFilter('page', newPage); - } - - useEffect(() => { - async function fetchData() { - try { - setLoading(true); - setError(null); - - // Comenzamos la consulta - const query = supabase.from('help_requests').select('*', { count: 'exact' }).eq('type', 'necesita'); - - // Solo agregar filtro si no es "todos" - if (filtroData.tipoAyuda !== 'todas') { - query.contains('type', [filtroData.tipoAyuda]); - } - - // Solo agregar filtro si no es "todos" - if (filtroData.pueblo !== 'todos') { - query.eq('town', filtroData.pueblo); - } - - // Solo agregar filtro si no es "todas" - if (filtroData.urgencia !== 'todas') { - query.eq('urgency', filtroData.urgencia); - } - 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); - setData([]); - } else { - setData(data || []); - setCurrentCount(count ?? 0); - } - } catch (err) { - console.log('Error general:', err); - setError('Error de conexión.'); - } finally { - setLoading(false); - } - } - - fetchData(); - }, [filtroData, currentPage]); - - if (loading) { - return ( -
-
-
- ); - } - - if (error) { - return ( -
-

{error}

-
- ); - } - - return ( - <> - {/* FILTROS */} -
-

Filtros

-
- - - -
-
-
- {data.length === 0 ? ( -
-

- No se encontraron solicitudes que coincidan con los filtros. -

-
- ) : ( - data.map((caso) => ) - )} -
-
- -
- - ); + const { towns } = useTowns(); + const searchParams = useSearchParams(); + const router = useRouter(); + + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + const [data, setData] = useState([]); + const [currentPage, setCurrentPage] = useState(Number(searchParams.get('page')) || 1); + const [currentCount, setCurrentCount] = useState(0); + + const itemsPerPage = 10; + const numPages = (count: number) => { + return Math.ceil(count / itemsPerPage) || 0; + }; + + const updateFilter = (filter: 'urgencia' | 'tipoAyuda' | 'pueblo' | 'page', value: string | number) => { + const params = new URLSearchParams(searchParams.toString()); + params.set(filter, value.toString()); + router.push(`?${params.toString()}`); + }; + + const [filtroData, setFiltroData] = useState({ + urgencia: searchParams.get('urgencia') || 'todas', + tipoAyuda: searchParams.get('tipoAyuda') || 'todas', + pueblo: searchParams.get('pueblo') || 'todos', + }); + + const changeDataFilter = (type: 'urgencia' | 'tipoAyuda' | 'pueblo', newFilter: string) => { + setFiltroData((prev) => ({ + ...prev, + [type]: newFilter, + })); + updateFilter(type, newFilter); + }; + + function changePage(newPage: number) { + setCurrentPage(newPage); + updateFilter('page', newPage); + } + + useEffect(() => { + async function fetchData() { + const url = process.env.NEXT_PUBLIC_BASE_URL + '/api/solicitudes/?'; + try { + setLoading(true); + setError(null); + const filter = []; + // Solo agregar filtro si no es "todos" + if (filtroData.tipoAyuda !== 'todas') { + filter.push('type=' + filtroData.tipoAyuda); + } + + // Solo agregar filtro si no es "todos" + if (filtroData.pueblo !== 'todos') { + filter.push('town=' + filtroData.pueblo); + } + + // Solo agregar filtro si no es "todas" + if (filtroData.urgencia !== 'todas') { + filter.push('urgency=' + filtroData.urgencia); + } + + 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); + } + } catch (err) { + console.log('Error general:', err); + setError('Error de conexión.'); + } finally { + setLoading(false); + } + } + + fetchData(); + }, [filtroData, currentPage]); + + if (loading) { + return ( +
+
+
+ ); + } + + if (error) { + return ( +
+

{error}

+
+ ); + } + + return ( + <> + {/* FILTROS */} +
+

Filtros

+
+ + + +
+
+
+ {data.length === 0 ? ( +
+

+ No se encontraron solicitudes que coincidan con los filtros. +

+
+ ) : ( + data.map((caso) => ) + )} +
+
+ +
+ + ); } diff --git a/src/components/SolicitudCard.tsx b/src/components/SolicitudCard.tsx index 046d72ad..3bf96b12 100644 --- a/src/components/SolicitudCard.tsx +++ b/src/components/SolicitudCard.tsx @@ -13,187 +13,183 @@ import { useState } from 'react'; import ChangeUrgencyHelpRequest from './ChangeUrgencyHelpRequest'; type SolicitudCardProps = { - caso: HelpRequestData; - showLink?: boolean; - showEdit?: boolean; + caso: HelpRequestData & { special_situations: any }; + showLink?: boolean; + showEdit?: boolean; + more?: boolean; }; -export default function SolicitudCard({ caso, showLink = true, showEdit = false }: SolicitudCardProps) { - const session = useSession(); - const role = useRole(); - const { getTownById } = useTowns(); - const additionalInfo = caso.additional_info as HelpRequestAdditionalInfo; - const special_situations = 'special_situations' in additionalInfo ? additionalInfo.special_situations : undefined; - const isAdmin = role === 'admin'; - const [deleted, setDeleted] = useState(false); - const isMyRequest = session.user?.id && session.user.id === caso.user_id; - const [updateUrgency, setUpdateUrgency] = useState(caso.urgency); - return ( - !deleted && ( -
-
-
-
- -
- - Urgencia: {updateUrgency === 'alta' ? 'Alta' : updateUrgency === 'media' ? 'Media' : 'Baja'} - - #{caso.id} -
-
-
-
- -
- - {caso.status === 'finished' ? 'FINALIZADO' : caso.status === 'progress' ? 'EN PROCESO' : 'ACTIVO'} - -
-
-
-
-

- {caso.description} -

-
-
-
- {caso.town_id && ( -
- - - Pueblo: {getTownById(caso.town_id)?.name || ''} - -
- )} -
- - - Ubicación: {caso.location} - -
- {caso.contact_info && ( -
- - -
- )} - {caso.help_type && ( -
- - - Necesita:{' '} - {Array.isArray(caso.help_type) - ? caso.help_type - .map((tipo) => { - return tiposAyudaOptions[tipo] || tipo; - }) - .join(', ') - : 'Ayuda general'} - -
- )} - {caso.number_of_people && ( -
- - - Personas afectadas: {caso.number_of_people} - -
- )} - {special_situations && ( - <> -
-
- Situaciones especiales: -

{special_situations}

-
- - )} -
-
-
-
-
- - - -
-
-
{caso?.name?.split(' ')[0] || 'Necesita Ayuda'}
- - {new Date(caso.created_at || '').toLocaleDateString() + - ' ' + - new Date(caso.created_at || '').toLocaleTimeString([], { - hour: '2-digit', - minute: '2-digit', - })} - -
-
-
- {isMyRequest && showEdit && ( - - Editar - - )} - {showLink && ( - - Ver solicitud - - )} - - {isAdmin && ( - - )} - {isAdmin && setDeleted(true)} />} -
-
-
- ) - ); +export default function SolicitudCard({ caso, showLink = true, showEdit = false, more }: SolicitudCardProps) { + const session = useSession(); + const role = useRole(); + const { getTownById } = useTowns(); + const isAdmin = role === 'admin'; + const [deleted, setDeleted] = useState(false); + const isMyRequest = session.user?.id && session.user.id === caso.user_id; + const [updateUrgency, setUpdateUrgency] = useState(caso.urgency); + return ( + !deleted && ( +
+
+
+
+ +
+ + Urgencia: {updateUrgency === 'alta' ? 'Alta' : updateUrgency === 'media' ? 'Media' : 'Baja'} + + #{caso.id} +
+
+
+
+ +
+ + {caso.status === 'finished' ? 'FINALIZADO' : caso.status === 'progress' ? 'EN PROCESO' : 'ACTIVO'} + +
+
+
+
+

+ {caso.description} +

+
+
+
+ {caso.town_id && ( +
+ + + Pueblo: {getTownById(caso.town_id)?.name || ''} + +
+ )} +
+ + + Ubicación: {caso.location} + +
+ {caso.contact_info && ( +
+ + +
+ )} + {caso.help_type && ( +
+ + + Necesita:{' '} + {Array.isArray(caso.help_type) + ? caso.help_type + .map((tipo) => { + return tiposAyudaOptions[tipo] || tipo; + }) + .join(', ') + : 'Ayuda general'} + +
+ )} + {caso.number_of_people && ( +
+ + + Personas afectadas: {caso.number_of_people} + +
+ )} + {caso.special_situations && ( + <> +
+
+ Situaciones especiales: +

{caso.special_situations}

+
+ + )} +
+
+
+
+
+ + + +
+
+
{caso?.name?.split(' ')[0] || 'Necesita Ayuda'}
+ + {new Date(caso.created_at || '').toLocaleDateString() + + ' ' + + new Date(caso.created_at || '').toLocaleTimeString([], { + hour: '2-digit', + minute: '2-digit', + })} + +
+
+
+ {isMyRequest && showEdit && ( + + Editar + + )} + {showLink && ( + + {more ? 'Ver solicitud completa' : 'Ver solicitud'} + + )} + + {isAdmin && ( + + )} + {isAdmin && setDeleted(true)} />} +
+
+
+ ) + ); } diff --git a/src/components/auth/SocialButton.tsx b/src/components/auth/SocialButton.tsx index 5b43792b..50e4442b 100644 --- a/src/components/auth/SocialButton.tsx +++ b/src/components/auth/SocialButton.tsx @@ -4,37 +4,37 @@ import { Provider } from '@supabase/auth-js'; import { ReactNode } from 'react'; type SocialButtonProps = { - provider: Provider; - children: ReactNode; - redirectUrl?: string; + provider: Provider; + children: ReactNode; + redirectUrl?: string; }; export default function SocialButton({ provider, redirectUrl, children }: SocialButtonProps) { - const baseUrl = - process.env.NEXT_PUBLIC_ENV === 'production' ? process.env.NEXT_PUBLIC_BASE_URL! : 'http://127.0.0.1:3000'; - console.log(baseUrl + redirectUrl); - const handleLogin = async (provider: Provider) => { - const { data, error } = await supabase.auth.signInWithOAuth({ - provider, - options: { - redirectTo: `${baseUrl + redirectUrl}`, - }, - }); - if (error) { - console.error('Error al iniciar sesión con proveedor:', error.message); - return; - } - if (data?.url) { - return redirect(data.url); - } - }; + const baseUrl = + process.env.NEXT_PUBLIC_ENV === 'production' ? process.env.NEXT_PUBLIC_BASE_URL! : 'http://127.0.0.1:3000'; + console.log(baseUrl + redirectUrl); + const handleLogin = async (provider: Provider) => { + const { data, error } = await supabase.auth.signInWithOAuth({ + provider, + options: { + redirectTo: `${baseUrl + redirectUrl}`, + }, + }); + if (error) { + console.error('Error al iniciar sesión con proveedor:', error.message); + return; + } + if (data?.url) { + return redirect(data.url); + } + }; - return ( - - ); + return ( + + ); } diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx index ed83d57b..822c8369 100644 --- a/src/components/layout/Sidebar.tsx +++ b/src/components/layout/Sidebar.tsx @@ -1,259 +1,287 @@ + 'use client'; -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { usePathname, useRouter } from 'next/navigation'; import Link from 'next/link'; import { - Search, - HeartHandshake, - UserSearch, - Package, - Menu, - X, - AlertCircle, - Home, - Thermometer, - Truck, - Inbox, - Car, - Landmark, - Scale, - MessageCircleQuestion, - CarTaxiFront, + Search, + HeartHandshake, + UserSearch, + Package, + Menu, + X, + AlertCircle, + Home, + Thermometer, + Truck, + Inbox, + Car, + Landmark, + Scale, + MessageCircleQuestion, + CarTaxiFront, } from 'lucide-react'; import UserInfo from '../UserInfo'; import { useSession } from '@/context/SessionProvider'; -import { useQuery } from '@tanstack/react-query'; -import { HelpRequestData } from '@/types/Requests'; -import { helpRequestService } from '@/lib/service'; type SidebarProps = { - isOpen: boolean; - toggleAction: () => void; + isOpen: boolean; + toggleAction: () => void; }; export default function Sidebar({ isOpen, toggleAction }: SidebarProps) { - const router = useRouter(); - const pathname = usePathname(); - const session = useSession(); + const router = useRouter(); + const pathname = usePathname(); + const session = useSession(); + + const [published, setPublished] = useState({ + requests: false, + offers: false + }) + + useEffect(() => { + async function fetchRequests() { + const url = process.env.NEXT_PUBLIC_BASE_URL + '/api/solicitudes/usuario'; + try { + const response = await fetch(url); + if (!response.ok) { + console.log(`Error fetching solicitudes: ${response.status}`); + } else { + const { count } = await response.json(); + if (count > 0) setPublished((prev) => ({ + ...prev, + requests: true, + })); - const userId = session.user?.id; + } + } catch (err) { + console.log('Error general:', err); + } + } - const { data: requests } = useQuery({ - queryKey: ['help_requests', { user_id: userId, type: 'necesita' }], - queryFn: () => helpRequestService.getRequestsByUser(userId), - }); - const { data: offers } = useQuery({ - queryKey: ['help_requests', { user_id: userId, type: 'ofrece' }], - queryFn: () => helpRequestService.getOffersByUser(userId), - }); - const hasRequests = (requests?.length ?? 0) > 0; - const hasOffers = (offers?.length ?? 0) > 0; + async function fetchOffers() { + const url = process.env.NEXT_PUBLIC_BASE_URL + '/api/ofertas/usuario'; + try { + const response = await fetch(url); + if (!response.ok) { + console.log(`Error fetching solicitudes: ${response.status}`); + } else { + const { count } = await response.json(); + if (count > 0) setPublished((prev) => ({ + ...prev, + offers: true, + })); + } + } catch (err) { + console.log('Error general:', err); + } + } + fetchOffers(); + fetchRequests(); + }, [session?.user]); - const menuItems = [ - { - icon: Home, - title: 'Inicio', - path: '/', - color: 'text-gray-600', - isHome: true, - }, - { - icon: AlertCircle, - title: 'Casos Activos', - description: 'Ver todos los casos activos', - path: '/casos-activos/solicitudes', - color: 'text-orange-600', - highlight: true, - }, - { - icon: Inbox, - title: 'Mis solicitudes', - description: 'Edita o elimina tus solicitudes', - path: '/solicitudes', - color: 'text-red-500', - hide: !hasRequests, - }, - { - icon: Inbox, - title: 'Mis ofertas', - description: 'Edita o elimina tus ofertas', - path: '/ofertas', - color: 'text-green-500', - hide: !hasOffers, - }, - { - icon: Thermometer, - title: 'Voluntómetro', - description: 'Medidor de voluntarios por localidad', - path: '/voluntometro', - color: 'text-yellow-500', - }, - { - icon: Search, - title: 'Solicitar Ayuda', - description: 'Si necesitas asistencia', - path: '/solicitar-ayuda', - color: 'text-red-600', - }, - { - icon: HeartHandshake, - title: 'Ofrecer Ayuda', - description: 'Si puedes ayudar a otros', - path: '/ofrecer-ayuda', - color: 'text-green-600', - }, - { - icon: UserSearch, - title: 'Desaparecidos', - description: 'Reportar o buscar', - path: '/personas-animales-desaparecidos', - color: 'text-purple-600', - }, - { - icon: Package, - title: 'Punto de Recogida', - description: 'Gestionar donaciones', - path: '/punto-recogida', - color: 'text-blue-600', - }, - { - icon: Truck, - title: 'Puntos de Entrega', - description: 'Para transportistas y logística', - path: '/puntos-entrega', - color: 'text-gray-800', - }, - { - icon: Scale, - title: 'Servicio Notarial', - description: 'Servicio notarial gratuito', - path: 'https://valencia.notariado.org/portal/-/20241031-servicio-notarial-de-ayuda-gratuito-para-los-afectados-por-la-dana-noticia-p%C3%BAblica-', - color: 'text-indigo-600', - isHref: true, - }, - { - icon: Landmark, - title: 'Reclamar a Consorcio', - description: 'Seguro de riesgos extraordinarios', - path: 'https://www.consorseguros.es/ambitos-de-actividad/seguros-de-riesgos-extraordinarios/solicitud-de-indemnizacion', - color: 'text-pink-600', - isHref: true, - }, - { - icon: MessageCircleQuestion, - title: 'Ayuda Psicológica', - description: 'Conecta con psicólogos voluntarios', - path: 'https://ayudana.org/', - color: 'text-teal-600', - isHref: true, - }, - ]; + const menuItems = [ + { + icon: Home, + title: 'Inicio', + path: '/', + color: 'text-gray-600', + isHome: true, + }, + { + icon: AlertCircle, + title: 'Casos Activos', + description: 'Ver todos los casos activos', + path: '/casos-activos/solicitudes', + color: 'text-orange-600', + highlight: true, + }, + { + icon: Inbox, + title: 'Mis solicitudes', + description: 'Edita o elimina tus solicitudes', + path: '/solicitudes', + color: 'text-red-500', + hide: !published.requests, + }, + { + icon: Inbox, + title: 'Mis ofertas', + description: 'Edita o elimina tus ofertas', + path: '/ofertas', + color: 'text-green-500', + hide: !published.offers, + }, + { + icon: Thermometer, + title: 'Voluntómetro', + description: 'Medidor de voluntarios por localidad', + path: '/voluntometro', + color: 'text-yellow-500', + }, + { + icon: Search, + title: 'Solicitar Ayuda', + description: 'Si necesitas asistencia', + path: '/solicitar-ayuda', + color: 'text-red-600', + }, + { + icon: HeartHandshake, + title: 'Ofrecer Ayuda', + description: 'Si puedes ayudar a otros', + path: '/ofrecer-ayuda', + color: 'text-green-600', + }, + { + icon: UserSearch, + title: 'Desaparecidos', + description: 'Reportar o buscar', + path: '/personas-animales-desaparecidos', + color: 'text-purple-600', + }, + { + icon: Package, + title: 'Punto de Recogida', + description: 'Gestionar donaciones', + path: '/punto-recogida', + color: 'text-blue-600', + }, + { + icon: Truck, + title: 'Puntos de Entrega', + description: 'Para transportistas y logística', + path: '/puntos-entrega', + color: 'text-gray-800', + }, + { + icon: Scale, + title: 'Servicio Notarial', + description: 'Servicio notarial gratuito', + path: 'https://valencia.notariado.org/portal/-/20241031-servicio-notarial-de-ayuda-gratuito-para-los-afectados-por-la-dana-noticia-p%C3%BAblica-', + color: 'text-indigo-600', + isHref: true, + }, + { + icon: Landmark, + title: 'Reclamar a Consorcio', + description: 'Seguro de riesgos extraordinarios', + path: 'https://www.consorseguros.es/ambitos-de-actividad/seguros-de-riesgos-extraordinarios/solicitud-de-indemnizacion', + color: 'text-pink-600', + isHref: true, + }, + { + icon: MessageCircleQuestion, + title: 'Ayuda Psicológica', + description: 'Conecta con psicólogos voluntarios', + path: 'https://ayudana.org/', + color: 'text-teal-600', + isHref: true, + }, + ]; - return ( - <> - {/* Quitamos el overlay con fondo negro */} - {isOpen &&
} + return ( + <> + {/* Quitamos el overlay con fondo negro */} + {isOpen &&
} - {/* Toggle button for mobile */} - + {/* Toggle button for mobile */} + - {/* Sidebar */} -
- {/* Logo or title */} -
- -

Ajuda Dana

- -
+ > + {/* Logo or title */} +
+ +

Ajuda Dana

+ +
- {/* Menu items - Contenedor con scroll */} - + {/* Menu items - Contenedor con scroll */} + - {/* User info and login */} -
- { - if (window.innerWidth < 768) toggleAction(); - }} - /> -
+ {/* User info and login */} +
+ { + if (window.innerWidth < 768) toggleAction(); + }} + /> +
- {/* Toggle button for desktop */} - -
- - ); -} + aria-label={isOpen ? 'Contraer menú' : 'Expandir menú'} + > + + +
+ + ); +} \ No newline at end of file diff --git a/src/lib/supabase/serverrole.ts b/src/lib/supabase/serverrole.ts index a4affaea..c2291b8d 100644 --- a/src/lib/supabase/serverrole.ts +++ b/src/lib/supabase/serverrole.ts @@ -1,24 +1,22 @@ 'use server'; -import { createServerClient } from '@supabase/ssr'; -import { cookies } from 'next/headers'; -import { Database } from '@/types/database'; +import { createClient } from '@supabase/supabase-js'; export async function createServerRoleClient() { - const cookieStore = await cookies(); - return createServerClient(process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.SUPABASE_SERVICE_ROLE!, { - cookies: { - getAll() { - return cookieStore.getAll(); - }, - setAll(cookiesToSet) { - try { - cookiesToSet.forEach(({ name, value, options }) => cookieStore.set(name, value, options)); - } catch { - // The `setAll` method was called from a Server Component. - // This can be ignored if you have middleware refreshing - // user sessions. - } - }, - }, - }); + if (!process.env.NEXT_PUBLIC_SUPABASE_URL || !process.env.SUPABASE_SERVICE_ROLE) { + throw new Error('Missing database credentials'); + } + + return createClient( + process.env.NEXT_PUBLIC_SUPABASE_URL, + process.env.SUPABASE_SERVICE_ROLE, + { + auth: { + autoRefreshToken: false, + persistSession: false + }, + db: { + schema: 'public' + } + } + ); } \ No newline at end of file