Как создать фильтр даты в JavaScript? - PullRequest
0 голосов
/ 25 февраля 2019

У меня есть данные JSON, структура которых выглядит следующим образом:

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"
}]

Теперь данные выше хранятся в массиве filterOptions.Теперь пример filterOptions:

filterOptions ["Ready", 2, 4, 1] -> это означает, что отфильтровываются все данные с включенным 2,4,1 BHK, а также те данные, которые имеютion_date <текущая дата </p>

filterOptions ["В разработке", 3] -> это означает, что фильтровать все данные, для которых есть 3 BHK, а также те данные, которые имеютion_date> текущая дата

Итак, у меня есть следующий код:

Примечание: я использую .slice (), потому что сравниваю дату формы 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);

Если я удаляю checkStatus(filterOptions, item.possession_date), тогда фильтр работает отлично, но только дляТип BHK.Теперь я должен объединить это с датой, как я могу это сделать?

Ответы [ 2 ]

0 голосов
/ 25 февраля 2019

Рекомендую использовать отдельные списки фильтров.(На основе обсуждения с вами в 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)
0 голосов
/ 25 февраля 2019

Вы можете изменить логику фильтра на:

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);
  }
}

РЕДАКТИРОВАТЬ Предполагая, что вы хотите проверить только на 'Ready' в массиве temp:

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);
  }
}

РЕДАКТИРОВАТЬ 2

в части display_filtered_projects.push(x);, я не уверен, ожидаете ли вы y в противном случае.Подвох в том, что если data содержит повторяющиеся результаты, они будут добавляться повторно. Я обновил код для использования Set для решения этой проблемы.

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));

Дополнительная проблема заключается в том, что ваша логика дат, которую я повторно использовал, не будет возвращать ничего, если статус проекта не будет частью вашего ввода.Так что, возможно, в этом случае вы просто хотите вернуть true для всех.Я обновил код соответственно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...