diff --git a/package-lock.json b/package-lock.json index 30d7b4e6..63a5e8d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@supabase/ssr": "^0.5.1", "@supabase/supabase-js": "^2.46.1", "@tanstack/react-query": "^5.59.19", + "babel-plugin-react-compiler": "19.0.0-beta-63b359f-20241101", "deck.gl": "^9.0.34", "leaflet": "^1.9.4", "lucide-react": "^0.454.0", @@ -3497,6 +3498,15 @@ "npm": ">=6" } }, + "node_modules/babel-plugin-react-compiler": { + "version": "19.0.0-beta-63b359f-20241101", + "resolved": "https://registry.npmjs.org/babel-plugin-react-compiler/-/babel-plugin-react-compiler-19.0.0-beta-63b359f-20241101.tgz", + "integrity": "sha512-qrmTHJP3O2kGbtL7kuySX3Lmk+5/4ZR1rHr8QhKa0GzKbmpAUGrTeWOg0NCI5t+QUfKKizxIO1+t0HsZW9x4vQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.19.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "dev": true, diff --git a/src/app/casos-activos/ofertas/page.tsx b/src/app/casos-activos/ofertas/page.tsx index d1b8f5de..6064a573 100644 --- a/src/app/casos-activos/ofertas/page.tsx +++ b/src/app/casos-activos/ofertas/page.tsx @@ -82,7 +82,7 @@ function Ofertas() { console.log('Error fetching solicitudes:', error); setData([]); } else { - setData(data || []); + setData((data as HelpRequestData[]) || []); setCurrentCount(count ?? 0); } } catch (err) { @@ -140,7 +140,7 @@ function Ofertas() {

) : ( - data.map((caso) => ) + data.map((caso) => ) )}
diff --git a/src/app/casos-activos/solicitudes/page.tsx b/src/app/casos-activos/solicitudes/page.tsx index 26b1f368..80d8ae0e 100644 --- a/src/app/casos-activos/solicitudes/page.tsx +++ b/src/app/casos-activos/solicitudes/page.tsx @@ -1,6 +1,6 @@ 'use client'; -import { Suspense, useEffect, useState, useCallback, useMemo, ChangeEventHandler } from 'react'; +import { Suspense, useEffect, useState, useCallback, ChangeEventHandler } from 'react'; import { supabase } from '@/lib/supabase/client'; import SolicitudCard from '@/components/SolicitudCard'; import Pagination from '@/components/Pagination'; @@ -74,7 +74,7 @@ function Solicitudes() { const handleToggleChange: ChangeEventHandler = useCallback( (e) => changeDataFilter('soloSinAsignar', `${e.target.checked}`), - [], + [changeDataFilter], ); useEffect(() => { @@ -116,7 +116,7 @@ function Solicitudes() { console.log('Error fetching solicitudes:', error); setData([]); } else { - setData(data || []); + setData((data as HelpRequestData[]) || []); setCurrentCount(count ?? 0); } } catch (err) { @@ -190,15 +190,13 @@ function Solicitudes() { ))}
- {/* -
- -
- */} +{/*
+ +
*/}
diff --git a/src/app/ofertas/[id]/page.tsx b/src/app/ofertas/[id]/page.tsx index a3bbd571..e732cf54 100644 --- a/src/app/ofertas/[id]/page.tsx +++ b/src/app/ofertas/[id]/page.tsx @@ -54,7 +54,7 @@ export default function CasoDetalle() { Volver
- + ); } diff --git a/src/app/ofertas/editar/[id]/page.tsx b/src/app/ofertas/editar/[id]/page.tsx index 57c438af..92b783a8 100644 --- a/src/app/ofertas/editar/[id]/page.tsx +++ b/src/app/ofertas/editar/[id]/page.tsx @@ -1,7 +1,7 @@ -import OfferHelp from '@/components/OfferHelp'; import Unauthorized from '@/components/Unauthorized'; import { createClient } from '@/lib/supabase/server'; import { helpRequestService } from '@/lib/service'; +import EditHelpOffer from '@/components/HelpOffers/EditHelpOffer'; export default async function EditarSolicitud({ params }: { params: Promise<{ id: string }> }) { const { id } = await params; @@ -12,14 +12,5 @@ export default async function EditarSolicitud({ params }: { params: Promise<{ id } const numberId = Number(id); const request = await helpRequestService.getOne(numberId); - return ( - - ); + return ; } diff --git a/src/app/ofertas/page.tsx b/src/app/ofertas/page.tsx index 03405fb8..3c837de1 100644 --- a/src/app/ofertas/page.tsx +++ b/src/app/ofertas/page.tsx @@ -1,16 +1,13 @@ 'use client'; -import { useState, useEffect, Suspense } from 'react'; +import { Suspense } from 'react'; import { HeartHandshake } from 'lucide-react'; -import { supabase } from '@/lib/supabase/client'; -import Pagination from '@/components/Pagination'; -import { useRouter, useSearchParams } from 'next/navigation'; -import { tiposAyudaOptions } from '@/helpers/constants'; -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'; +import { useQuery } from '@tanstack/react-query'; +import { helpRequestService } from '@/lib/service'; export default function ListaSolicitudesPage() { return ( @@ -22,92 +19,14 @@ export default function ListaSolicitudesPage() { function ListaSolicitudes() { const session = useSession(); + const userId = session.user?.id; - 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 { towns } = useTowns(); - - const itemsPerPage = 10; - const numPages = (count: number) => { - return Math.ceil(count / itemsPerPage) || 0; - }; - - const updateFilter = (filter: 'urgencia' | 'tipoAyuda' | 'pueblo' | 'page', value: string) => { - 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', + const { data, isLoading, error } = useQuery({ + queryKey: ['help_requests', { user_id: userId, type: 'ofrece' }], + queryFn: () => helpRequestService.getOffersByUser(userId), }); - 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.toString()); - } - useEffect(() => { - async function fetchData() { - try { - setLoading(true); - setError(null); - - // Comenzamos la consulta - const query = supabase - .from('help_requests') - .select('*', { count: 'exact' }) - .eq('type', 'ofrece') - .contains('additional_info', { email: session.user?.email }); - // Solo agregar filtro si no es "todos" - if (filtroData.pueblo !== 'todos') { - query.eq('town_id', filtroData.pueblo); - } - - // Solo agregar filtro si no es "todas" - if (filtroData.urgencia !== 'todas') { - query.eq('urgency', filtroData.urgencia); - } - - // 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 || count === null) { - console.log('Error fetching solicitudes:', error); - setData([]); - } else { - setData(data || []); - setCurrentCount(count); - } - } catch (err) { - console.log('Error general:', err); - setError('Error de conexión.'); - } finally { - setLoading(false); - } - } - - fetchData(); - }, [filtroData, currentPage]); - - if (loading) { + if (isLoading) { return (
@@ -115,10 +34,10 @@ function ListaSolicitudes() { ); } - if (error) { + if (error || !data) { return (
-

{error}

+

{error?.message}

); } @@ -126,53 +45,11 @@ function ListaSolicitudes() { return ( <>
- {/* FILTROS */} -
-

Filtros

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

- {filtroData.urgencia === 'todas' && filtroData.tipoAyuda === 'todas' && filtroData.pueblo === 'todos' - ? 'No se encontraron solicitudes de ayuda correspondientes a tu cuenta.' - : 'No se encontraron solicitudes que coincidan con los filtros.'} + No se encontraron solicitudes de ayuda correspondientes a tu cuenta.

) : ( - data.map((caso) => ) + data.map((caso) => ) )}
-
- -
); diff --git a/src/app/ofrecer-ayuda/page.tsx b/src/app/ofrecer-ayuda/page.tsx index c2f4a3a6..4ef3528e 100644 --- a/src/app/ofrecer-ayuda/page.tsx +++ b/src/app/ofrecer-ayuda/page.tsx @@ -1,22 +1,5 @@ -'use client'; -import OfferHelp from '@/components/OfferHelp'; -import { supabase } from '@/lib/supabase/client'; -import { useEffect, useState } from 'react'; +import CreateHelpOffer from '@/components/HelpOffers/CreateHelpOffer'; export default function OfrecerAyuda() { - const [session, setSession] = useState(null); - - useEffect(() => { - supabase.auth.getSession().then(({ data: { session } }: any) => { - setSession(session); - }); - }, []); - - return session ? ( - - ) : ( -
-
-
- ); + return ; } diff --git a/src/app/punto-recogida/page.tsx b/src/app/punto-recogida/page.tsx index 00b9bcf2..71eaa620 100644 --- a/src/app/punto-recogida/page.tsx +++ b/src/app/punto-recogida/page.tsx @@ -3,7 +3,7 @@ import { useState, useCallback, useEffect, FormEvent } from 'react'; import { supabase } from '@/lib/supabase/client'; import { MapPin, Phone, Package, House, Contact, Megaphone } from 'lucide-react'; -import AddressAutocomplete from '@/components/AddressAutocomplete'; +import AddressAutocomplete, { AddressDetails } from '@/components/AddressAutocomplete'; import { isValidPhone } from '@/helpers/utils'; import { PhoneInput } from '@/components/input/PhoneInput'; import { CollectionPointData, CollectionPointInsert } from '@/types/DataPoints'; @@ -220,7 +220,7 @@ export default function PuntosRecogida() {
{ + onSelect={(address: AddressDetails) => { setFormData((prev) => ({ ...prev, location: address.fullAddress, diff --git a/src/app/puntos-entrega/page.tsx b/src/app/puntos-entrega/page.tsx index 5ea18b2b..822e7b68 100644 --- a/src/app/puntos-entrega/page.tsx +++ b/src/app/puntos-entrega/page.tsx @@ -3,7 +3,7 @@ import { useState, useEffect, FormEvent } from 'react'; import { supabase } from '@/lib/supabase/client'; import { Truck, MapPin, Phone, Mail, Calendar, Package } from 'lucide-react'; -import AddressAutocomplete from '@/components/AddressAutocomplete'; +import AddressAutocomplete, { AddressDetails } from '@/components/AddressAutocomplete'; import { DeliveryPointData, DeliveryPointInsert, isCoordinates } from '@/types/DataPoints'; export default function PuntosEntrega() { @@ -226,7 +226,7 @@ export default function PuntosEntrega() {
{ + onSelect={(address: AddressDetails) => { setFormData((prev) => ({ ...prev, location: address.fullAddress, diff --git a/src/app/solicitar-ayuda/_components/Form/FormContainer.tsx b/src/app/solicitar-ayuda/_components/Form/FormContainer.tsx deleted file mode 100644 index 88861c64..00000000 --- a/src/app/solicitar-ayuda/_components/Form/FormContainer.tsx +++ /dev/null @@ -1,218 +0,0 @@ -'use client'; - -import React, { FormEvent, useCallback, useMemo, useState } from 'react'; - -import { FormRenderer } from './FormRenderer'; -import { FormData, Status } from '../types'; -import { helpRequestService, townService } from '@/lib/service'; -import { formatPhoneNumber, isValidPhone, removeUrls } from '@/helpers/utils'; -import { Database } from '@/types/database'; -import { Enums } from '@/types/common'; -import { useRouter } from 'next/navigation'; - -import { TIPOS_DE_AYUDA, TIPOS_DE_AYUDA_MAP } from '../constants'; -import { useSession } from '@/context/SessionProvider'; -import { AddressDescriptor } from '../../../../components/AddressMap'; - -const mapHelpToEnum = (helpTypeMap: FormData['tiposDeAyuda']): Enums['help_type_enum'][] => - Array.from(helpTypeMap).reduce( - (acc, [id, isSelected]) => { - if (isSelected) { - const value = TIPOS_DE_AYUDA_MAP.get(id); - if (!value) { - return acc; - } - return acc.concat(value.enum); - } - return acc; - }, - [] as Enums['help_type_enum'][], - ); - -export function FormContainer({ session }: any) { - const router = useRouter(); - - const userId = session.user?.id; - - const [formData, setFormData] = useState({ - nombre: session?.user?.user_metadata?.full_name || session?.user?.user_metadata?.nombre || ''.split(' ')[0], - coordinates: null, - tiposDeAyuda: new Map(TIPOS_DE_AYUDA.map(({ id }) => [id, false])), - numeroDePersonas: undefined, - descripcion: '', - urgencia: 'alta', - situacionEspecial: '', - contacto: session?.user?.user_metadata?.telefono || '', - consentimiento: false, - email: session?.user?.user_metadata?.email || '', - ubicacion: '', - town: '', - }); - - const [status, setStatus] = useState({ - isSubmitting: false, - error: null, - success: false, - }); - - const handleSubmit = useCallback( - async (e: FormEvent) => { - e.preventDefault(); - - /* Form validation */ - if (!formData.coordinates) { - alert('Elige una ubicacion valida'); - return; - } - - if (!formData.consentimiento) { - alert('Debe aceptar el consentimiento para enviar la solicitud'); - return; - } - - if (!isValidPhone(formData.contacto)) { - alert('El teléfono de contacto no es válido.'); - return; - } - - if (!isValidPhone(formData.contacto)) { - alert('El teléfono de contacto no es válido.'); - return; - } - - setStatus({ isSubmitting: true, error: null, success: false }); - - try { - const latitude = String(formData.coordinates.lat); - const longitude = String(formData.coordinates.lng); - - const { data: townResponse, error: townError } = await townService.createIfNotExists(formData.town); - if (townError) throw townError; - - const helpRequestData: Database['public']['Tables']['help_requests']['Insert'] = { - type: 'necesita', - name: formData.nombre.split(' ')[0], - location: formData.ubicacion, - latitude: formData.coordinates ? parseFloat(latitude) : null, - longitude: formData.coordinates ? parseFloat(longitude) : null, - help_type: mapHelpToEnum(formData.tiposDeAyuda), - description: removeUrls(formData.descripcion), - urgency: formData.urgencia, - number_of_people: formData.numeroDePersonas || 1, - contact_info: formatPhoneNumber(formData.contacto), - additional_info: { - special_situations: formData.situacionEspecial || null, - consent: true, - email: formData.email, - }, - town_id: townResponse[0].id, - status: 'active', - user_id: userId, - }; - - await helpRequestService.createRequest(helpRequestData); - - // Limpiar formulario - setFormData({ - nombre: '', - coordinates: null, - tiposDeAyuda: new Map(), - numeroDePersonas: undefined, - descripcion: '', - urgencia: 'alta', - situacionEspecial: '', - contacto: '', - consentimiento: false, - email: '', - ubicacion: '', - town: '', - }); - - setStatus({ isSubmitting: false, error: null, success: true }); - setStatus((prev) => ({ ...prev, success: false })); - router.push('/casos-activos/solicitudes'); - } catch (error: any) { - console.error('Error al enviar solicitud:', error.message); - setStatus({ - isSubmitting: false, - error: `Error al enviar la solicitud: ${error.message}`, - success: false, - }); - } - }, - [userId, formData, router], - ); - - const handleInputElementChange: React.ChangeEventHandler = useCallback((e) => { - const { name, value, type, checked } = e.target; - setFormData((prev) => ({ - ...prev, - [name]: type === 'checkbox' ? checked : value, - })); - }, []); - - const handleTextAreaElementChange: React.ChangeEventHandler = useCallback((e) => { - const { name, value } = e.target; - setFormData((formData) => ({ - ...formData, - [name]: value, - })); - }, []); - - const handleSelectElementChange: React.ChangeEventHandler = useCallback((e) => { - const { name, value } = e.target; - setFormData((prev) => ({ - ...prev, - [name]: value, - })); - }, []); - - const handleNewAddressDescriptor = useCallback((addressDescriptor: AddressDescriptor) => { - setFormData((prev) => ({ - ...prev, - town: addressDescriptor.town, - ubicacion: addressDescriptor.address, - coordinates: addressDescriptor.coordinates, - })); - }, []); - - const handlePhoneChange = useCallback((phoneNumber: string) => { - setFormData((formData) => ({ - ...formData, - contacto: phoneNumber, - })); - }, []); - - const handleHelpTypeChange: React.ChangeEventHandler = useCallback((event) => { - const { id, checked } = event.target; - - setFormData((formData) => { - const prevHelp = formData.tiposDeAyuda; - const newHelp = new Map([...prevHelp]); - newHelp.set(parseInt(id), checked); - return { ...formData, tiposDeAyuda: newHelp }; - }); - }, []); - - const selectedHelp = useMemo(() => formData.tiposDeAyuda, [formData]); - - return ( - - ); -} diff --git a/src/app/solicitar-ayuda/_components/Form/FormRenderer.tsx b/src/app/solicitar-ayuda/_components/Form/FormRenderer.tsx deleted file mode 100644 index e4e3154d..00000000 --- a/src/app/solicitar-ayuda/_components/Form/FormRenderer.tsx +++ /dev/null @@ -1,209 +0,0 @@ -'use client'; -import React from 'react'; -import { Check } from 'lucide-react'; -import AddressMap, { AddressDescriptor } from '../../../../components/AddressMap'; -import { PhoneInput } from '@/components/input/PhoneInput'; -import AddressAutocomplete from '@/components/AddressAutocomplete.js'; -import { TIPOS_DE_AYUDA } from '../constants'; -import { TipoDeAyudaInputRenderer } from '../TipoDeAyudaInputRenderer'; -import { FormData, HelpCategory, Status } from '../types'; -import { LimitedTextarea } from '@/components/input/LimitedTextarea'; - -type FormRendererProps = { - status: Status; - formData: FormData; - isUserLoggedIn: boolean; - selectedHelp: Map; - handleSubmit: React.FormEventHandler; - handlePhoneChange: (phoneNumber: string) => void; - handleNewAddressDescriptor: (addressDescriptor: AddressDescriptor) => void; - handleSituacionEspecialChange: React.ChangeEventHandler; - handleUrgencyChange: React.ChangeEventHandler; - handleDescriptionChange: React.ChangeEventHandler; - handleTipoAyudaChange: React.ChangeEventHandler; - handleNameChange: React.ChangeEventHandler; - handleEmailChange: React.ChangeEventHandler; - handleNumberPeopleChange: React.ChangeEventHandler; - handleConsentChange: React.ChangeEventHandler; -}; - -export function FormRenderer({ - handleSubmit, - status, - formData, - isUserLoggedIn, - handlePhoneChange, - handleNewAddressDescriptor, - handleSituacionEspecialChange, - handleUrgencyChange, - handleDescriptionChange, - handleTipoAyudaChange, - handleNameChange, - handleEmailChange, - handleNumberPeopleChange, - handleConsentChange, - selectedHelp, -}: FormRendererProps) { - return ( - <> - {status.error && ( -
-

{status.error}

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

Solicitar Ayuda

- -
-
-
- - -
- -
- {/* - MANTENIDO EN CASO DE RE UTILIZAR EN EL FUTURO - ACTUALMENTE NO APARECERA DE NINGUNA FORMA - */} - {!isUserLoggedIn && ( -
- - -

- {isUserLoggedIn - ? 'Se utilizará para que puedas eliminar o editar la información de tu solicitud' - : 'Se utilizará para que puedas actualizar tu solicitud y marcarla como completada. Para realizar cambios, deberás registrarte con el mismo email'} -

-
- )} - -
- -
- {TIPOS_DE_AYUDA.map(({ id, label }) => ( - - ))} -
-
- -
- - -
- -
- - -
- -
- - -
- -
- -