From c91eba0a62b14e4e3d287bd3852d1644ece734b7 Mon Sep 17 00:00:00 2001 From: b1ek Date: Thu, 11 May 2023 23:11:38 +1000 Subject: [PATCH] make filters work (almost) --- pairent_backend/pairent_app/views.py | 17 +++-- pairent_backend/pairent_backend/settings.py | 2 +- pairent_frontend_react/src/API/Filters.js | 34 +++++++++ .../src/pages/IndexPage/index.jsx | 69 ++++++++++++++++--- 4 files changed, 106 insertions(+), 16 deletions(-) create mode 100644 pairent_frontend_react/src/API/Filters.js diff --git a/pairent_backend/pairent_app/views.py b/pairent_backend/pairent_app/views.py index 6fb2521..88f00e9 100644 --- a/pairent_backend/pairent_app/views.py +++ b/pairent_backend/pairent_app/views.py @@ -59,17 +59,24 @@ class ApartmentFilter(viewsets.ViewSet): def list(self, req: Request): filters = dict(req.data); - unfiltered = ApartamentDetailSerializer(Apartament.objects.all()[:100], many=True).data; + unfiltered = Apartament.objects.all(); filtered = []; + # TODO: Some better converting practice? + filters['price_range']['from'] = int(filters['price_range']['from']); + filters['price_range']['to'] = int(filters['price_range']['to']); + filters['area_range']['from'] = int(filters['area_range']['from']); + filters['area_range']['to'] = int(filters['area_range']['to']); + filters['rooms'] = int(filters['rooms']) + for entry in unfiltered: - if (filters['price_range']['from'] >= entry['price'] and (filters['price_range']['to'] != -1 and filters['price_range']['to'] <= entry['price'])): + if (filters['price_range']['from'] >= entry.price and (filters['price_range']['to'] != -1 and filters['price_range']['to'] <= entry.price)): continue; - if (filters['area_range']['from'] >= entry['perimetrs'] and (filters['area_range']['to'] != -1 and filters['area_range']['to'] <= entry['perimetrs'])): + if (filters['area_range']['from'] >= entry.perimetrs and (filters['area_range']['to'] != -1 and filters['area_range']['to'] <= entry.perimetrs)): continue; - if (filters['rooms'] != -1 and entry['rooms'] != filters['rooms']): + if (filters['rooms'] != -1 and entry.rooms != filters['rooms']): continue; filtered.append(entry); - return Response(filtered); \ No newline at end of file + return Response(ApartamentListSerializer(filtered, many=True).data); \ No newline at end of file diff --git a/pairent_backend/pairent_backend/settings.py b/pairent_backend/pairent_backend/settings.py index 12146ac..9a97b53 100644 --- a/pairent_backend/pairent_backend/settings.py +++ b/pairent_backend/pairent_backend/settings.py @@ -25,7 +25,7 @@ SECRET_KEY = 'django-insecure-=(7b+4ka=5jak-mokuh4#-6_14f58#^0kjwqsz7wyon$4i@sel # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True -ALLOWED_HOSTS = [] +ALLOWED_HOSTS = ['*'] # Application definition diff --git a/pairent_frontend_react/src/API/Filters.js b/pairent_frontend_react/src/API/Filters.js new file mode 100644 index 0000000..8cedaa2 --- /dev/null +++ b/pairent_frontend_react/src/API/Filters.js @@ -0,0 +1,34 @@ +class Range { + /** @type {number} */ + from; + + /** @type {number} */ + to; +} + +class Filters { + /** @type { Range } */ + price_range; + + /** @type { Range } */ + area_range; + + /** @type { string[] } */ + lease_period; + + /** @type { string } */ + address; + + /** @type { number } */ + rooms; + + constructor() { + this.price_range = new Range(); + this.area_range = new Range(); + this.lease_period = []; + this.address = ''; + this.rooms = 0; + } +} + +export { Filters, Range } \ No newline at end of file diff --git a/pairent_frontend_react/src/pages/IndexPage/index.jsx b/pairent_frontend_react/src/pages/IndexPage/index.jsx index 320d840..618603f 100644 --- a/pairent_frontend_react/src/pages/IndexPage/index.jsx +++ b/pairent_frontend_react/src/pages/IndexPage/index.jsx @@ -4,6 +4,7 @@ import { Scrollbar, Navigation } from 'swiper/core'; import ISVGIcon from '../../components/UI/Icon/SVGIcon'; import Select from 'react-select'; import ApartmentsList from "../../components/ApartmentsList"; +import { Filters } from "../../API/Filters"; import styled from 'styled-components'; import 'swiper/css'; @@ -15,6 +16,9 @@ import './swiper.css'; import ApartamentService from "../../API/ApartamentService"; import { HashLoader } from 'react-spinners'; +import constants from "../../constants"; + +const API_ROOT = constants.API_ROOT; const SVGIcon = styled(ISVGIcon)` margin-left:0; @@ -37,7 +41,7 @@ const SwiperImage = styled.div` height: 100%; `; -const Filters = styled.div` +const FiltersEl = styled.div` background: url(/images/filter.png); height: 300px; width: 1150px; @@ -163,7 +167,7 @@ const Splash = styled.h3` text-align: center; `; -const FiltersForm = () => { +const FiltersForm = (props) => { const apart_sizes = [ { value: 0, label: "Гостинка" }, @@ -175,7 +179,7 @@ const FiltersForm = () => { const def_form = { per_day: false, - per_month: false, + per_month: true, area_from: '', area_to: '', @@ -185,7 +189,9 @@ const FiltersForm = () => { address: '', - rooms: 0, + rooms: { value: -1, label: 'Выберите' }, + + form_err: false }; @@ -195,8 +201,28 @@ const FiltersForm = () => { return setState_({...state, ...new_state}); } + const onSumbit = () => { + let transformed = new Filters(); + + transformed.address = state.address; + transformed.area_range = { + from: state.area_from, + to: state.area_to + }; + transformed.price_range = { + from: state.price_from, + to: state.price_to + }; + + if (state.per_day) transformed.lease_period.push('day'); + if (state.per_month) transformed.lease_period.push('month'); + if (state.rooms.value != -1) transformed.rooms = state.rooms.value; + + if (props.onSubmit) props.onSubmit(transformed); + } + return ( - + Фильтры @@ -280,11 +306,11 @@ const FiltersForm = () => { - console.log(state)}> + Показать варианты - + ); } @@ -295,6 +321,7 @@ export default class IndexPage extends React.Component { this.state = { apartments: [], + unfiltered: [], pageSize: 10, page: 0, data_loaded: false, @@ -302,10 +329,32 @@ export default class IndexPage extends React.Component { }; ApartamentService.getAll(100).then(data => { - this.setState({apartments: data.data.results, data_loaded: true}); + this.setState({apartments: data.data.results, unfiltered: data.data.results, data_loaded: true}); }).catch(err => { - this.setState({data_loaded: true, apartments: [], load_err: err.message}); + this.setState({data_loaded: true, apartments: [], unfiltered: data.data.results, load_err: err.message}); }); + + this.filterData = this.filterData.bind(this); + } + + /** + * + * @param {Filters} filters + */ + async filterData(filters) { + + const filtered_raw = await fetch(API_ROOT + '/api/apartaments/filters/', { + method: 'POST', + body: JSON.stringify(filters), + headers: { + 'Content-Type': 'application/json' + } + }).catch(err => console.error(err)); + + const filtered = await filtered_raw.json(); + + this.setState({apartments: filtered, data_loaded: true, load_err: false}); + ; } render() { @@ -340,7 +389,7 @@ export default class IndexPage extends React.Component { Владивостоке - + {