diff --git a/pairent_frontend/Comparison.html b/pairent_frontend/Comparison.html index f5447c9..fde9209 100644 --- a/pairent_frontend/Comparison.html +++ b/pairent_frontend/Comparison.html @@ -114,7 +114,7 @@
- +

37 660 ₽ / мес.

@@ -143,7 +143,7 @@
- +

37 660 ₽ / мес.

@@ -170,7 +170,7 @@
- +

37 660 ₽ / мес.

@@ -197,7 +197,7 @@
- +

37 660 ₽ / мес.

@@ -742,7 +742,7 @@
- +

56 м², 2-х комнатная

36 тыс. / мес.

Владивосток, ул. Нейбута 15А

@@ -750,7 +750,7 @@
- +

56 м², 2-х комнатная

36 тыс. / мес.

Владивосток, ул. Нейбута 15А

@@ -758,7 +758,7 @@
- +

56 м², 2-х комнатная

36 тыс. / мес.

Владивосток, ул. Нейбута 15А

@@ -766,7 +766,7 @@
- +

56 м², 2-х комнатная

36 тыс. / мес.

Владивосток, ул. Нейбута 15А

diff --git a/pairent_frontend_react/public/images/icons/left-arrow-light.svg b/pairent_frontend_react/public/images/icons/left-arrow-light.svg new file mode 100644 index 0000000..14d02c9 --- /dev/null +++ b/pairent_frontend_react/public/images/icons/left-arrow-light.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/pairent_frontend_react/public/images/icons/left-arrow.svg b/pairent_frontend_react/public/images/icons/left-arrow.svg new file mode 100644 index 0000000..5304319 --- /dev/null +++ b/pairent_frontend_react/public/images/icons/left-arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/pairent_frontend_react/public/images/icons/right-arrow.svg b/pairent_frontend_react/public/images/icons/right-arrow.svg new file mode 100644 index 0000000..8aa07fd --- /dev/null +++ b/pairent_frontend_react/public/images/icons/right-arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/pairent_frontend_react/src/API/ApartamentService.js b/pairent_frontend_react/src/API/ApartamentService.js index d3525f5..64b45e2 100644 --- a/pairent_frontend_react/src/API/ApartamentService.js +++ b/pairent_frontend_react/src/API/ApartamentService.js @@ -18,4 +18,9 @@ export default class ApartamentService { const response = await axios.get(API_ROOT + '/api/apartament/' + id) return response; } + + static async getComparisons() { + const response = await axios.get(API_ROOT + '/api/comparison/') + return response; + } } \ No newline at end of file diff --git a/pairent_frontend_react/src/components/BlockApartment/index.jsx b/pairent_frontend_react/src/components/BlockApartment/index.jsx new file mode 100644 index 0000000..928a7f8 --- /dev/null +++ b/pairent_frontend_react/src/components/BlockApartment/index.jsx @@ -0,0 +1,81 @@ +import React from 'react'; +import styled from 'styled-components'; +import SVGIcon from '../UI/Icon/SVGIcon'; + +const ApartmentBlock = styled.div` + width: 20%; + margin-top: 26px; +` +const ApartmentImage = styled.img` + width: 100%; +` + +const ApartmentPrice = styled.h3` + margin-top: 16px; + font-weight: 600; + font-size: 20px; + color: #222; +` + +const ApartmentAddress = styled.p` + margin-top: 16px; + font-size: 16px; + color: #0050A1; +` + +const TransportSection = styled.div` + display: flex; + margin-top: 9px; +` + +const TransportIcon = styled.div` + display: flex; + justify-content: space-around; + align-items: center; + width: 96px; + height: 32px; + border: 2px solid #A9A9A9; + border-radius: 20px; + + margin-left: 9px; +` + +const TransportTime = styled.p` + font-weight: 500; + font-size: 15px; + color: #A9A9A9; +` + +const ButtonContact = styled.button` + width: 180px; + height: 36px; + margin-top: 26px; + background: #175FA9; + border-radius: 12px; + font-weight: 500; + font-size: 16px; + color: #fff; +` + +const BlockApartment = function (props) { + return ( + + + {props.results.price} ₽ / мес. + {props.results.address} + + + + {props.results.timeToBus} мин + + + + {props.results.timeToTrain} мин + + + Показать контакты + + ); +} + +export default BlockApartment; \ No newline at end of file diff --git a/pairent_frontend_react/src/components/CardSmallApartament/index.jsx b/pairent_frontend_react/src/components/CardSmallApartament/index.jsx index d6aed4f..517980b 100644 --- a/pairent_frontend_react/src/components/CardSmallApartament/index.jsx +++ b/pairent_frontend_react/src/components/CardSmallApartament/index.jsx @@ -5,7 +5,13 @@ const CardSmallApartament = function (props) { return (
-

{props.results.perimetrs} м², {props.results.rooms}-х комнатная

+

{props.results.perimetrs} м², {props.results.rooms == 0 ? '' : props.results.rooms} + + {props.results.rooms == 0 ? 'Гостинка' : + (props.results.rooms > 1 ? "-х комнатная" : " комнатная") + } + +

{props.results.price}₽ / мес.

{props.results.address}

diff --git a/pairent_frontend_react/src/components/ComparisonsApartamentsList/index.jsx b/pairent_frontend_react/src/components/ComparisonsApartamentsList/index.jsx new file mode 100644 index 0000000..bc8c041 --- /dev/null +++ b/pairent_frontend_react/src/components/ComparisonsApartamentsList/index.jsx @@ -0,0 +1,188 @@ +import React, { useEffect, useState } from 'react'; + +import PaginatedTitle from '../UI/PaginatedTitle'; +import BlockApartment from '../BlockApartment'; + +import ApartamentService from '../../API/ApartamentService'; +import { useFetching } from '../../hooks/useFetching'; +import { getPageCount } from '../../utils/Pages'; + +import styled from 'styled-components'; +import SVGIcon from '../UI/Icon/SVGIcon'; + +const ApartmentSection = styled.section` + display: flex; + justify-content: space-between; + padding-left: 3%; +` + +const ApartmentSectionTitle = styled.div` + width: 19%; +` + +const ApartmentSectionTitleText = styled.h3` + font-weight: 600; + font-size: 16px; + display: flex; + align-items: center; +` + +const Separation = styled.div` + margin-top: 50px; +` + +const SeparationText = styled.p` + margin-left: 3%; + font-weight: 500; + font-size: 16px; + color: rgba(0, 0, 0, 0.5); +` + +const SeparationLine = styled.div` + height: 2px; + margin-top: 8px; + width: 100%; + background-color: #CCC; +` + +const AboutSection = styled.section` + display: flex; + justify-content: space-between; + margin-left: 3%; +` + +const AboutTitle = styled.h3` + margin-top: 33px; + font-weight: 600; + font-size: 16px; +` + +const Indicator = styled.p` + color: rgba(0, 0, 0, 0.5); + margin-top: 33px; + font-weight: 600; + font-size: 16px; +` + +const ComparisonsApartmentsList = () => { + const [apartmentsComparisons, setApartmentsComparisons] = useState([]) + const [totalPages, setTotalPages] = useState(0); + const [page, setPage] = useState(1); + const limit = 4; + + const [fetchApartaments, isApartmentsLoading, apartmentsError] = useFetching(async (limit) => { + let offset = (page - 1) * limit; + const response = await ApartamentService.getAll(limit, offset); + setApartmentsComparisons(response.data.results) + let totalCount = response.data.count; + setTotalPages(getPageCount(totalCount, limit)) + }) + + useEffect(() => { + fetchApartaments(limit) + }, [page]) + + const changePage = (page) => { + setPage(page) + } + + return ( + <> + + + + Фото + Cтоимость + Адрес + + {apartmentsComparisons.map((apartament, index) => + <> + + + )} + + + + Характеристики + + + + +
+ Количество комнат + Этаж + Общая площадь + Санузел +
+ {apartmentsComparisons.map((apartament, index) => +
+ {apartament.rooms} + {apartament.floor} из {apartament.floorHouse} + {apartament.perimetrs} м² + {apartament.isBathroom ? '✓' : '—'} +
+ )} +
+ + + Удобства + + + + +
+ Мебель + Интернет + Телевизор + Стиральная машинка + Холодильник + Кондиционер + Можно с детьми + Можно с животными + Свежий ремонт +
+ {apartmentsComparisons.map((apartament, index) => +
+ {apartament.isFurniture ? '✓' : '—'} + {apartament.isInternet ? '✓' : '—'} + {apartament.isTelevision ? '✓' : '—'} + {apartament.isWasher ? '✓' : '—'} + {apartament.isRefrigerator ? '✓' : '—'} + {apartament.isAirConditioning ? '✓' : '—'} + {apartament.isChild ? '✓' : '—'} + {apartament.isAnimal ? '✓' : '—'} + {apartament.isFreshRepair ? '✓' : '—'} +
+ )} +
+ + + О здании + + + + +
+ Высота потолков + Количество этажей + Лифт + Мусоропровод + Закрытая парковка + Охрана или консьерж +
+ {apartmentsComparisons.map((apartament, index) => +
+ {apartament.ceilingHeight} м + {apartament.floorHouse} + {apartament.isElevator ? '✓' : '—'} + {apartament.isGarbageChute ? '✓' : '—'} + {apartament.isParking ? '✓' : '—'} + {apartament.isConcierge ? '✓' : '—'} +
+ )} +
+ + ); +}; + +export default ComparisonsApartmentsList; \ No newline at end of file diff --git a/pairent_frontend_react/src/components/FavoritesApartamentsList/index.jsx b/pairent_frontend_react/src/components/FavoritesApartamentsList/index.jsx index f6efed5..79c3a4c 100644 --- a/pairent_frontend_react/src/components/FavoritesApartamentsList/index.jsx +++ b/pairent_frontend_react/src/components/FavoritesApartamentsList/index.jsx @@ -10,7 +10,7 @@ const FavoritesApartamentsList = () => { const [apartamentsFavorites, setApartamentsFavorites] = useState([]) const [totalPages, setTotalPages] = useState(0); const [page, setPage] = useState(1); - const [limit, setLimit] = useState(1); + const [limit, setLimit] = useState(5); const [fetchApartaments, isApartamentsLoading, apartamentsError] = useFetching(async (limit) => { let offset = (page - 1) * limit; diff --git a/pairent_frontend_react/src/components/LastView/index.jsx b/pairent_frontend_react/src/components/LastView/index.jsx index cb629db..520527d 100644 --- a/pairent_frontend_react/src/components/LastView/index.jsx +++ b/pairent_frontend_react/src/components/LastView/index.jsx @@ -11,7 +11,7 @@ const LastView = function () { const [apartamentsLastView, setApartamentsLastView] = useState([]) const [totalPages, setTotalPages] = useState(0); const [page, setPage] = useState(1); - const limit = 1; + const limit = 4; const [totalCount, setTotalCount] = useState(0); const [fetchApartaments, isApartamentsLoading, apartamentsError] = useFetching(async (limit) => { diff --git a/pairent_frontend_react/src/components/UI/PaginatedTitle/index.jsx b/pairent_frontend_react/src/components/UI/PaginatedTitle/index.jsx new file mode 100644 index 0000000..c7c6b4e --- /dev/null +++ b/pairent_frontend_react/src/components/UI/PaginatedTitle/index.jsx @@ -0,0 +1,77 @@ +import React from 'react'; +import { getPreviousAndNextPage } from '../../../utils/Pages'; +import { Link } from 'react-router-dom'; +import styled from 'styled-components'; +import SVGIcon from '../Icon/SVGIcon'; + +const TitleSection = styled.section` + display: flex; + justify-content: space-between; + margin-top: 24px; + padding: 0 3% 0 3%; +`; + +const TitleSectionLeftAndRight = styled.div` + display: flex; + align-items: center; +`; + +const ButtonBack = styled.button` + display: flex; + justify-content: space-evenly; + align-items: center; + width: 180px; + height: 36px; + color: #BABABA; + background: #fff; + border: 1px solid #ccc; + border-radius: 12px; + font-size: 15px; +`; + +const Title = styled.h2` + margin-left: 31px; + font-size: 24px; + color: #222; +`; + +const ButtonPreviousAndNext = styled.button` + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border-radius: 20px; + background: #fff; + box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.25); + margin-right: 10px; +`; + +const PaginatedTitle = function ({title, totalPages, page, changePage}) { + let [previousPage, nextPage] = getPreviousAndNextPage(totalPages, page); + + return( + + + + + + Вернуться назад + + + {title} + + + + changePage(previousPage)}> + + + changePage(nextPage)}> + + + + + ); +} + +export default PaginatedTitle; \ No newline at end of file diff --git a/pairent_frontend_react/src/components/UI/Pagination/index.jsx b/pairent_frontend_react/src/components/UI/Pagination/index.jsx index adb5ce7..c703c06 100644 --- a/pairent_frontend_react/src/components/UI/Pagination/index.jsx +++ b/pairent_frontend_react/src/components/UI/Pagination/index.jsx @@ -1,11 +1,18 @@ import React from 'react'; -import {getPagesArray} from "../../../utils/Pages"; +import {getPagesArray, getPreviousAndNextPage} from "../../../utils/Pages"; const Pagination = ({totalPages, page, changePage, viewAll}) => { let pagesArray = getPagesArray(totalPages); - let previousPage = page !== 1 ? page - 1 : page - let nextPage = page < pagesArray.length ? page + 1 : page + let [previousPage, nextPage] = getPreviousAndNextPage(totalPages, page); + const getPagesShow = () => { + let pagesShow = []; + for (let index = page - 1, len = page + 14 > totalPages ? totalPages : page + 14; index < len; ++index) { + pagesShow.push(pagesArray[index]) + } + return pagesShow; + } + return (
@@ -15,9 +22,9 @@ const Pagination = ({totalPages, page, changePage, viewAll}) => { - {pagesArray.map(p => + {getPagesShow().map(p => - )} + )}