-
-
Save adrianhajdin/2fb91c8b6e7b2e64671c85ea4c05cbc9 to your computer and use it in GitHub Desktop.
import Router from 'next/router'; | |
import Head from 'next/head'; | |
import NProgress from 'nprogress'; | |
import { ChakraProvider } from '@chakra-ui/react'; | |
import Layout from '../components/Layout'; | |
function MyApp({ Component, pageProps }) { | |
NProgress.configure({ showSpinner: false }); | |
Router.events.on('routeChangeStart', () => { | |
NProgress.start(); | |
}); | |
Router.events.on('routeChangeComplete', () => { | |
NProgress.done(); | |
}); | |
return ( | |
<> | |
<Head> | |
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/nprogress/0.2.0/nprogress.min.css' integrity='sha512-42kB9yDlYiCEfx2xVwq0q7hT4uf26FUgSIZBK8uiaEnTdShXjwr8Ip1V4xGJMg3mHkUt9nNuTDxunHF0/EgxLQ==' crossOrigin='anonymous' referrerPolicy='no-referrer' /> | |
</Head> | |
<ChakraProvider> | |
<Layout> | |
<Component {...pageProps} /> | |
</Layout> | |
</ChakraProvider> | |
</> | |
); | |
} | |
export default MyApp; |
export const filterData = [ | |
{ | |
items: [ | |
{ name: 'Buy', value: 'for-sale' }, | |
{ name: 'Rent', value: 'for-rent' }, | |
], | |
placeholder: 'Purpose', | |
queryName: 'purpose', | |
}, | |
{ | |
items: [ | |
{ name: 'Daily', value: 'daily' }, | |
{ name: 'Weekly', value: 'weekly' }, | |
{ name: 'Monthly', value: 'monthly' }, | |
{ name: 'Yearly', value: 'yearly' }, | |
], | |
placeholder: 'Rent Frequency', | |
queryName: 'rentFrequency', | |
}, | |
{ | |
items: [ | |
{ name: '10,000', value: '10000' }, | |
{ name: '20,000', value: '20000' }, | |
{ name: '30,000', value: '30000' }, | |
{ name: '40,000', value: '40000' }, | |
{ name: '50,000', value: '50000' }, | |
{ name: '60,000', value: '60000' }, | |
{ name: '85,000', value: '85000' }, | |
], | |
placeholder: 'Min Price(AED)', | |
queryName: 'minPrice', | |
}, | |
{ | |
items: [ | |
{ name: '50,000', value: '50000' }, | |
{ name: '60,000', value: '60000' }, | |
{ name: '85,000', value: '85000' }, | |
{ name: '110,000', value: '110000' }, | |
{ name: '135,000', value: '135000' }, | |
{ name: '160,000', value: '160000' }, | |
{ name: '185,000', value: '185000' }, | |
{ name: '200,000', value: '200000' }, | |
{ name: '300,000', value: '300000' }, | |
{ name: '400,000', value: '400000' }, | |
{ name: '500,000', value: '500000' }, | |
{ name: '600,000', value: '600000' }, | |
{ name: '700,000', value: '700000' }, | |
{ name: '800,000', value: '800000' }, | |
{ name: '900,000', value: '900000' }, | |
{ name: '1000,000', value: '1000000' }, | |
], | |
placeholder: 'Max Price(AED)', | |
queryName: 'maxPrice', | |
}, | |
{ | |
items: [ | |
{ name: 'Lowest Price', value: 'price-asc' }, | |
{ name: 'Highest Price', value: 'price-des' }, | |
{ name: 'Newest', value: 'date-asc' }, | |
{ name: 'Oldest', value: 'date-desc' }, | |
{ name: 'Verified', value: 'verified-score' }, | |
{ name: 'City Level Score', value: 'city-level-score' }, | |
], | |
placeholder: 'Sort', | |
queryName: 'sort', | |
}, | |
{ | |
items: [ | |
{ name: '1000', value: '1000' }, | |
{ name: '2000', value: '2000' }, | |
{ name: '3000', value: '3000' }, | |
{ name: '4000', value: '4000' }, | |
{ name: '5000', value: '5000' }, | |
{ name: '10000', value: '10000' }, | |
{ name: '20000', value: '20000' }, | |
], | |
placeholder: 'Max Area(sqft)', | |
queryName: 'areaMax', | |
}, | |
{ | |
items: [ | |
{ name: '1', value: '1' }, | |
{ name: '2', value: '2' }, | |
{ name: '3', value: '3' }, | |
{ name: '4', value: '4' }, | |
{ name: '5', value: '5' }, | |
{ name: '6', value: '6' }, | |
{ name: '7', value: '7' }, | |
{ name: '8', value: '8' }, | |
{ name: '9', value: '9' }, | |
{ name: '10', value: '10' }, | |
], | |
placeholder: 'Rooms', | |
queryName: 'roomsMin', | |
}, | |
{ | |
items: [ | |
{ name: '1', value: '1' }, | |
{ name: '2', value: '2' }, | |
{ name: '3', value: '3' }, | |
{ name: '4', value: '4' }, | |
{ name: '5', value: '5' }, | |
{ name: '6', value: '6' }, | |
{ name: '7', value: '7' }, | |
{ name: '8', value: '8' }, | |
{ name: '9', value: '9' }, | |
{ name: '10', value: '10' }, | |
], | |
placeholder: 'Baths', | |
queryName: 'bathsMin', | |
}, | |
{ | |
items: [ | |
{ name: 'Furnished', value: 'furnished' }, | |
{ name: 'Unfurnished', value: 'unfurnished' }, | |
], | |
placeholder: 'Furnish Type', | |
queryName: 'furnishingStatus', | |
}, | |
{ | |
items: [ | |
{ name: 'Apartment', value: '4' }, | |
{ name: 'Townhouses', value: '16' }, | |
{ name: 'Villas', value: '3' }, | |
{ name: 'Penthouses', value: '18' }, | |
{ name: 'Hotel Apartments', value: '21' }, | |
{ name: 'Villa Compound', value: '19' }, | |
{ name: 'Residential Plot', value: '14' }, | |
{ name: 'Residential Floor', value: '12' }, | |
{ name: 'Residential Building', value: '17' }, | |
], | |
placeholder: 'Property Type', | |
queryName: 'categoryExternalID', | |
}, | |
]; | |
export const getFilterValues = (filterValues) => { | |
const { | |
purpose, | |
rentFrequency, | |
categoryExternalID, | |
minPrice, | |
maxPrice, | |
areaMax, | |
roomsMin, | |
bathsMin, | |
sort, | |
locationExternalIDs, | |
} = filterValues; | |
const values = [ | |
{ | |
name: 'purpose', | |
value: purpose, | |
}, | |
{ | |
name: 'rentFrequency', | |
value: rentFrequency, | |
}, | |
{ | |
name: 'minPrice', | |
value: minPrice, | |
}, | |
{ | |
name: 'maxPrice', | |
value: maxPrice, | |
}, | |
{ | |
name: 'areaMax', | |
value: areaMax, | |
}, | |
{ | |
name: 'roomsMin', | |
value: roomsMin, | |
}, | |
{ | |
name: 'bathsMin', | |
value: bathsMin, | |
}, | |
{ | |
name: 'sort', | |
value: sort, | |
}, | |
{ | |
name: 'locationExternalIDs', | |
value: locationExternalIDs, | |
}, | |
{ | |
name: 'categoryExternalID', | |
value: categoryExternalID, | |
}, | |
]; | |
return values; | |
}; |
export async function getServerSideProps({ query }) { | |
const purpose = query.purpose || 'for-rent'; | |
const rentFrequency = query.rentFrequency || 'yearly'; | |
const minPrice = query.minPrice || '0'; | |
const maxPrice = query.maxPrice || '1000000'; | |
const roomsMin = query.roomsMin || '0'; | |
const bathsMin = query.bathsMin || '0'; | |
const sort = query.sort || 'price-desc'; | |
const areaMax = query.areaMax || '35000'; | |
const locationExternalIDs = query.locationExternalIDs || '5002'; | |
const categoryExternalID = query.categoryExternalID || '4'; | |
const data = await fetchApi(`${baseUrl}/properties/list?locationExternalIDs=${locationExternalIDs}&purpose=${purpose}&categoryExternalID=${categoryExternalID}&bathsMin=${bathsMin}&rentFrequency=${rentFrequency}&priceMin=${minPrice}&priceMax=${maxPrice}&roomsMin=${roomsMin}&sort=${sort}&areaMax=${areaMax}`); | |
return { | |
props: { | |
properties: data?.hits, | |
}, | |
}; | |
} | |
export default Search; |
https://bayut-production.s3.eu-central-1.amazonaws.com/image/145426814/33973352624c48628e41f2ec460faba4 | |
assets - https://drive.google.com/drive/folders/1VmohYaB3PHVPrRQ20Ql44HKJaaKhLiEN?usp=sharing |
import { useEffect, useState } from 'react'; | |
import { Flex, Select, Box, Text, Input, Spinner, Icon, Button } from '@chakra-ui/react'; | |
import { useRouter } from 'next/router'; | |
import { MdCancel } from 'react-icons/md'; | |
import Image from 'next/image'; | |
import { filterData, getFilterValues } from '../utils/filterData'; | |
import { baseUrl, fetchApi } from '../utils/fetchApi'; | |
import noresult from '../assets/images/noresult.svg'; | |
export default function SearchFilters() { | |
const [filters] = useState(filterData); | |
const [searchTerm, setSearchTerm] = useState(''); | |
const [locationData, setLocationData] = useState(); | |
const [showLocations, setShowLocations] = useState(false); | |
const [loading, setLoading] = useState(false); | |
const router = useRouter(); | |
const searchProperties = (filterValues) => { | |
const path = router.pathname; | |
const { query } = router; | |
const values = getFilterValues(filterValues) | |
values.forEach((item) => { | |
if(item.value && filterValues?.[item.name]) { | |
query[item.name] = item.value | |
} | |
}) | |
router.push({ pathname: path, query: query }); | |
}; | |
useEffect(() => { | |
if (searchTerm !== '') { | |
const fetchData = async () => { | |
setLoading(true); | |
const data = await fetchApi(`${baseUrl}/auto-complete?query=${searchTerm}`); | |
setLoading(false); | |
setLocationData(data?.hits); | |
}; | |
fetchData(); | |
} | |
}, [searchTerm]); | |
return ( | |
<Flex bg='gray.100' p='4' justifyContent='center' flexWrap='wrap'> | |
{filters?.map((filter) => ( | |
<Box key={filter.queryName}> | |
<Select onChange={(e) => searchProperties({ [filter.queryName]: e.target.value })} placeholder={filter.placeholder} w='fit-content' p='2' > | |
{filter?.items?.map((item) => ( | |
<option value={item.value} key={item.value}> | |
{item.name} | |
</option> | |
))} | |
</Select> | |
</Box> | |
))} | |
<Flex flexDir='column'> | |
<Button onClick={() => setShowLocations(!showLocations)} border='1px' borderColor='gray.200' marginTop='2' > | |
Search Location | |
</Button> | |
{showLocations && ( | |
<Flex flexDir='column' pos='relative' paddingTop='2'> | |
<Input | |
placeholder='Type Here' | |
value={searchTerm} | |
w='300px' | |
focusBorderColor='gray.300' | |
onChange={(e) => setSearchTerm(e.target.value)} | |
/> | |
{searchTerm !== '' && ( | |
<Icon | |
as={MdCancel} | |
pos='absolute' | |
cursor='pointer' | |
right='5' | |
top='5' | |
zIndex='100' | |
onClick={() => setSearchTerm('')} | |
/> | |
)} | |
{loading && <Spinner margin='auto' marginTop='3' />} | |
{showLocations && ( | |
<Box height='300px' overflow='auto'> | |
{locationData?.map((location) => ( | |
<Box | |
key={location.id} | |
onClick={() => { | |
searchProperties({ locationExternalIDs: location.externalID }); | |
setShowLocations(false); | |
setSearchTerm(location.name); | |
}} | |
> | |
<Text cursor='pointer' bg='gray.200' p='2' borderBottom='1px' borderColor='gray.100' > | |
{location.name} | |
</Text> | |
</Box> | |
))} | |
{!loading && !locationData?.length && ( | |
<Flex justifyContent='center' alignItems='center' flexDir='column' marginTop='5' marginBottom='5' > | |
<Image src={noresult} /> | |
<Text fontSize='xl' marginTop='3'> | |
Waiting to search! | |
</Text> | |
</Flex> | |
)} | |
</Box> | |
)} | |
</Flex> | |
)} | |
</Flex> | |
</Flex> | |
); | |
} |
you may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. see https://webpack.js.org/concepts#loaders
I am having this message while importing images in this project.
I don't know what to do. Please help me.
hi
@kawsar441 i think your nextJs is broken, try reinstalling nextJS again in a seperate project folder and import the image again...if it does import properly without the error then all you gotta do is to just move your needed folders (pages, public, styles) over
Hi All,
I was getting the error below, when running npm run dev on my localhost. I googled it and learned that it's invalid API.. please anyone can assist or advise? Thanks.
"Server Error TypeError: Invalid value "undefined" for header "x-rapidapi-key"
This error happened while generating the page. Any console logs will be displayed in the terminal window.
Hi, I'm new to the project video..i realized there is actually no need for the getFilterValues function, the undefined objects takes more memory space and slows down the program... and since we already have the correct query names, we can just use it directly by passing the key and value of the filter directly to the router
42:9 Error: Missing "key" prop for element in iterator react/jsx-key
I am getting this error while deploying ,anybody up there for help?
please share the codesandbox link
You are amazing, I pray that someday I get to buy you a cofee
Thank You so much! Awesome project for learning.