From 83d89b31ae996a1ec02b89cf3ab78b238408f9e0 Mon Sep 17 00:00:00 2001 From: Kaan Koc Date: Wed, 16 Oct 2024 07:25:01 +0000 Subject: [PATCH] Added AddressSuggestion component to handle address suggestions and autofill in user registration. Reworked form to make everything use input component --- src/app/components/AddressSuggestions.tsx | 137 ++++++++++++++++++++++ src/app/components/Input.tsx | 4 +- src/app/user/register/page.tsx | 119 ++++++++----------- 3 files changed, 190 insertions(+), 70 deletions(-) create mode 100644 src/app/components/AddressSuggestions.tsx diff --git a/src/app/components/AddressSuggestions.tsx b/src/app/components/AddressSuggestions.tsx new file mode 100644 index 0000000..b2ae2e8 --- /dev/null +++ b/src/app/components/AddressSuggestions.tsx @@ -0,0 +1,137 @@ +import React, { useState, useRef, ChangeEvent, useEffect } from 'react'; + +interface AddressSuggestionsProps { + address: string; + setAddress: (address: string) => void; + postcode: string; + setPostcode: (postcode: string) => void; + setCity: (city: string) => void; +} + +const fetchAddressSuggestions = async (query: string): Promise => { + try { + const response = await fetch( + `https://api.dataforsyningen.dk/adgangsadresser/autocomplete?q=${encodeURIComponent(query)}&fuzzy=true` + ); + const data = await response.json(); + return data; + } catch (error) { + console.error('Error fetching address suggestions:', error); + return []; + } +}; + +const fetchCity = async (postcode: string): Promise => { + try { + const response = await fetch(`https://api.dataforsyningen.dk/postnumre?nr=${postcode}`); + const data = await response.json(); + if (data.length > 0) { + return data[0].navn; // Return the city name + } + return null; + } catch (error) { + console.error('Error fetching city:', error); + return null; + } +}; + +const AddressSuggestions: React.FC = ({ address, setAddress, postcode, setPostcode, setCity }) => { + const [addressSuggestions, setAddressSuggestions] = useState([]); + const [showSuggestions, setShowSuggestions] = useState(false); + const suggestionListRef = useRef(null); + + const handleAddressChange = async (e: ChangeEvent) => { + const newValue = e.target.value; + setAddress(newValue); + + if (newValue) { + const suggestions = await fetchAddressSuggestions(newValue); + setAddressSuggestions(suggestions); + setShowSuggestions(true); + } else { + setAddressSuggestions([]); + setShowSuggestions(false); + } + }; + + const handleAddressSelect = async (selectedAddress: any) => { + const adgangsadresse = selectedAddress.adgangsadresse; + if (adgangsadresse) { + const street = [adgangsadresse.vejnavn, adgangsadresse.husnr].filter(Boolean).join(' '); + const postcode = adgangsadresse.postnr || ''; + setAddress(street); + setPostcode(postcode); + setAddressSuggestions([]); + setShowSuggestions(false); + + // Fetch and set the city based on the selected postcode + const cityName = await fetchCity(postcode); + if (cityName) { + setCity(cityName); + } + } + }; + + const handleClickOutside = (event: MouseEvent) => { + if (suggestionListRef.current && !suggestionListRef.current.contains(event.target as Node)) { + setShowSuggestions(false); + } + }; + + useEffect(() => { + document.addEventListener('click', handleClickOutside); + return () => { + document.removeEventListener('click', handleClickOutside); + }; + }, []); + + useEffect(() => { + const fetchAndSetCity = async () => { + if (postcode) { + const cityName = await fetchCity(postcode); + if (cityName) { + setCity(cityName); + } + } + }; + fetchAndSetCity(); + }, [postcode, setCity]); + + return ( +
+ + + {showSuggestions && addressSuggestions.length > 0 && ( +
    + {addressSuggestions.map((suggestion, index) => { + const adgangsadresse = suggestion.adgangsadresse; + if (!adgangsadresse) return null; + + const vejnavn = adgangsadresse.vejnavn || ''; + const husnr = adgangsadresse.husnr || ''; + const postnr = adgangsadresse.postnr || ''; + + return ( +
  • handleAddressSelect(suggestion)} + className="p-2 hover:bg-gray-100 cursor-pointer" + > + {vejnavn} {husnr}, {postnr} +
  • + ); + })} +
+ )} +
+ ); +}; + +export default AddressSuggestions; \ No newline at end of file diff --git a/src/app/components/Input.tsx b/src/app/components/Input.tsx index c9e960c..b0a8f15 100644 --- a/src/app/components/Input.tsx +++ b/src/app/components/Input.tsx @@ -10,7 +10,7 @@ interface InputProps { placeholder?: string; } -const Input: React.FC = ({ id, label, value, setChange, required = false, type = "text", placeholder }) => { +const Input: React.FC = ({ id, label, value, setChange, required = false, type = "text", placeholder}) => { return (