add comparisons page react

This commit is contained in:
Александр Манаенков 2023-05-09 12:26:41 +10:00
parent 4b55008f16
commit 8a2ffa7260
16 changed files with 404 additions and 93 deletions

View File

@ -114,7 +114,7 @@
<!--Блок с квартирой-->
<div class="apartmentBlock">
<!--Фото квартиры-->
<img src="./img/Apartment.png" alt="">
<img src="./images/Apartment.png" alt="">
<!--Стоимость квартиры-->
<h3>37 660 ₽ / мес.</h3>
<!--Адрес квартиры-->
@ -143,7 +143,7 @@
<!--Блок с квартирой-->
<div class="apartmentBlock">
<!--Фото квартиры-->
<img src="./img/Apartment.png" alt="">
<img src="./images/Apartment.png" alt="">
<!--Стоимость квартиры-->
<h3>37 660 ₽ / мес.</h3>
<!--Адрес квартиры-->
@ -170,7 +170,7 @@
<!--Блок с квартирой-->
<div class="apartmentBlock">
<!--Фото квартиры-->
<img src="./img/Apartment.png" alt="">
<img src="./images/Apartment.png" alt="">
<!--Стоимость квартиры-->
<h3>37 660 ₽ / мес.</h3>
<!--Адрес квартиры-->
@ -197,7 +197,7 @@
<!--Блок с квартирой-->
<div class="apartmentBlock">
<!--Фото квартиры-->
<img src="./img/Apartment.png" alt="">
<img src="./images/Apartment.png" alt="">
<!--Стоимость квартиры-->
<h3>37 660 ₽ / мес.</h3>
<!--Адрес квартиры-->
@ -742,7 +742,7 @@
<div class="viewedBlock">
<!--Квартира-->
<div class="viewedElem">
<img src="./img/Apartment.png" alt="">
<img src="./images/Apartment.png" alt="">
<p>56 м², 2-х комнатная</p>
<h3>36 тыс. / мес.</h3>
<p>Владивосток, ул. Нейбута 15А</p>
@ -750,7 +750,7 @@
<!--Квартира-->
<div class="viewedElem">
<img src="./img/Apartment.png" alt="">
<img src="./images/Apartment.png" alt="">
<p>56 м², 2-х комнатная</p>
<h3>36 тыс. / мес.</h3>
<p>Владивосток, ул. Нейбута 15А</p>
@ -758,7 +758,7 @@
<!--Квартира-->
<div class="viewedElem">
<img src="./img/Apartment.png" alt="">
<img src="./images/Apartment.png" alt="">
<p>56 м², 2-х комнатная</p>
<h3>36 тыс. / мес.</h3>
<p>Владивосток, ул. Нейбута 15А</p>
@ -766,7 +766,7 @@
<!--Квартира-->
<div class="viewedElem">
<img src="./img/Apartment.png" alt="">
<img src="./images/Apartment.png" alt="">
<p>56 м², 2-х комнатная</p>
<h3>36 тыс. / мес.</h3>
<p>Владивосток, ул. Нейбута 15А</p>

View File

@ -0,0 +1 @@
<svg width="10" height="16" viewBox="0 0 10 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0.265172 7.37804L7.59868 0.257485C7.95225 -0.0858284 8.5258 -0.0858284 8.87936 0.257485L9.73478 1.08811C10.088 1.43105 10.0883 1.98651 9.73629 2.33019L3.92419 7.99982L9.73591 13.6698C10.0883 14.0135 10.0876 14.5689 9.7344 14.9119L8.87898 15.7425C8.52542 16.0858 7.95187 16.0858 7.59831 15.7425L0.265172 8.62159C-0.0883908 8.27828 -0.0883908 7.72135 0.265172 7.37804Z" fill="#CCCCCC"/></svg>

After

Width:  |  Height:  |  Size: 498 B

View File

@ -0,0 +1 @@
<svg width="9" height="16" viewBox="0 0 9 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0.238707 8.62179L6.83881 15.7424C7.15713 16.0859 7.6732 16.0859 7.99148 15.7424L8.76127 14.9119C9.07904 14.5691 9.07965 14.0134 8.76263 13.6698L3.53193 7.99998L8.76263 2.33019C9.07965 1.98655 9.07904 1.43091 8.76127 1.08808L7.99148 0.257567C7.67316 -0.0858556 7.15709 -0.0858556 6.83881 0.257567L0.238741 7.37821C-0.0795746 7.72159 -0.0795746 8.27837 0.238707 8.62179Z" fill="black"/></svg>

After

Width:  |  Height:  |  Size: 505 B

View File

@ -0,0 +1 @@
<svg width="9" height="16" viewBox="0 0 9 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M8.76129 8.62179L2.16119 15.7424C1.84287 16.0859 1.3268 16.0859 1.00852 15.7424L0.238729 14.9119C-0.0790435 14.5691 -0.0796547 14.0134 0.237371 13.6698L5.46807 7.99998L0.237371 2.33019C-0.0796547 1.98655 -0.0790435 1.43091 0.238729 1.08808L1.00852 0.257567C1.32684 -0.0858556 1.84291 -0.0858556 2.16119 0.257567L8.76126 7.37821C9.07957 7.72159 9.07957 8.27837 8.76129 8.62179Z" fill="black"/></svg>

After

Width:  |  Height:  |  Size: 506 B

View File

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

View File

@ -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 (
<ApartmentBlock>
<ApartmentImage src="/images/apartment.png"></ApartmentImage>
<ApartmentPrice>{props.results.price} / мес.</ApartmentPrice>
<ApartmentAddress>{props.results.address}</ApartmentAddress>
<TransportSection>
<TransportIcon>
<SVGIcon src='/images/icons/bus.svg' width={20} height={21} />
<TransportTime>{props.results.timeToBus} мин</TransportTime>
</TransportIcon>
<TransportIcon>
<SVGIcon src='/images/icons/train.svg' width={18} height={20} />
<TransportTime>{props.results.timeToTrain} мин</TransportTime>
</TransportIcon>
</TransportSection>
<ButtonContact>Показать контакты</ButtonContact>
</ApartmentBlock>
);
}
export default BlockApartment;

View File

@ -5,7 +5,13 @@ const CardSmallApartament = function (props) {
return (
<div className="viewedElem">
<img src="/images/apartment.png" alt=""></img>
<p>{props.results.perimetrs} м², {props.results.rooms}-х комнатная</p>
<p>{props.results.perimetrs} м², {props.results.rooms == 0 ? '' : props.results.rooms}
{props.results.rooms == 0 ? 'Гостинка' :
(props.results.rooms > 1 ? "-х комнатная" : " комнатная")
}
</p>
<h3>{props.results.price} / мес.</h3>
<p>{props.results.address}</p>
</div>

View File

@ -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 (
<>
<PaginatedTitle title={"Сравнения квартир"} totalPages={totalPages} page={page} changePage={changePage}/>
<ApartmentSection>
<ApartmentSectionTitle>
<ApartmentSectionTitleText style={{height:300}}>Фото</ApartmentSectionTitleText>
<ApartmentSectionTitleText style={{height:1}}>оимость</ApartmentSectionTitleText>
<ApartmentSectionTitleText style={{height:65}}>Адрес</ApartmentSectionTitleText>
</ApartmentSectionTitle>
{apartmentsComparisons.map((apartament, index) =>
<>
<BlockApartment results={apartament}/>
</>
)}
</ApartmentSection>
<Separation>
<SeparationText>Характеристики</SeparationText>
<SeparationLine></SeparationLine>
</Separation>
<AboutSection>
<div>
<AboutTitle>Количество комнат</AboutTitle>
<AboutTitle>Этаж</AboutTitle>
<AboutTitle>Общая площадь</AboutTitle>
<AboutTitle>Санузел</AboutTitle>
</div>
{apartmentsComparisons.map((apartament, index) =>
<div>
<AboutTitle>{apartament.rooms}</AboutTitle>
<AboutTitle>{apartament.floor} из {apartament.floorHouse}</AboutTitle>
<AboutTitle>{apartament.perimetrs} м²</AboutTitle>
<Indicator>{apartament.isBathroom ? '✓' : '—'}</Indicator>
</div>
)}
</AboutSection>
<Separation>
<SeparationText>Удобства</SeparationText>
<SeparationLine></SeparationLine>
</Separation>
<AboutSection>
<div>
<AboutTitle>Мебель</AboutTitle>
<AboutTitle>Интернет</AboutTitle>
<AboutTitle>Телевизор</AboutTitle>
<AboutTitle>Стиральная машинка</AboutTitle>
<AboutTitle>Холодильник</AboutTitle>
<AboutTitle>Кондиционер</AboutTitle>
<AboutTitle>Можно с детьми</AboutTitle>
<AboutTitle>Можно с животными</AboutTitle>
<AboutTitle>Свежий ремонт</AboutTitle>
</div>
{apartmentsComparisons.map((apartament, index) =>
<div>
<Indicator>{apartament.isFurniture ? '✓' : '—'}</Indicator>
<Indicator>{apartament.isInternet ? '✓' : '—'}</Indicator>
<Indicator>{apartament.isTelevision ? '✓' : '—'}</Indicator>
<Indicator>{apartament.isWasher ? '✓' : '—'}</Indicator>
<Indicator>{apartament.isRefrigerator ? '✓' : '—'}</Indicator>
<Indicator>{apartament.isAirConditioning ? '✓' : '—'}</Indicator>
<Indicator>{apartament.isChild ? '✓' : '—'}</Indicator>
<Indicator>{apartament.isAnimal ? '✓' : '—'}</Indicator>
<Indicator>{apartament.isFreshRepair ? '✓' : '—'}</Indicator>
</div>
)}
</AboutSection>
<Separation>
<SeparationText>О здании</SeparationText>
<SeparationLine></SeparationLine>
</Separation>
<AboutSection>
<div>
<AboutTitle>Высота потолков</AboutTitle>
<AboutTitle>Количество этажей</AboutTitle>
<AboutTitle>Лифт</AboutTitle>
<AboutTitle>Мусоропровод</AboutTitle>
<AboutTitle>Закрытая парковка</AboutTitle>
<AboutTitle>Охрана или консьерж</AboutTitle>
</div>
{apartmentsComparisons.map((apartament, index) =>
<div>
<AboutTitle>{apartament.ceilingHeight} м</AboutTitle>
<AboutTitle>{apartament.floorHouse}</AboutTitle>
<Indicator>{apartament.isElevator ? '✓' : '—'}</Indicator>
<Indicator>{apartament.isGarbageChute ? '✓' : '—'}</Indicator>
<Indicator>{apartament.isParking ? '✓' : '—'}</Indicator>
<Indicator>{apartament.isConcierge ? '✓' : '—'}</Indicator>
</div>
)}
</AboutSection>
</>
);
};
export default ComparisonsApartmentsList;

View File

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

View File

@ -3,7 +3,7 @@ import { Link } from "react-router-dom";
import styled from 'styled-components';
import SVGIcon from '../UI/Icon/SVGIcon';
// import './styles/Header.css';
import './styles/Header.css'
const HeaderElement = styled.header`
display: flex;
@ -38,21 +38,7 @@ const LocationButton = styled.button`
const PairentLogo = styled.h1`
user-select: none;
`;
const NavButton = styled.div`
& a:hover {
color: #0050A1;
transition: 0.3s ease;
}
`;
const Navbar = styled.nav`
display: flex;
align-items: center;
& ${NavButton} {
margin-right: 55px
}
`;
`
const Header = function () {
return (
@ -72,29 +58,29 @@ const Header = function () {
</LocationButton>
</Link>
</LogoSection>
<Navbar>
<NavButton>
<nav>
<div>
<Link to="/favorites">
<SVGIcon src='/images/icons/heart.svg' width='16' height='14' />
Избранное
</Link>
</NavButton>
<NavButton>
</div>
<div>
<Link to="/comparisons">
<SVGIcon src='/images/icons/stats.svg' width='16' height='14' />
Сравнения
</Link>
</NavButton>
<NavButton>
</div>
<div>
<Link to="/">
<SVGIcon src='/images/icons/chat-bubble.svg' width='16' height='14' />
Чаты
</Link>
</NavButton>
</div>
<Link to="/">
<SVGIcon src='/images/icons/user.svg' width='32' height='32' />
</Link>
</Navbar>
</nav>
</HeaderElement>
);
}

View File

@ -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) => {

View File

@ -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(
<TitleSection>
<TitleSectionLeftAndRight>
<Link to="/">
<ButtonBack>
<SVGIcon src='/images/icons/left-arrow-light.svg' width={10} height={16}/>
Вернуться назад
</ButtonBack>
</Link>
<Title>{title}</Title>
</TitleSectionLeftAndRight>
<TitleSectionLeftAndRight>
<ButtonPreviousAndNext onClick={() => changePage(previousPage)}>
<SVGIcon src='/images/icons/left-arrow.svg' width={9} height={16}/>
</ButtonPreviousAndNext>
<ButtonPreviousAndNext onClick={() => changePage(nextPage)}>
<SVGIcon src='/images/icons/right-arrow.svg' width={9} height={16}/>
</ButtonPreviousAndNext>
</TitleSectionLeftAndRight>
</TitleSection>
);
}
export default PaginatedTitle;

View File

@ -1,10 +1,17 @@
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 (
<section className="btnSection">
@ -15,7 +22,7 @@ const Pagination = ({totalPages, page, changePage, viewAll}) => {
<path d="M0.238707 8.62179L6.83881 15.7424C7.15713 16.0859 7.6732 16.0859 7.99148 15.7424L8.76127 14.9119C9.07904 14.5691 9.07965 14.0134 8.76263 13.6698L3.53193 7.99998L8.76263 2.33019C9.07965 1.98655 9.07904 1.43091 8.76127 1.08808L7.99148 0.257567C7.67316 -0.0858556 7.15709 -0.0858556 6.83881 0.257567L0.238741 7.37821C-0.0795746 7.72159 -0.0795746 8.27837 0.238707 8.62179Z" fill="black"/>
</svg>
</button>
{pagesArray.map(p =>
{getPagesShow().map(p =>
<button onClick={() => changePage(p)} key={p} className={page === p ? "pageBtn activePage" : "pageBtn"}>{p}</button>
)}
<button onClick={() => changePage(nextPage)} className="btnNext">

View File

@ -1,4 +1,5 @@
import React from 'react';
import ComparisonsApartmentsList from '../../components/ComparisonsApartamentsList';
import Questions from '../../components/Questions';
import LastView from '../../components/LastView';
@ -6,7 +7,7 @@ const Comparisons = function () {
return(
<>
<h2>Сравнения</h2>
<ComparisonsApartmentsList/>
<Questions/>
<LastView/>
</>

View File

@ -14,54 +14,3 @@ h2{
margin-left: 34%;
border: 1px solid #ccc;
}
/*Кнопки с вопросами*/
.questionBtnSection{
display: flex;
justify-content: space-between;
margin-top: 55px;
}
.questionBtn{
width: 323px;
height: 128px;
padding: 2% 5% 2% 3%;
border-radius: 12px;
text-align: left;
}
.questionBtn h3{
font-size: 18px;
color: #fff;
}
.questionBtn p{
margin-top: 16px;
font-size: 16px;
line-height: 19px;
color: #fff;
}
.orangeBtn{
background: linear-gradient(180deg, #F76D09 0%, #FFA800 100%);
}
.orangeBtn:active{
background: linear-gradient(180deg, #FFA800 0%, #F76D09 100%);
}
.greenBtn{
background: linear-gradient(180deg, #107A34 0%, #51A633 100%);
}
.greenBtn:active{
background: linear-gradient(180deg, #51A633 0%, #107A34 100%);
}
.blueBtn{
background: linear-gradient(180deg, #2E50A7 0%, #0993F7 100%);
}
.blueBtn:active{
background: linear-gradient(180deg, #0993F7 0%, #2E50A7 100%);
}

View File

@ -9,3 +9,11 @@ export const getPagesArray = (totalPages) => {
}
return result;
}
export const getPreviousAndNextPage = (totalPages, page) => {
let pagesArray = getPagesArray(totalPages);
let previousPage = page !== 1 ? page - 1 : page;
let nextPage = page < pagesArray.length ? page + 1 : page;
return [previousPage, nextPage];
}