diff --git a/src/app/api/health/route.js b/src/app/api/health/route.ts similarity index 100% rename from src/app/api/health/route.js rename to src/app/api/health/route.ts diff --git a/src/app/api/ofertas/route.js b/src/app/api/ofertas/route.ts similarity index 100% rename from src/app/api/ofertas/route.js rename to src/app/api/ofertas/route.ts diff --git a/src/app/api/solicitudes/route.js b/src/app/api/solicitudes/route.ts similarity index 91% rename from src/app/api/solicitudes/route.js rename to src/app/api/solicitudes/route.ts index be9591fa..1636fc06 100644 --- a/src/app/api/solicitudes/route.js +++ b/src/app/api/solicitudes/route.ts @@ -1,4 +1,4 @@ -import { NextResponse } from 'next/server'; +import { NextRequest, NextResponse } from 'next/server'; import { createClient } from '@/lib/supabase/server'; export async function GET() { @@ -16,7 +16,7 @@ export async function GET() { return Response.json({ registeredPost }); } -export async function POST(request) { +export async function POST(request: NextRequest) { try { // Obtener los datos del formulario (multipart/form-data) const formData = await request.formData(); diff --git a/src/app/api/user/route.js b/src/app/api/user/route.ts similarity index 100% rename from src/app/api/user/route.js rename to src/app/api/user/route.ts diff --git a/src/app/auth/page.js b/src/app/auth/page.tsx similarity index 100% rename from src/app/auth/page.js rename to src/app/auth/page.tsx diff --git a/src/app/casos-activos/ofertas/page.js b/src/app/casos-activos/ofertas/page.js index c2a78d1b..007cfcf3 100644 --- a/src/app/casos-activos/ofertas/page.js +++ b/src/app/casos-activos/ofertas/page.js @@ -141,7 +141,7 @@ export default function Ofertas() { ) : ( - data.map((caso) => ) + data.map((caso) => ) )}
diff --git a/src/app/oferta/page.js b/src/app/oferta/page.js deleted file mode 100644 index 9007f44f..00000000 --- a/src/app/oferta/page.js +++ /dev/null @@ -1,21 +0,0 @@ -import { ArrowLeft } from 'lucide-react'; -import Link from 'next/link'; - -export default function Oferta() { - return ( -
-
- - - Volver - -
-
-

No se encontró la oferta.

-
-
- ); -} diff --git a/src/app/oferta/[id]/page.js b/src/app/ofertas/[id]/page.tsx similarity index 67% rename from src/app/oferta/[id]/page.js rename to src/app/ofertas/[id]/page.tsx index 80de85ca..a3bbd571 100644 --- a/src/app/oferta/[id]/page.js +++ b/src/app/ofertas/[id]/page.tsx @@ -1,37 +1,31 @@ 'use client'; -import { useEffect, useState } from 'react'; + import { useParams } from 'next/navigation'; -import { supabase } from '@/lib/supabase/client'; import { ArrowLeft } from 'lucide-react'; import OfferCard from '@/components/OfferCard'; -import { useTowns } from '@/context/TownProvider'; +import { useQuery } from '@tanstack/react-query'; +import { HelpRequestData } from '@/types/Requests'; +import { helpRequestService } from '@/lib/service'; export default function CasoDetalle() { const params = useParams(); const { id } = params; - const [caso, setCaso] = useState(null); - const [loading, setLoading] = useState(true); - const { towns } = useTowns(); - useEffect(() => { - async function fetchCaso() { - const { data, error } = await supabase.from('help_requests').select('*').eq('id', id).single(); - if (error) { - console.error('Error fetching caso:', error); - } else { - setCaso(data); - } - setLoading(false); - } - fetchCaso(); - }, [id]); - if (loading) { + const { + data: request, + isLoading, + error, + } = useQuery({ + queryKey: ['help_requests', { id: id }], + queryFn: () => helpRequestService.getOne(Number(id)), + }); + if (isLoading) { return (
); } - if (!caso) { + if (error || request === undefined) { return (
@@ -60,7 +54,7 @@ export default function CasoDetalle() { Volver
- +
); } diff --git a/src/app/ofertas/editar/[id]/page.js b/src/app/ofertas/editar/[id]/page.js deleted file mode 100644 index c2401786..00000000 --- a/src/app/ofertas/editar/[id]/page.js +++ /dev/null @@ -1,40 +0,0 @@ -import { createClient } from '@/lib/supabase/server'; -import OfferHelp from '@/components/OfferHelp'; -import Unauthorized from '@/components/Unauthorized'; - -const getRequest = async (id) => { - const supabase = await createClient(); - const { data: session, sessionError } = await supabase.auth.getUser(); - if (sessionError || !session?.user) { - return 'unauthorized'; - } - const { data, error } = await supabase - .from('help_requests') - .select('*') - .eq('id', id) - .eq('type', 'ofrece') - .contains('additional_info', { email: session.user.email }) - .single(); - if (error) { - throw new Error(error); - } - return data; -}; - -export default async function EditarSolicitud({ params }) { - const { id } = await params; - const request = await getRequest(id); - if (request === 'unauthorized') { - return ; - } - return ( - - ); -} diff --git a/src/app/ofertas/editar/[id]/page.tsx b/src/app/ofertas/editar/[id]/page.tsx new file mode 100644 index 00000000..57c438af --- /dev/null +++ b/src/app/ofertas/editar/[id]/page.tsx @@ -0,0 +1,25 @@ +import OfferHelp from '@/components/OfferHelp'; +import Unauthorized from '@/components/Unauthorized'; +import { createClient } from '@/lib/supabase/server'; +import { helpRequestService } from '@/lib/service'; + +export default async function EditarSolicitud({ params }: { params: Promise<{ id: string }> }) { + const { id } = await params; + const supabase = await createClient(); + const { data: session } = await supabase.auth.getUser(); + if (session.user === null) { + return ; + } + const numberId = Number(id); + const request = await helpRequestService.getOne(numberId); + return ( + + ); +} diff --git a/src/app/ofertas/page.js b/src/app/ofertas/page.tsx similarity index 87% rename from src/app/ofertas/page.js rename to src/app/ofertas/page.tsx index a3fac973..38c01f7e 100644 --- a/src/app/ofertas/page.js +++ b/src/app/ofertas/page.tsx @@ -10,6 +10,7 @@ import { useTowns } from '@/context/TownProvider'; import { useSession } from '@/context/SessionProvider'; import OfferCard from '@/components/OfferCard'; import Link from 'next/link'; +import { HelpRequestData } from '@/types/Requests'; export default function ListaSolicitudes() { const session = useSession(); @@ -17,20 +18,20 @@ export default function ListaSolicitudes() { const searchParams = useSearchParams(); const router = useRouter(); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); + 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 [data, setData] = useState([]); + const [currentPage, setCurrentPage] = useState(Number(searchParams.get('page')) || 1); + const [currentCount, setCurrentCount] = useState(0); const { towns } = useTowns(); const itemsPerPage = 10; - const numPages = (count) => { + const numPages = (count: number) => { return Math.ceil(count / itemsPerPage) || 0; }; - const updateFilter = (filter, value) => { + const updateFilter = (filter: 'urgencia' | 'tipoAyuda' | 'pueblo' | 'page', value: string) => { const params = new URLSearchParams(searchParams.toString()); params.set(filter, value); router.push(`?${params.toString()}`); @@ -41,7 +42,7 @@ export default function ListaSolicitudes() { pueblo: searchParams.get('pueblo') || 'todos', }); - const changeDataFilter = (type, newFilter) => { + const changeDataFilter = (type: 'urgencia' | 'tipoAyuda' | 'pueblo', newFilter: string) => { setFiltroData((prev) => ({ ...prev, [type]: newFilter, @@ -49,9 +50,9 @@ export default function ListaSolicitudes() { updateFilter(type, newFilter); }; - function changePage(newPage) { + function changePage(newPage: number) { setCurrentPage(newPage); - updateFilter('page', newPage); + updateFilter('page', newPage.toString()); } useEffect(() => { async function fetchData() { @@ -64,7 +65,7 @@ export default function ListaSolicitudes() { .from('help_requests') .select('*', { count: 'exact' }) .eq('type', 'ofrece') - .contains('additional_info', { email: session.user.email }); + .contains('additional_info', { email: session.user?.email }); // Solo agregar filtro si no es "todos" if (filtroData.pueblo !== 'todos') { query.eq('town_id', filtroData.pueblo); @@ -80,7 +81,7 @@ export default function ListaSolicitudes() { .range((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage - 1) .order('created_at', { ascending: false }); - if (error) { + if (error || count === null) { console.log('Error fetching solicitudes:', error); setData([]); } else { @@ -174,16 +175,7 @@ export default function ListaSolicitudes() {
) : ( - data.map((caso) => ( - - )) + data.map((caso) => ) )}
diff --git a/src/app/ofrecer-ayuda/page.js b/src/app/ofrecer-ayuda/page.tsx similarity index 100% rename from src/app/ofrecer-ayuda/page.js rename to src/app/ofrecer-ayuda/page.tsx diff --git a/src/app/personas-animales-desaparecidos/page.js b/src/app/personas-animales-desaparecidos/page.tsx similarity index 98% rename from src/app/personas-animales-desaparecidos/page.js rename to src/app/personas-animales-desaparecidos/page.tsx index d309ee4e..f2adeb18 100644 --- a/src/app/personas-animales-desaparecidos/page.js +++ b/src/app/personas-animales-desaparecidos/page.tsx @@ -1,4 +1,4 @@ -// personas-animales-desaparecidos/page.js +// personas-animales-desaparecidos/page.tsx import { Users, PawPrint, Car, UserSearch } from 'lucide-react'; diff --git a/src/app/personas-desaparecidas/page.js b/src/app/personas-desaparecidas/page.js deleted file mode 100644 index f972f404..00000000 --- a/src/app/personas-desaparecidas/page.js +++ /dev/null @@ -1,346 +0,0 @@ -'use client'; - -import { useState } from 'react'; -import { UserSearch, AlertCircle, Phone, Check } from 'lucide-react'; -import { supabase } from '@/lib/supabase/client'; - -export default function PersonaDesaparecida() { - const [formData, setFormData] = useState({ - // Datos personales - nombreCompleto: '', - edad: '', - genero: '', - altura: '', - complexion: '', - - // Descripción física - descripcionFisica: '', - ropa: '', - - // Último avistamiento - lugarUltimaVez: '', - fechaUltimaVez: '', - horaUltimaVez: '', - circunstancias: '', - - // Información médica - condicionesMedicas: '', - - // Datos del reportante - nombreReportante: '', - parentesco: '', - telefonoContacto: '', - telefonoAlternativo: '', - - consentimiento: false, - }); - - const [status, setStatus] = useState({ - isSubmitting: false, - error: null, - success: false, - }); - - // En el handleSubmit, reemplazar con: - - const handleSubmit = async (e) => { - e.preventDefault(); - - if (!formData.consentimiento) { - alert('Debe aceptar el consentimiento para enviar el reporte'); - return; - } - - setStatus({ isSubmitting: true, error: null, success: false }); - - try { - // Preparar datos para Supabase - const missingPersonData = { - name: formData.nombreCompleto, - age: parseInt(formData.edad), - gender: formData.genero, - height: formData.altura ? parseInt(formData.altura) : null, - description: formData.descripcionFisica, - last_seen_location: formData.lugarUltimaVez, - last_seen_date: new Date(`${formData.fechaUltimaVez}T${formData.horaUltimaVez}`).toISOString(), - reporter_name: formData.nombreReportante, - reporter_contact: formData.telefonoContacto, - status: 'active', - medical_conditions: formData.condicionesMedicas || null, - clothing_description: formData.ropa, - additional_info: { - circumstances: formData.circunstancias, - secondary_contact: formData.telefonoAlternativo, - relationship: formData.parentesco, - }, - }; - - // Insertar directamente usando supabase - const { error } = await supabase.from('missing_persons').insert([missingPersonData]); - - if (error) throw error; - - // Limpiar formulario - setFormData({ - nombreCompleto: '', - edad: '', - genero: '', - altura: '', - complexion: '', - descripcionFisica: '', - ropa: '', - lugarUltimaVez: '', - fechaUltimaVez: '', - horaUltimaVez: '', - circunstancias: '', - condicionesMedicas: '', - nombreReportante: '', - parentesco: '', - telefonoContacto: '', - telefonoAlternativo: '', - consentimiento: false, - }); - - setStatus({ isSubmitting: false, error: null, success: true }); - setTimeout(() => setStatus((prev) => ({ ...prev, success: false })), 5000); - } catch (error) { - console.error('Error al enviar el reporte:', error); - setStatus({ - isSubmitting: false, - error: 'Error al enviar el reporte. Por favor, inténtalo de nuevo.', - success: false, - }); - } - }; - - return ( -
- {/* Banner de emergencia 112 */} -
-
- -
-

- - LLAME PRIMERO AL 112 -

-

- Si la desaparición es reciente o sospecha que la persona está en peligro inmediato, contacte primero con - el 112. -

-
-
-
- - {status.error && ( -
-

{status.error}

-
- )} - - {/* Formulario principal */} -
-
- -

Reportar Persona Desaparecida

-
- -
- {/* Datos personales */} -
-

Datos de la Persona Desaparecida

- -
-
- - setFormData({ ...formData, nombreCompleto: e.target.value })} - className="w-full p-2 border rounded focus:ring-2 focus:ring-purple-500" - /> -
- -
- - setFormData({ ...formData, edad: e.target.value })} - className="w-full p-2 border rounded focus:ring-2 focus:ring-purple-500" - /> -
-
- -
-
- - -
- -
- - setFormData({ ...formData, altura: e.target.value })} - className="w-full p-2 border rounded focus:ring-2 focus:ring-purple-500" - /> -
-
-
- - {/* Descripción física y ropa */} -
-

Descripción

- -
- -