Я пытаюсь отсортировать данные с джсона по чекбоксам. Пример данных:
[{
"id": 111,
"name": "Standart Room",
"img": "rooms_img_1.jpg",
"price": 126,
"category": "single",
"roomType": "room",
"adults": 1,
"children": 0,
"bed": "King",
"facilities": "Closet with hangers, HD flat-screen TV, Telephone",
"area": 20,
"breakfast": false,
"reservedFrom": "2020-02-07T23:28:56.782Z",
"reservedTo": "2020-02-09T23:28:56.782Z"
},{
"id": 112,
"name": "Standart Room",
"img": "rooms_img_1.jpg",
"price": 126,
"category": "single",
"roomType": "room",
"adults": 1,
"children": 0,
"bed": "King",
"facilities": "Closet with hangers, HD flat-screen TV, Telephone",
"area": 20,
"breakfast": false,
"reservedFrom": "2020-02-01T23:28:56.782Z",
"reservedTo": "2020-02-05T23:28:56.782Z"
}, {
"id": 313,
"name": "Double Room",
"img": "rooms_img_3.jpg",
"price": 320,
"category": "double",
"roomType": "room",
"adults": 2,
"children": 1,
"bed": "Twin",
"facilities": "Closet with hangers, HD flat-screen TV, Telephone",
"area": 20,
"breakfast": false,
"reservedFrom": "2020-03-07T23:28:56.782Z",
"reservedTo": "2020-03-091T23:28:56.782Z"
}, {
"id": 314,
"name": "Double Room",
"img": "rooms_img_4.jpg",
"price": 320,
"category": "double",
"roomType": "room",
"adults": 2,
"children": 0,
"bed": "Twin",
"facilities": "Closet with hangers, HD flat-screen TV, Telephone",
"area": 20,
"breakfast": false,
"reservedFrom": "2020-03-07T23:28:56.782Z",
"reservedTo": "2020-03-091T23:28:56.782Z"
}]
после чего фильтрую его по кол-ву людей и датам и загоняю их в новый массив availbleRooms.
availableRooms = data.filter(room => {
let reservedFromData = new Date(room.reservedFrom);
let reservedToData = new Date(room.reservedTo);
let checkinDate2 = new Date(checkinDate);
let checkoutDate2 = new Date(checkoutDate);
let wasNotSet = (room.reservedFrom == undefined || room.reservedTo == undefined);
let isAvaliable = wasNotSet || ((checkinDate2 <= reservedFromData || checkinDate2 >= reservedToData) && (checkoutDate2 <= reservedFromData || checkoutDate2 >= reservedToData));
if(!room.adults >= adultsValue && room.children >= childrenValue && isAvaliable)
return false;
if(isBreakfastRequired && !room.breakfast)
return false;
if(suiteType == true && room.roomType != "suite" ||
roomType == true && room.roomType != "room" ||
suitesAndRooms == true && room.roomType != "suite" && room.roomType != "room")
return false;
if(room.bed == "King" && !kingBed ||
room.bed == "Queen" && !queenBed ||
room.bed == "Twin" && !twinBed &&
(kingBed || queenBed || twinBed))
return false;
return true;
});
Такая фильтрация показывает только первый найденный эл, если условие показать и тип кровати кинг и квин, выведет только первый тип.
Как исправить мой фильтр?
И может кто-то подскажет варианты как сделать его изящнее и не таким полотном. Спасибо
Пара предварительных советов по организации кода:
Для начала можно forEach
заменить на filter
:
let availableRooms = data.filter(room => {
let reservedFromData = new Date(room.reservedFrom);
let reservedToData = new Date(room.reservedTo);
let checkinDate2 = new Date(checkinDate);
let checkoutDate2 = new Date(checkoutDate);
let wasNotSet = (room.reservedFrom == undefined || room.reservedTo == undefined);
let isAvaliable = wasNotSet || ((checkinDate2 <= reservedFromData || checkinDate2 >= reservedToData) && (checkoutDate2 <= reservedFromData || checkoutDate2 >= reservedToData));
return room.adults >= adultsValue && room.children >= childrenValue && isAvaliable;
});
Далее, можно туда же засунуть все остальные условия фильтрации, а не проходить массив целую кучу раз (что заметный проигрыш в производительности, если комнат много):
let availableRooms = data.filter(room => ({
let reservedFromData = new Date(room.reservedFrom);
let reservedToData = new Date(room.reservedTo);
let checkinDate2 = new Date(checkinDate);
let checkoutDate2 = new Date(checkoutDate);
let wasNotSet = (room.reservedFrom == undefined || room.reservedTo == undefined);
let isAvaliable = wasNotSet || ((checkinDate2 <= reservedFromData || checkinDate2 >= reservedToData) && (checkoutDate2 <= reservedFromData || checkoutDate2 >= reservedToData));
if(!room.adults >= adultsValue && room.children >= childrenValue && isAvaliable)
return false;
// обратите внимание, эта строчка плохо читается из-за неудачного названия переменной hasBreakfast - лучше бы она называлась isBreakfastRequired
if(hasBreakfast && !room.breakfast)
return false;
... // остальные условия в том же порядке
}));
Что касается собственно логики фильтрации, тут у вас довольно явная ошибка: вы вначале при kingBed == true
оставляете в avaliableRooms
комнаты, у которых тип кровати King, а затем среди них в случае queenBed == true
ищете комнаты с Queen, а это, очевидно, пустое множество. Давайте попробуем аккуратно дописать оставшиеся условия (по большому счёту, вы забыли else
в тех условиях + в фрагментах типа room.bed == "King" && room.bed == "Twin"
на самом деле должно быть "или" – иначе условие не выполнится никогда):
if(!room.adults >= adultsValue && room.children >= childrenValue && isAvaliable)
return false;
if(hasBreakfast && !room.breakfast)
return false;
if(suiteType == true && room.roomType != "suite" ||
roomType == true && room.roomType != "room" ||
suitesAndRooms == true && room.roomType != "suite" && room.roomType != "room")
return false;
if(kingBed == true && room.bed != "King" ||
queenBed == true && room.bed != "Queen" ||
twinBed == true && room.bed != "Twin" ||
kingBed == true && twinBed == true && (room.bed == "King" || room.bed == "Twin") ||
...
)
return false;
return true;
}));
Но, конечно, это всё равно ужасная реализация, короче будет описать логику "если тип кровати не соответствует фильтру", т.е.:
if(room.bed == "King" && !kingBed ||
room.bed == "Queen" && !queenBed ||
room.bed == "Twin" && !twinBed)
// еще, возможно, понадобится взять всё в скобки и добавить && (kingBed || queenBed || twinBed)
// если нужна логика "ничего не отмечено = всё выбрано"
return false;
а ещё лучше было бы не хранить данные о каждом типе отдельным флагом (kingBed
, queenBed
, twinBed
), а в объекте с теми же полями (selectedBedTypes: { King: boolean, Queen: boolean, Twin: boolean }
) и обходить его в for .. in ..
цикле – иначе добавление нового типа кровати заставит вас менять кучу кода.
Виртуальный выделенный сервер (VDS) становится отличным выбором
Поясните разницу между выводом одного и того же кода методами arrfilter() и arr