diff --git a/.env.example b/.env.example index c4c451c5..8b8552c1 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,4 @@ NEXT_PUBLIC_SUPABASE_URL= NEXT_PUBLIC_SUPABASE_ANON_KEY= + +API_KEY= diff --git a/src/app/api/address/route.ts b/src/app/api/address/route.ts new file mode 100644 index 00000000..bd5dc153 --- /dev/null +++ b/src/app/api/address/route.ts @@ -0,0 +1,77 @@ +import { NextRequest } from 'next/server'; + +const mapsTranslationToDbTowns: { [key: string]: string } = { + Aldaya: 'Aldaia', + 'Ribarroja de Turia': 'Riba-roja de Túria', + Benetuser: 'Benetusser', + Benetússer: 'Benetusser', + Benetúser: 'Benetusser', + Toris: 'Turís', + Picaña: 'Picanya', + 'La Alcudia': "L'Alcúdia", + 'Lugar Nuevo de la Corona': 'Llocnou de la Corona', + 'Castellón de la Plana': 'Castelló de la Plana', + Alcudia: "L'Alcúdia", + Guadasuar: 'Guadassuar', + València: 'Valencia', +}; + +const GOOGLE_URL = `https://maps.googleapis.com/maps/api/geocode/json?key=${process.env.API_KEY}&latlng=`; + +export type AddressAndTown = { address: string; town: string }; + +function normalizeData({ address, town }: AddressAndTown): AddressAndTown { + const normalizedTown = Object.keys(mapsTranslationToDbTowns).includes(town) ? mapsTranslationToDbTowns[town] : town; + const normalizedAddress = address.replace(town, normalizedTown); + return { address: normalizedAddress, town: normalizedTown }; +} + +function extractAddressAndTown(googleResponse: any) { + // for response refer to documentation: https://developers.google.com/maps/documentation/geocoding/requests-reverse-geocoding + // it returns many due to inaccuracies but they only differ from street number(normally) - we look for a good result - contains sublocality + let town = ''; + let address = ''; + for (const result of googleResponse['results']) { + for (const addressComponent of result['address_components']) { + let localityFound = false; + + // max three, not really a performance issue + for (const type of addressComponent['types']) { + if (type === 'locality') { + localityFound = true; + town = addressComponent['long_name']; + break; + } + } + + if (localityFound) { + address = result['formatted_address']; + + return normalizeData({ address, town }); + } + } + } + + return { address, town }; +} + +export async function POST(request: NextRequest) { + const body = await request.json(); + if (!body.latitude || !body.longitude) { + return Response.json({ + error: 'Latitude and longitude are mandatory fields!', + }); + } + + try { + const response = await fetch(`${GOOGLE_URL}${body.latitude},${body.longitude}`); + const extractedData = extractAddressAndTown(await response.json()); + + return Response.json(extractedData); + } catch (exception) { + console.error(exception); + return Response.json({ + error: 'An error occured calling google - check logs', + }); + } +} diff --git a/src/app/page.tsx b/src/app/page.tsx index 5b8b4e43..47801201 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,6 +1,5 @@ import { AlertCircle, Clock, Cross, Heart, MapPin, Navigation, Package, Thermometer, Users } from 'lucide-react'; -// @ts-expect-error import PhoneNumberDialog from '@/components/auth/PhoneNumberDialog'; import Image from 'next/image'; diff --git a/src/components/AddressAutocomplete.js b/src/components/AddressAutocomplete.js index 70236609..2cabb82c 100644 --- a/src/components/AddressAutocomplete.js +++ b/src/components/AddressAutocomplete.js @@ -3,7 +3,12 @@ import { useState, useEffect, useRef, useCallback } from 'react'; import { MapPin } from 'lucide-react'; -export default function AddressAutocomplete({ onSelect, placeholder = 'Buscar dirección...', initialValue = '' }) { +export default function AddressAutocomplete({ + onSelect, + placeholder = 'Buscar dirección...', + initialValue = '', + required = false, +}) { const [query, setQuery] = useState(initialValue); const [suggestions, setSuggestions] = useState([]); const [isLoading, setIsLoading] = useState(false); @@ -150,6 +155,7 @@ export default function AddressAutocomplete({ onSelect, placeholder = 'Buscar di
{suggestions.map((suggestion, index) => (