3

I'm building a NextJs web app where the user can explore various stores near him. I'm using google places Api to select location from the places dropdown. Based on the location the stores are displayed. Rather typing the location I want a buttons with city name which on click will set the location of that city.

Here search bar and get current location button is present along with city button

Location.tsx

 useEffect(()=>{
    if(!getLocation?.formattedAddress){
        setLocation(true);
        setHasLoction(false);
    }else{
        setHasLoction(true);
    }
},[])

 function changeLocation(data:any){
   
    var location=JSON.stringify(data);
    console.log(data?.formattedAddress);
    document.getElementById("location_id").value=data?.formattedAddress;
    setLocation(data?.formattedAddress);

    if(location){
        setHasLoction(true);
        // closeLocation(); 
    }

    var {query ,pathname} = router;
    var pathname="/"+router.locale+pathname
    
    router.push(
    {
        pathname,
        query: query,
    },
    {
        pathname,
        query: query,
    },
    );
    handleLocation()
}


return (

<div style={{zIndex: 1000}}  className={`absolute  flex flex-col  w-full z-1000 inset-0 shadow-lg transform ml-0 duration-200 ease-in 
                                ${location ? ' translate-y-0 ' : '-translate-y-full' }  transform border-5 bg-gray-100 h-screen lg:h-100 xl:h-110 2xl:h-110 overflow-y-hidden overflow-hidden `}>
                                  
                                   <div className='border-red-400 flex w-full'>
                                       <div className='flex flex-col'>
                                           <h4 className='block lg:hidden text-sm sm:text-2xl md:text-3xl lg:text-4xl mx-4 sm:mx-16 md:mx-16 mt-8 text-magenta font-heading font-semibold'>
                                               
                                           </h4>
                                           <div className=''>
                                               <p className=' lg:hidden flex mx-4  sm:mx-16 md:mx-16 mt-4 font-semibold items-center text-xs 
                                               xs+:text-sm sm:text-sm text-gray-700'>
                                                   Local stores </p>
                                               <p className=' lg:hidden flex mx-4 sm:mx-16 md:mx-16 mt-0 font-semibold items-center text-xs 
                                                              xs+:text-sm sm:text-sm text-gray-700'>
                                                  </p>
                                           </div>
                                       </div>
                                       <img src='/drop-down.jpg' className='hidden lg:block md:relative object-fill md:object-contain'/>
                                   </div>

                                    {/* <HeaderMiddle/> */}
                        <div className='flex items-center justify-between mx-auto mt-20 '>

                            {/* <Logo className="mx-auto" /> */}
                            <img src="/icons/x.svg"  onClick = {closeLocation} 
                                 style={{zIndex: 100}} className={`${(hasLocation)?"":"hidden"} absolute font-bold z-40 h-7 w-7 top-2 bg-gold  rounded-full right-2 2xl:top-5 text-gray-400 2xl:h-8  2xl:w-8 2xl:right-7 `}/>
                            {/* <h2 className=' font-md text-md sm:text-lg md:text-lg lg:text-lg 2xl:text-2xl '> Get best deals in your name </h2> */}

                        </div>
                        {/* <img src='/drop-down.jpg' className='relative   top-0 object-contain'/> */}
                        
                        <div id='location-input' style={{zIndex: 0}} 
                             className='absolute flex flex-col justify-center 
                                   w-full lg:w-full items-center  pt-36  sm:pt-20 md:pt-4 lg:pt-0 space-y-6 ml-0 mx-3 
                                   sm:mx-16 md:ml-16 lg:ml-6 xl:ml-8 2xl:ml-10 lg:mt-80'> 
                                      
                            <div  style = {{zIndex: 1000}}  
                                  className='w-full'> 
                                <GooglePlacesAutocomplete onChange = {changeLocation} 
                                                          address  = 
          {getLocation?.formattedAddress} /> 
                            </div>
    
                            <div style={{zIndex: 1000}}  className='w-full'> 
                                 <GetCurrentLocation onChange = {changeLocation} />  
                            </div>

                        </div>

                        <div className='-mt-10'>
                            <button onClick={setCityLocation}
                            className='p-2 border'>
                                New York
                            </button>
                        </div>
                        
                    {/* <Dialog.Overlay className="fixed inset-0 bg-gray-900 bg- 
    opaname-80 w-full h-full" /> */}
                       
            </div> 

google-places-autocomplete.tsx

import { Autocomplete, useJsApiLoader } from "@react-google-maps/api";
import { Libraries } from "@react-google-maps/api/dist/utils/make-load-script-url";
import { LocationInput } from "@ts-types/generated";
import React, { useState ,useEffect } from "react";
import { useTranslation } from "next-i18next";
import Loader from "@components/ui/loader/loader";
 import { useLocation } from "@contexts/location/location.context";
 import { useCreateLogMutation } from "@data/log/use-create-log.mutation";
 import useOnClickOutside from "@utils/use-click-outside";


const libraries: Libraries = ["places"];
// data,
// data: LocationInput;
 export default function GooglePlacesAutocomplete({address,
   onChange
 }: {
onChange: any;
 address :any
 }) {
 const { t } = useTranslation();
 const [loc,setLocation]=useState(address);
 const { mutate: createLog, isLoading: loading } = useCreateLogMutation();

 const { isLoaded, loadError } = useJsApiLoader({
 id: "google_map_autocomplete",
 googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_MAP_API_KEY!,
 libraries,
 });

  const [autocomplete, setAutocomplete] = React.useState<any>(null);

  const onLoad = React.useCallback(function callback(autocompleteInstance) {
  setAutocomplete(autocompleteInstance);
 }, []);

  const onUnmount = React.useCallback(function callback() {
   setAutocomplete(null);
  }, []);


   const onPlaceChanged = () => {
  const place = autocomplete.getPlace();

  if (!place.geometry || !place.geometry.location) {
    console.log("Returned place contains no geometry");
    return;
  }


  setLocation(place.formatted_address);
  const location: any = {
  lat: place.geometry.location.lat(),
  lng: place.geometry.location.lng(),
  formattedAddress: place.formatted_address,
 };

  for (const component of place.address_components) {
  // @ts-ignore remove once typings fixed
  const componentType = component.types[0];

    switch (componentType) {
    case "postal_code": {
      location["zip"] = component.long_name;
      break;
     }

     case "postal_code_suffix": {
      location["zip"] = `${location?.zip}-${component.long_name}`;
      break;
    }

     case "locality":
      location["city"] = component.long_name;
      break;

     case "administrative_area_level_1": {
       location["state"] = component.short_name;
       break;
    }

     case "country":
      location["country"] = component.long_name;
       break;
   }
 }

 if (onChange) {
    onChange(location);

   createLog({location:location.formattedAddress}, {
    onSuccess: (data: any) => {
        console.log(data)
    },
      onError: (error: any) => {
       
     },
    });
     }
   };

 if (loadError) {
 return <div>{t("common:text-map-cant-load")}</div>;
 }

  return isLoaded ? (
  
   <Autocomplete
    onLoad={onLoad}
    onPlaceChanged={onPlaceChanged}
    onUnmount={onUnmount}
    fields={["address_components", "geometry.location", "formatted_address"]}
    types={["address"]}
    className="flex"
    >

    <input
      type = "text"
      defaultValue={loc}
      style={{borderRadius:"5px"}}
      className="p-3 pl-8  mx-8 w-full  sm:px-8 sm:w-full sm:mx-auto  xmd:mx-4 md:w- 
      full md:mx-auto 
                  2xl:p-3 lg:p-3 lg:mx-auto  lg:w-full 2xl:w-full 2xl:mx-auto font- 
         light
                  focus:border-accent focus:bg-light bg-gray-80
                  outline-none text-xs sm:text-sm md:text-base lg:text-lg 
                border-gray-300 border "
    />

  </Autocomplete >

   ) : (

 <div className="flex">
  <Loader simple={true} className="w-6 h-6" />
 </div>
 );
}
juliomalves
  • 42,130
  • 20
  • 150
  • 146
vinender singh
  • 339
  • 1
  • 3
  • 8

0 Answers0