Reputation: 1727
I have JSON data which has structure as follows:
data = [
{
"id": 100,
"floorplans": [
{
"bhk": 1,
...some other fields
},
{
"bhk": 3,
...some other fields
},
{
"bhk": 2,
...some other fields
}
],
"possession_date": "2016-08-21"
},
{
"id": 200,
"floorplans": [
{
"bhk": 1.5,
...some other fields
},
{
"bhk": 1,
...some other fields
},
{
"bhk": 2.5,
...some other fields
}
],
"possession_date": "2017-08-21"
},
{
"id": 300,
"floorplans": [
{
"bhk": 1,
...some other fields
},
{
"bhk": 4,
...some other fields
},
{
"bhk": 2,
...some other fields
}
],
"possession_date": "2018-08-21"
}]
Now above data is getting stored inside filterOptions array. Now filterOptions example:
filterOptions ["Ready", 2, 4, 1] -> this means filter all the data which has 2,4,1 BHK included and also that data which has possession_date < current date
filterOptions ["Under construction", 3] -> this means filter all the data which has 3 BHK included and also that data which has possession_date > current date
So I have the code as follows:
Note: I am using .slice() because I am comparing date of form YYYY-MM-DD
.
function checkStatus(options, date) {
console.log("Status: ", options)
const currentTime = moment().format();
let d1 = Date.parse(currentTime.slice(0,10));
let d2 = Date.parse(date.slice(0,10));
if(options.includes("Ready")){
if(d1 > d2)
return true;
} else if(options.includes("Under construction")){
if(d1 < d2)
return true;
}
}
var display_filtered_projects = data.filter(
(item) => item.floorplans.some(val => filterOptions.includes(val.bhk))
&& checkStatus(filterOptions, item.possession_date));
console.log("display_filtered_projects: ", display_filtered_projects);
If I remove checkStatus(filterOptions, item.possession_date)
then the filter works perfect but only for BHK type. Now I have to combine it with date how can I do that ?
Upvotes: 0
Views: 1711
Reputation: 207
I recommend to use separate filter lists. (Based on discussion with you in Discord)
import moment from 'moment'
import React from 'react'
import ReactDOM from 'react-dom'
const FIELD_DATE = `possession_date`
const yourMegaListFromStackoverflow = [
{
"id": 100,
"floorplans": [
{
"bhk": 1,
},
{
"bhk": 3,
},
{
"bhk": 2,
}
],
"possession_date": "2016-08-21"
},
{
"id": 200,
"floorplans": [
{
"bhk": 1.5,
},
{
"bhk": 1,
},
{
"bhk": 2.5,
}
],
"possession_date": "2017-08-21"
},
{
"id": 300,
"floorplans": [
{
"bhk": 1,
},
{
"bhk": 4,
},
{
"bhk": 2,
}
],
"possession_date": "2018-08-21"
}
]
const statusType = {
'READY': `READY`,
'UNDER_CONSTRUCTION': `UNDER_CONSTRUCTION`,
}
const statusMap = {
[statusType.READY]: `Ready to move`,
[statusType.UNDER_CONSTRUCTION]: `Under Construction`,
}
const statusList = Object.keys(statusMap)
const FilterStatus = (props) => {
const {
activeList = [],
onClick,
} = props
return statusList.map((name) => (
<div
key={name}
style={{ fontWeight: activeList.includes(name) && `bold` }}
onClick={() => onClick({ name })}
>
{statusMap[name]}
</div>
))
}
const typeType = {
'UNO': `UNO`,
'DOS': `DOS`,
'TRES': `TRES`,
'TRES_PLUS': `TRES_PLUS`,
}
const typeMap = {
[typeType.UNO]: `1 BHK`,
[typeType.DOS]: `2 BHK`,
[typeType.TRES]: `3 BHK`,
[typeType.TRES_PLUS]: `3+ BHK`,
}
const typeFilterMap = {
[typeType.UNO]: (value) => value === 1,
[typeType.DOS]: (value) => value === 2,
[typeType.TRES]: (value) => value === 3,
[typeType.TRES_PLUS]: (value) => value >= 3,
}
const typeList = Object.keys(typeMap)
const FilterType = (props) => {
const {
activeList = [],
onClick,
} = props
return typeList.map((name) => (
<div
key={name}
style={{ fontWeight: activeList.includes(name) && `bold` }}
onClick={() => onClick({ name })}
>
{typeMap[name]}
</div>
))
}
const App = () => {
const [filterStatusList, filterStatusListSet] = React.useState([])
const [filterTypeList, filterTypeListSet] = React.useState([])
const onFilterStatusClick = React.useCallback(({ name }) => {
filterStatusList.includes(name)
? filterStatusListSet([])
: filterStatusListSet([name])
})
const onFilterTypeClick = React.useCallback(({ name }) => {
filterTypeList.includes(name)
? filterTypeListSet(filterTypeList.filter((value) => value !== name))
: filterTypeListSet([...filterTypeList, name])
})
const list = React.useMemo(
() => {
const now = Date.now()
return yourMegaListFromStackoverflow.filter((doc) => {
const date = moment(doc[FIELD_DATE]).format(`x`)
const isStatusOk = filterStatusList.includes(statusType.READY)
? now > date
: filterStatusList.includes(statusType.UNDER_CONSTRUCTION)
&& now < date
return isStatusOk
&& doc.floorplans.some(
({ bhk }) => filterTypeList.some(
(name) => typeFilterMap[name](bhk)
)
)
})
},
[filterStatusList, filterTypeList]
)
return <>
<FilterStatus
activeList={filterStatusList}
onClick={onFilterStatusClick}
/>
<FilterType
activeList={filterTypeList}
onClick={onFilterTypeClick}
/>
{list.map((doc) => (
<div key={doc.id}>{doc.id}</div>
))}
</>
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
Upvotes: 2
Reputation: 510
you can modify your filter logic to:
let filterData = data.filter(
a => a.floorplans.some(e => temp.includes(e.bhk))
&& checkStatus(temp[2], a.possession_date)
);
.
.
.
function checkStatus(status, date) {
if (status === 'Ready') {
return new Date(date) < Date.now();
} else {
return Date.now() < new Date(date);
}
}
EDIT
Assuming you only want to check for 'Ready'
in the temp array:
let filterData = data.filter(
a => a.floorplans.some(e => temp.includes(e.bhk))
&& checkStatus(temp, a.possession_date)
);
.
.
.
function checkStatus(temporaryData, date) {
if (temporaryData.indexOf('Ready') !== -1) {
return new Date(date) < Date.now();
} else {
return Date.now() < new Date(date);
}
}
EDIT 2
in the display_filtered_projects.push(x);
part, I am not sure if you are expecting y
otherwise. The catch here is that if data
contains repeated results, they would end up being added repeatedly. I have updated code to use Set to solve this.
var data = [{
"id": 100,
"floorplans": [{
"bhk": 1,
},
{
"bhk": 3,
},
{
"bhk": 2,
}
],
"possession_date": "2016-08-21"
},
{
"id": 200,
"floorplans": [{
"bhk": 1.5,
},
{
"bhk": 1,
},
{
"bhk": 2.5,
}
],
"possession_date": "2017-08-21"
},
{
"id": 300,
"floorplans": [{
"bhk": 1,
},
{
"bhk": 4,
},
{
"bhk": 2,
}
],
"possession_date": "2018-08-21"
}
]
var filterOptions = ["Ready", 2];
function checkStatus(options, date) {
// console.log("Status: ", options)
let d1 = Date.now();
let d2 = new Date(date);
if (options.includes("Ready")) {
if (d1 > d2)
return true;
} else if (options.includes("Under construction")) {
if (d1 < d2)
return true;
} else {
return true;
}
}
var display_filtered_projects = new Set();
data.filter(
(item) => checkStatus(filterOptions, item.possession_date)
).forEach(x => x.floorplans.forEach(y => {
if (filterOptions.includes(y.bhk)) {
display_filtered_projects.add(x);
}
}));
console.log("display_filtered_projects: ", Array.from(display_filtered_projects));
The additional problem here is that your date logic which I have reused would return nothing if the project status wasn't part of your input. So maybe in that case, you just want to return true for all. I've updated the code accordingly.
Upvotes: 2