Skip to content

Instantly share code, notes, and snippets.

@gauravkrp
Forked from adrianhajdin/SearchFilters.jsx
Created January 28, 2022 16:25
Show Gist options
  • Save gauravkrp/a4f5300271cc4f7ffa15c8d6338416cb to your computer and use it in GitHub Desktop.
Save gauravkrp/a4f5300271cc4f7ffa15c8d6338416cb 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>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment