From 253741d08a1ea2823dad6c29b3d9dd728fc1bcc7 Mon Sep 17 00:00:00 2001 From: Roberto Milla Martinez Date: Thu, 7 Nov 2024 19:18:17 +0100 Subject: [PATCH 01/10] feat: fixed endpoint problems --- .env.example | 2 +- src/app/api/address/route.ts | 13 +- .../_components/Form/FormContainer.tsx | 60 +++---- .../_components/Form/FormRenderer.tsx | 35 ++-- src/app/solicitar-ayuda/_components/types.ts | 5 +- src/components/AddressMap.tsx | 50 ++---- src/components/RequestHelp.js | 97 ++++------- src/components/map/GeolocationMap.tsx | 155 +++++++++++------- src/lib/service.ts | 13 ++ 9 files changed, 215 insertions(+), 215 deletions(-) diff --git a/.env.example b/.env.example index 8b8552c1..229b7206 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,4 @@ NEXT_PUBLIC_SUPABASE_URL= NEXT_PUBLIC_SUPABASE_ANON_KEY= -API_KEY= +GEOCODING_API_KEY= diff --git a/src/app/api/address/route.ts b/src/app/api/address/route.ts index bd5dc153..d9a72115 100644 --- a/src/app/api/address/route.ts +++ b/src/app/api/address/route.ts @@ -14,6 +14,8 @@ const mapsTranslationToDbTowns: { [key: string]: string } = { Alcudia: "L'Alcúdia", Guadasuar: 'Guadassuar', València: 'Valencia', + Almusafes: 'Almussafes', + Montroi: 'Montroy', }; const GOOGLE_URL = `https://maps.googleapis.com/maps/api/geocode/json?key=${process.env.API_KEY}&latlng=`; @@ -64,8 +66,15 @@ export async function POST(request: NextRequest) { } try { - const response = await fetch(`${GOOGLE_URL}${body.latitude},${body.longitude}`); - const extractedData = extractAddressAndTown(await response.json()); + const response = await fetch(`${GOOGLE_URL}${body.latitude},${body.longitude}`).then((value) => value.json()); + + if (response.error_message) { + return Response.json({ + error: response.error_message, + }); + } + + const extractedData = extractAddressAndTown(response); return Response.json(extractedData); } catch (exception) { diff --git a/src/app/solicitar-ayuda/_components/Form/FormContainer.tsx b/src/app/solicitar-ayuda/_components/Form/FormContainer.tsx index ce94b157..a5805a6d 100644 --- a/src/app/solicitar-ayuda/_components/Form/FormContainer.tsx +++ b/src/app/solicitar-ayuda/_components/Form/FormContainer.tsx @@ -1,17 +1,18 @@ 'use client'; -import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; import { FormRenderer } from './FormRenderer'; import { FormData, Status } from '../types'; import { formatPhoneNumber, isValidPhone } from '@/helpers/utils'; -import { helpRequestService } from '@/lib/service'; +import { helpRequestService, locationService, townService } from '@/lib/service'; 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 { LngLat } from '@/components/map/GeolocationMap'; const mapHelpToEnum = (helpTypeMap: FormData['tiposDeAyuda']): Enums['help_type_enum'][] => Array.from(helpTypeMap).reduce( @@ -33,8 +34,7 @@ export function FormContainer() { const session = useSession(); const [formData, setFormData] = useState({ - nombre: session?.user?.user_metadata?.full_name.split(" ")[0]|| '', - ubicacion: '', + nombre: session?.user?.user_metadata?.full_name || '', coordinates: null, tiposDeAyuda: new Map(TIPOS_DE_AYUDA.map(({ id }) => [id, false])), numeroDePersonas: undefined, @@ -43,18 +43,9 @@ export function FormContainer() { situacionEspecial: '', contacto: session?.user?.user_metadata?.telefono || '', consentimiento: false, - pueblo: '', email: session?.user?.user_metadata?.email || '', }); - useEffect(() => { - console.log('Component mounted'); - }, []); - - useEffect(() => { - console.log('formData changed: ', formData); - }, [formData]); - const [status, setStatus] = useState({ isSubmitting: false, error: null, @@ -66,8 +57,8 @@ export function FormContainer() { e.preventDefault(); /* Form validation */ - if (!formData.ubicacion) { - alert('La ubicación es un campo obligatorio'); + if (!formData.coordinates) { + alert('Elige una ubicacion valida'); return; } @@ -89,12 +80,23 @@ export function FormContainer() { setStatus({ isSubmitting: true, error: null, success: false }); try { + const latitude = String(formData.coordinates.lat); + const longitude = String(formData.coordinates.lng); + + const { address, town, error } = await locationService.getFormattedAddress(longitude, latitude); + if (!address || !town || error) { + throw { message: `Error inesperado con la api de google: ${error}` }; + } + + const { data: townResponse, error: townError } = await townService.createIfNotExists(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(formData.coordinates.lat) : null, - longitude: formData.coordinates ? parseFloat(formData.coordinates.lng) : null, + name: formData.nombre, + location: address, + latitude: formData.coordinates ? parseFloat(latitude) : null, + longitude: formData.coordinates ? parseFloat(longitude) : null, help_type: mapHelpToEnum(formData.tiposDeAyuda), description: formData.descripcion, urgency: formData.urgencia, @@ -105,7 +107,7 @@ export function FormContainer() { consent: true, email: formData.email, }, - town_id: parseInt(formData.pueblo), + town_id: townResponse[0].id, status: 'active', }; @@ -114,7 +116,6 @@ export function FormContainer() { // Limpiar formulario setFormData({ nombre: '', - ubicacion: '', coordinates: null, tiposDeAyuda: new Map(), numeroDePersonas: undefined, @@ -122,7 +123,6 @@ export function FormContainer() { urgencia: 'alta', situacionEspecial: '', contacto: '', - pueblo: '', consentimiento: false, email: '', }); @@ -131,7 +131,7 @@ export function FormContainer() { setStatus((prev) => ({ ...prev, success: false })); router.push('/casos-activos/solicitudes'); } catch (error: any) { - console.log('Error al enviar solicitud:', error.message); + console.error('Error al enviar solicitud:', error.message); setStatus({ isSubmitting: false, error: `Error al enviar la solicitud: ${error.message}`, @@ -166,18 +166,11 @@ export function FormContainer() { })); }, []); - const handleAddressSelection = useCallback((address: any) => { + const handleCoordinatesChange = useCallback((lngLat: LngLat) => { setFormData((formData) => ({ ...formData, - ubicacion: address.fullAddress, - coordinates: address.coordinates - ? { - lat: address.coordinates.lat, - lng: address.coordinates.lon, - } - : null, + coordinates: lngLat ?? null, })); - console.log('address: ', address); }, []); const handlePhoneChange = useCallback((phoneNumber: string) => { @@ -210,14 +203,13 @@ export function FormContainer() { isUserLoggedIn={Boolean(session?.user)} handleConsentChange={handleInputElementChange} handleEmailChange={handleInputElementChange} - handleAddressSelection={handleAddressSelection} + handleCoordinatesChange={handleCoordinatesChange} handleDescriptionChange={handleTextAreaElementChange} handleNameChange={handleInputElementChange} handleNumberPeopleChange={handleInputElementChange} handlePhoneChange={handlePhoneChange} handleSituacionEspecialChange={handleTextAreaElementChange} handleTipoAyudaChange={handleHelpTypeChange} - handleTownChange={handleSelectElementChange} handleUrgencyChange={handleSelectElementChange} handleSubmit={handleSubmit} status={status} diff --git a/src/app/solicitar-ayuda/_components/Form/FormRenderer.tsx b/src/app/solicitar-ayuda/_components/Form/FormRenderer.tsx index e0196b30..1daba848 100644 --- a/src/app/solicitar-ayuda/_components/Form/FormRenderer.tsx +++ b/src/app/solicitar-ayuda/_components/Form/FormRenderer.tsx @@ -3,11 +3,11 @@ import React from 'react'; import { Check } from 'lucide-react'; import { PhoneInput } from '@/components/PhoneInput'; -import AddressAutocomplete from '@/components/AddressAutocomplete.js'; import { TIPOS_DE_AYUDA } from '../constants'; import { TipoDeAyudaInputRenderer } from '../TipoDeAyudaInputRenderer'; import { FormData, HelpCategory, Status } from '../types'; -import { TownSelector } from '../TownSelector'; +import AddressMap from '../../../../components/AddressMap'; +import { LngLat } from '@/components/map/GeolocationMap'; type FormRendererProps = { status: Status; @@ -16,11 +16,10 @@ type FormRendererProps = { selectedHelp: Map; handleSubmit: React.FormEventHandler; handlePhoneChange: (phoneNumber: string) => void; - handleAddressSelection: (address: string) => void; + handleCoordinatesChange: (lngLat: LngLat) => void; handleSituacionEspecialChange: React.ChangeEventHandler; handleUrgencyChange: React.ChangeEventHandler; handleDescriptionChange: React.ChangeEventHandler; - handleTownChange: React.ChangeEventHandler; handleTipoAyudaChange: React.ChangeEventHandler; handleNameChange: React.ChangeEventHandler; handleEmailChange: React.ChangeEventHandler; @@ -34,11 +33,10 @@ export function FormRenderer({ formData, isUserLoggedIn, handlePhoneChange, - handleAddressSelection, + handleCoordinatesChange, handleSituacionEspecialChange, handleUrgencyChange, handleDescriptionChange, - handleTownChange, handleTipoAyudaChange, handleNameChange, handleEmailChange, @@ -84,23 +82,11 @@ export function FormRenderer({ className="w-full p-2 border rounded focus:ring-2 focus:ring-green-500 focus:border-green-500" />

- {isUserLoggedIn ? 'Se utilizará para que puedas eliminar o editar la información de tu solicitud' + {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'}

-
- - -

- Incluya todos los detalles posibles para poder localizarle (campo obligatorio) -

-
@@ -166,8 +152,13 @@ export function FormRenderer({ placeholder="Personas mayores, niños pequeños, personas con movilidad reducida, necesidades médicas, mascotas..." />
- {/* Pueblos */} - + +
+ + +
{/* Consentimiento */}
diff --git a/src/app/solicitar-ayuda/_components/types.ts b/src/app/solicitar-ayuda/_components/types.ts index 94bb4470..4a6b1391 100644 --- a/src/app/solicitar-ayuda/_components/types.ts +++ b/src/app/solicitar-ayuda/_components/types.ts @@ -1,5 +1,6 @@ import { Town as SupabaseTown } from '@/types/Town'; import { Enums } from '@/types/common'; +import { LngLat } from '@/components/map/GeolocationMap'; export type FormData = { nombre: string; @@ -9,10 +10,8 @@ export type FormData = { descripcion: string; urgencia: string; situacionEspecial: string; - pueblo: string; consentimiento: boolean; - ubicacion: string; - coordinates: any; + coordinates: LngLat | null; tiposDeAyuda: Map; }; diff --git a/src/components/AddressMap.tsx b/src/components/AddressMap.tsx index d0b4de94..9ab4d5a6 100644 --- a/src/components/AddressMap.tsx +++ b/src/components/AddressMap.tsx @@ -3,47 +3,27 @@ import GeoLocationMap, { LngLat } from '@/components/map/GeolocationMap'; import { useState } from 'react'; -export type AddressDescriptopr = { address: string; town: string; coordinates: LngLat }; -export type AddressAndTownCallback = (addressAndTown: AddressDescriptopr) => void; export type AddressMapProps = { - onNewAddressCallback: AddressAndTownCallback; + onNewCoordinatesCallback: (lngLat: LngLat) => void; }; -export default function AddressMap({ onNewAddressCallback }: AddressMapProps) { - const [address, setAddress] = useState(''); - const [town, setTown] = useState(''); - - const onNewPosition = async (lngLat: LngLat) => { - if (address !== '') { - return; - } - - const response = await fetch('/api/address', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - longitude: lngLat.lng, - latitude: lngLat.lat, - }), - }).then((res) => res.json()); - - setAddress(response.address); - setTown(response.town); - if (typeof onNewAddressCallback === 'function') { - onNewAddressCallback({ address: response.address, town: response.town, coordinates: lngLat }); - } - }; +export default function AddressMap({ onNewCoordinatesCallback }: AddressMapProps) { + const [status, setStatus] = useState('unknown'); return (
- - {/* Address */} - setAddress(e.target.value)} - className="w-full p-2 border rounded focus:ring-2 focus:ring-green-500 focus:border-green-500" + {/* Mensaje de error */} + {(status === 'denied' || status === 'prompt') && ( +
+

Debes activar la ubicación para que podamos localizarte

+
+ )} + { + setStatus(permission); + }} + onNewPositionCallback={(lngLat) => {}} + onNewCenterCallback={onNewCoordinatesCallback} />
); diff --git a/src/components/RequestHelp.js b/src/components/RequestHelp.js index 0e861d76..de8a810a 100644 --- a/src/components/RequestHelp.js +++ b/src/components/RequestHelp.js @@ -5,13 +5,14 @@ import { AlertTriangle, Check, Mail } from 'lucide-react'; import AddressAutocomplete from '@/components/AddressAutocomplete'; import { mapToIdAndLabel, tiposAyudaOptions } from '@/helpers/constants'; import { formatPhoneNumber, isValidPhone } from '@/helpers/utils'; -import { helpRequestService } from '@/lib/service'; +import { helpRequestService, locationService, townService } from '@/lib/service'; import { PhoneInput } from '@/components/PhoneInput'; import Image from 'next/image'; import { useRouter } from 'next/navigation'; import { useTowns } from '../context/TownProvider'; import { CallCenterLink } from '@/components/CallCenterLink'; +import AddressMap from './AddressMap'; export default function RequestHelp({ data = {}, @@ -57,8 +58,9 @@ export default function RequestHelp({ const handleSubmit = async (e) => { e.preventDefault(); - if (!formData.ubicacion) { - alert('La ubicación es un campo obligatorio'); + /* Form validation */ + if (!formData.coordinates) { + alert('Elige una ubicacion valida'); return; } @@ -75,12 +77,25 @@ export default function RequestHelp({ setStatus({ isSubmitting: true, error: null, success: false }); try { + const latitude = String(formData.coordinates.lat); + const longitude = String(formData.coordinates.lng); + + debugger; + + const { address, town, error } = await locationService.getFormattedAddress(longitude, latitude); + if (!address || !town || error) { + throw { message: `Error inesperado con la api de google: ${error}` }; + } + + const { data: townResponse, error: townError } = await townService.createIfNotExists(town); + if (townError) throw townError; + const helpRequestData = { type: 'necesita', name: formData.nombre, - location: formData.ubicacion, - latitude: formData.coordinates ? parseFloat(formData.coordinates.lat) : 3, - longitude: formData.coordinates ? parseFloat(formData.coordinates.lng) : 3, + location: address, + latitude, + longitude, help_type: formData.tiposAyuda, description: formData.descripcion, urgency: formData.urgencia, @@ -91,7 +106,7 @@ export default function RequestHelp({ consent: true, email: formData.email, }, - town_id: formData.pueblo, + town_id: townResponse[0].id, status: formData.status, }; if (submitType === 'create') { @@ -101,7 +116,6 @@ export default function RequestHelp({ } } if (submitType === 'edit') { - console.log('EDITAR'); const { error } = await helpRequestService.editRequest(helpRequestData, id); if (error) { throw new Error(error.message); @@ -128,7 +142,7 @@ export default function RequestHelp({ setStatus((prev) => ({ ...prev, success: false })); router.push(redirect); } catch (error) { - console.log('Error al enviar solicitud:', error.message); + console.error('Error al enviar solicitud:', error.message); setStatus({ isSubmitting: false, error: `Error al enviar la solicitud: ${error.message}`, @@ -260,31 +274,6 @@ export default function RequestHelp({
)} -
- - { - setFormData({ - ...formData, - ubicacion: address.fullAddress, - coordinates: address.coordinates - ? { - lat: address.coordinates.lat, - lng: address.coordinates.lon, - } - : null, - }); - }} - placeholder="Calle, número, piso, ciudad..." - required - /> -

- Incluya todos los detalles posibles para poder localizarle (campo obligatorio) -

-
@@ -357,35 +346,21 @@ export default function RequestHelp({ placeholder="Personas mayores, niños pequeños, personas con movilidad reducida, necesidades médicas, mascotas..." />
- {/* Pueblos */} + {/* Mapa */}
- - + + { + setFormData((prev) => ({ + ...prev, + coordinates: lngLat, + })); + }} + />
+ {/* Consentimiento */}