Skip to content

Instantly share code, notes, and snippets.

@adrianhajdin
Created November 25, 2021 18:56
Show Gist options
  • Star 47 You must be signed in to star a gist
  • Fork 19 You must be signed in to fork a gist
  • Save adrianhajdin/2fb91c8b6e7b2e64671c85ea4c05cbc9 to your computer and use it in GitHub Desktop.
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>
);
}
@coderakib
Copy link

Thank You very much

@JulianIfesiokwu
Copy link

Thank you so much. I am learning alot from the project.

@fuzzyprogrammer
Copy link

Thank You very much

@dandelg88
Copy link

Thank You so much! Awesome project for learning.

@alienkawsar
Copy link

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.

@Maxgranderford
Copy link

hi

@Josh-millr
Copy link

@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

@jtemia
Copy link

jtemia commented Feb 21, 2022

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.

@Josh-millr
Copy link

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

@sohamm7
Copy link

sohamm7 commented Feb 27, 2022

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?

@sdarnadeem
Copy link

please share the codesandbox link

@SMDSImpacts
Copy link

You are amazing, I pray that someday I get to buy you a cofee

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment