update page favorites react
This commit is contained in:
parent
7568268621
commit
9b9956dcaa
|
@ -0,0 +1,18 @@
|
|||
import axios from 'axios';
|
||||
|
||||
export default class ApartamentService {
|
||||
static async getAll(limit, offest) {
|
||||
const response = await axios.get('http://127.0.0.1:8000/api/apartaments/', {
|
||||
params: {
|
||||
limit: limit,
|
||||
...(offest !== 0 ? {offset: offest} : {})
|
||||
}
|
||||
})
|
||||
return response;
|
||||
}
|
||||
|
||||
static async getById(id) {
|
||||
const response = await axios.get('http://127.0.0.1:8000/api/apartament/' + id)
|
||||
return response;
|
||||
}
|
||||
}
|
|
@ -24,3 +24,59 @@ main{
|
|||
height: 1px;
|
||||
background-color: #CCC;
|
||||
}
|
||||
|
||||
/*Кнопки выбора страницы*/
|
||||
.btnSection{
|
||||
display: flex;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
/*Кнопка "Показать весь список*/
|
||||
.allBtn{
|
||||
width: 208px;
|
||||
height: 32px;
|
||||
background-color: #fff;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 12px;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/*Кнопки переключения страниц*/
|
||||
.choiceBtn{
|
||||
display: flex;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
/*Кнопки "предыдущая" и "следующая"*/
|
||||
.btnPrevious, .btnNext {
|
||||
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);
|
||||
}
|
||||
|
||||
.btnNext{
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.pageBtn{
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
margin-left: 10px;
|
||||
background: #D9D9D9;
|
||||
border-radius: 12px;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.activePage{
|
||||
border: 2px solid #175FA9;
|
||||
background-color: #fff;
|
||||
color: #175FA9;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
import React from 'react';
|
||||
import './styles/CardSmallApartament.css';
|
||||
|
||||
const CardSmallApartament = function (props) {
|
||||
return (
|
||||
<div className="viewedElem">
|
||||
<img src="/images/apartment.png" alt=""></img>
|
||||
<p>{props.results.perimetrs} м², {props.results.rooms}-х комнатная</p>
|
||||
<h3>{props.results.price}₽ / мес.</h3>
|
||||
<p>{props.results.address}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default CardSmallApartament;
|
|
@ -0,0 +1,29 @@
|
|||
/*Квартира*/
|
||||
.viewedElem{
|
||||
width: 24%;
|
||||
padding-bottom: 1%;
|
||||
background: #fff;
|
||||
border: 2px solid #ccc;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.viewedElem img{
|
||||
width: 100%;
|
||||
margin-bottom: 3%;
|
||||
}
|
||||
|
||||
.viewedElem h3, .viewedElem p{
|
||||
margin-left: 5%;
|
||||
}
|
||||
|
||||
.viewedElem h3{
|
||||
font-weight: 600;
|
||||
font-size: 24px;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.viewedElem p{
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
color: #222;
|
||||
}
|
|
@ -1,29 +1,31 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import CardApartament from '../../components/CardApartament/CardApartament';
|
||||
import axios from 'axios'; /* БЛЯ 10 КБ СУКА */
|
||||
import React from 'react';
|
||||
|
||||
import FavoritesApartamentsList from './FavoritesApartamentsList';
|
||||
import LastView from '../../components/LastView/LastView';
|
||||
|
||||
import './styles/Favorites.css';
|
||||
|
||||
const Favorites = function () {
|
||||
const [apartaments, setApartaments] = useState([])
|
||||
|
||||
async function fetchApartaments() {
|
||||
const response = await axios.get('http://127.0.0.1:8000/api/apartaments/')
|
||||
setApartaments(response.data.results)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
fetchApartaments()
|
||||
})
|
||||
|
||||
return(
|
||||
<>
|
||||
<h2>Избранное</h2>
|
||||
{apartaments.map((apartament, index) =>
|
||||
<>
|
||||
<CardApartament results={apartament}/>
|
||||
<div className="separationLine"></div>
|
||||
</>
|
||||
)}
|
||||
<FavoritesApartamentsList/>
|
||||
<section className="questionBtnSection">
|
||||
<button className="questionBtn orangeBtn">
|
||||
<h3>Рестик или кафешка?</h3>
|
||||
<p>Какой общепит предпочтительнее для вас возле жилища?</p>
|
||||
</button>
|
||||
<button className="questionBtn greenBtn">
|
||||
<h3>Двушка или однушка?</h3>
|
||||
<p>Как выбрать квартиру под себя, чтобы не переплачивать?</p>
|
||||
</button>
|
||||
<button className="questionBtn blueBtn">
|
||||
<h3>Совмещенный или отдельно?</h3>
|
||||
<p>Какой санузел будет для вас лучшим вариантом?</p>
|
||||
</button>
|
||||
</section>
|
||||
<LastView/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import ApartamentService from '../../API/ApartamentService';
|
||||
import {useFetching} from '../../hooks/useFetching';
|
||||
import {getPageCount} from '../../utils/Pages';
|
||||
|
||||
import CardApartament from '../../components/CardApartament/CardApartament';
|
||||
import Pagination from '../../components/UI/Pagination/Pagination';
|
||||
|
||||
const FavoritesApartamentsList = () => {
|
||||
const [apartaments, setApartaments] = useState([])
|
||||
const [totalPages, setTotalPages] = useState(0);
|
||||
const limit = 1;
|
||||
const [page, setPage] = useState(1);
|
||||
|
||||
const [fetchApartaments, isApartamentsLoading, apartamentsError] = useFetching(async (limit) => {
|
||||
let offset = (page - 1) * limit;
|
||||
const response = await ApartamentService.getAll(limit, offset);
|
||||
setApartaments(response.data.results)
|
||||
const totalCount = response.data.count
|
||||
setTotalPages(getPageCount(totalCount, limit))
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
fetchApartaments(limit)
|
||||
}, [page])
|
||||
|
||||
const changePage = (page) => {
|
||||
setPage(page)
|
||||
}
|
||||
|
||||
// TODO: Переделать, сейчас сделанно для MVP (то есть заглушки)
|
||||
if (!apartaments.length && !isApartamentsLoading && !apartamentsError) {
|
||||
return (
|
||||
<h1 style={{textAlign: 'center'}}>В избранном ничего нет :/</h1>
|
||||
)
|
||||
}
|
||||
|
||||
if (apartamentsError){
|
||||
return(
|
||||
<h1 style={{textAlign: 'center'}}>Произошла ошибка ({apartamentsError})</h1>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{isApartamentsLoading &&
|
||||
<h1 style={{textAlign: 'center'}}>Идет загрузка...</h1>
|
||||
}
|
||||
{apartaments.map((apartament, index) =>
|
||||
<>
|
||||
<CardApartament results={apartament}/>
|
||||
<div className="separationLine"></div>
|
||||
</>
|
||||
)}
|
||||
<Pagination page={page} changePage={changePage} totalPages={totalPages}/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default FavoritesApartamentsList;
|
|
@ -14,3 +14,54 @@ 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%);
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import CardSmallApartament from '../../components/CardSmallApartament/CardSmallApartament';
|
||||
import axios from 'axios';
|
||||
import './styles/LastView.css';
|
||||
|
||||
const LastView = function () {
|
||||
const [apartamentsLastView, setApartamentsLastView] = useState([])
|
||||
|
||||
async function fetchLastApartamentsView() {
|
||||
const response = await axios.get('http://127.0.0.1:8000/api/apartaments/')
|
||||
setApartamentsLastView(response.data.results)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
fetchLastApartamentsView()
|
||||
}, [])
|
||||
|
||||
return(
|
||||
<>
|
||||
<section className="viewedSection">
|
||||
<div className="viewedTittle">
|
||||
<h2>Недавно просмотренные <span>15</span></h2>
|
||||
<div className="viewedBtnSection">
|
||||
<button className="btnViewed">Посмотреть все Недавние</button>
|
||||
<div className="viewedBtn">
|
||||
<button className="btnPrevious">
|
||||
<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>
|
||||
</button>
|
||||
<button className="btnNext">
|
||||
<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>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="viewedBlock">
|
||||
{apartamentsLastView.map((apartament, index) =>
|
||||
<>
|
||||
<CardSmallApartament key={index} results={apartament}/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default LastView;
|
|
@ -0,0 +1,53 @@
|
|||
/*Недавно просмотренные*/
|
||||
.viewedSection{
|
||||
margin-top: 46px;
|
||||
}
|
||||
|
||||
.viewedTittle{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.viewedTittle h2{
|
||||
font-weight: 700;
|
||||
font-size: 20px;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.viewedTittle span{
|
||||
margin-left: 30px;
|
||||
font-size: 16px;
|
||||
color: #A9A9A9;
|
||||
}
|
||||
|
||||
/*Кнопки*/
|
||||
.viewedBtnSection{
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/*Кнопка "посмотреть все недавние"*/
|
||||
.btnViewed{
|
||||
width: 208px;
|
||||
height: 32px;
|
||||
margin-top: 15px;
|
||||
margin-right: 22px;
|
||||
background: #fff;
|
||||
border: 1px solid #CCCCCC;
|
||||
border-radius: 12px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
/*Кнопки "предыдущие" и "следующие"*/
|
||||
.viewedBtn{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/*Недавно просмотренные квартиры*/
|
||||
.viewedBlock{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 27px;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
import React from 'react';
|
||||
import {getPagesArray} from "../../../utils/Pages";
|
||||
|
||||
const Pagination = ({totalPages, page, changePage}) => {
|
||||
let pagesArray = getPagesArray(totalPages);
|
||||
let previousPage = page !== 1 ? page - 1 : page
|
||||
let nextPage = page < pagesArray.length ? page + 1 : page
|
||||
|
||||
return (
|
||||
<section className="btnSection">
|
||||
<button className="allBtn">Показать весь список</button>
|
||||
<div className="choiceBtn">
|
||||
<button onClick={() => changePage(previousPage)} className="btnPrevious">
|
||||
<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>
|
||||
</button>
|
||||
{pagesArray.map(p =>
|
||||
<button onClick={() => changePage(p)} key={p} className={page === p ? "pageBtn activePage" : "pageBtn"}>{p}</button>
|
||||
)}
|
||||
<button onClick={() => changePage(nextPage)} className="btnNext">
|
||||
<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>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Pagination;
|
|
@ -0,0 +1,19 @@
|
|||
import {useState} from "react";
|
||||
|
||||
export const useFetching = (callback) => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
|
||||
const fetching = async (...args) => {
|
||||
try {
|
||||
setIsLoading(true)
|
||||
await callback(...args)
|
||||
} catch (e) {
|
||||
setError(e.message);
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
return [fetching, isLoading, error]
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
export const getPageCount = (totalCount, limit) => {
|
||||
return Math.ceil(totalCount / limit)
|
||||
}
|
||||
|
||||
export const getPagesArray = (totalPages) => {
|
||||
let result = [];
|
||||
for (let i = 0; i < totalPages; i++) {
|
||||
result.push(i + 1)
|
||||
}
|
||||
return result;
|
||||
}
|
Loading…
Reference in New Issue