add basic tinder

This commit is contained in:
b1ek 2023-05-15 10:47:33 +10:00
parent 90cd5fe843
commit 8cabfeb1ba
Signed by: blek
GPG Key ID: 14546221E3595D0C
8 changed files with 362 additions and 16 deletions

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-gender-female" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 1a4 4 0 1 0 0 8 4 4 0 0 0 0-8zM3 5a5 5 0 1 1 5.5 4.975V12h2a.5.5 0 0 1 0 1h-2v2.5a.5.5 0 0 1-1 0V13h-2a.5.5 0 0 1 0-1h2V9.975A5 5 0 0 1 3 5z"/>
</svg>

After

Width:  |  Height:  |  Size: 316 B

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-gender-male" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M9.5 2a.5.5 0 0 1 0-1h5a.5.5 0 0 1 .5.5v5a.5.5 0 0 1-1 0V2.707L9.871 6.836a5 5 0 1 1-.707-.707L13.293 2H9.5zM6 6a4 4 0 1 0 0 8 4 4 0 0 0 0-8z"/>
</svg>

After

Width:  |  Height:  |  Size: 312 B

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-question-lg" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M4.475 5.458c-.284 0-.514-.237-.47-.517C4.28 3.24 5.576 2 7.825 2c2.25 0 3.767 1.36 3.767 3.215 0 1.344-.665 2.288-1.79 2.973-1.1.659-1.414 1.118-1.414 2.01v.03a.5.5 0 0 1-.5.5h-.77a.5.5 0 0 1-.5-.495l-.003-.2c-.043-1.221.477-2.001 1.645-2.712 1.03-.632 1.397-1.135 1.397-2.028 0-.979-.758-1.698-1.926-1.698-1.009 0-1.71.529-1.938 1.402-.066.254-.278.461-.54.461h-.777ZM7.496 14c.622 0 1.095-.474 1.095-1.09 0-.618-.473-1.092-1.095-1.092-.606 0-1.087.474-1.087 1.091S6.89 14 7.496 14Z"/>
</svg>

After

Width:  |  Height:  |  Size: 655 B

View File

@ -93,7 +93,7 @@ const ComparisonsApartmentsList = () => {
return (
<>
<PaginatedTitle title={"Сравнения квартир"} totalPages={totalPages} page={page} changePage={changePage}/>
<PaginatedTitle title={"Сравнения квартир"} totalPages={totalPages} page={page} changePage={changePage} displayPages={true} />
<ApartmentSection>
<ApartmentSectionTitle>
<ApartmentSectionTitleText style={{height:300}}>Фото</ApartmentSectionTitleText>

View File

@ -48,7 +48,7 @@ const ButtonPreviousAndNext = styled.button`
margin-right: 10px;
`;
const PaginatedTitle = function ({title, totalPages, page, changePage}) {
const PaginatedTitle = function ({title, totalPages, page, changePage, displayPages}) {
let [previousPage, nextPage] = getPreviousAndNextPage(totalPages, page);
return(
@ -64,12 +64,18 @@ const PaginatedTitle = function ({title, totalPages, page, changePage}) {
</TitleSectionLeftAndRight>
<TitleSectionLeftAndRight>
{
displayPages ?
<>
<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>
</>
: null
}
</TitleSectionLeftAndRight>
</TitleSection>
);

View File

@ -101,14 +101,16 @@ class Pagination extends React.Component {
value: props.value
}
this.value_controlled = props.onChange != undefined && props.value != undefined;
this.value_controlled = props.value != undefined;
this.updateValue = this.updateValue.bind(this);
}
updateValue(new_val) {
if (this.props.pages != 0) {
if (new_val < 0) new_val = 0;
if (new_val > this.props.pages)
new_val = this.props.pages;
}
this.props.onChange(new_val);
if (this.value_controlled)

View File

@ -0,0 +1,327 @@
import React from "react";
import styled, { keyframes } from 'styled-components';
import SVGIcon from "../../components/UI/Icon/SVGIcon";
import Pagination from "../../components/UI/Pagination";
const ChatSVG = () => {
return <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"><path d="M8 15c4.418 0 8-3.134 8-7s-3.582-7-8-7-8 3.134-8 7c0 1.76.743 3.37 1.97 4.6-.097 1.016-.417 2.13-.771 2.966-.079.186.074.394.273.362 2.256-.37 3.597-.938 4.18-1.234A9.06 9.06 0 0 0 8 15z"/></svg>;
}
const Box = styled.div`
box-shadow: 0 2px 1px #00000010;
border: 1px solid #c2c4c2;
border-radius: 14px;
`;
const BackButton = styled.button`
border: 1px solid #c2c4c2;
display: inline-block;
padding: 12px 16px;
border-radius: 14px;
background: #ffffff;
color: gray;
box-shadow: 0 2px 1px #00000010;
font-size: 12pt;
float: left;
& ${SVGIcon} {
transform: translate(-4px, 2px)
}
`;
const Title = styled.div`
text-align: center;
height: 100px;
padding-top: 32px;
z-index: 1;
position: relative;
top: 0;
& h2 {
font-weight: 600;
text-align: center;
padding: 0;
display: inline-block;
transform: translateY(6px);
}
`;
const FilterForm = styled.div`
display: inline-block;
float: right
`;
const FilterOption = styled(Box)`
display: inline-block;
border: 1px solid #c2c4c2;
border-radius: 14px;
padding: 6px 10px;
margin: 0 12px;
font-size: 11pt;
width: 160px;
& input[type=text] {
margin: 0 8px;
display: inline-block;
width: 20px;
border: 0;
border-bottom: 1px solid gray;
outline: none;
padding-bottom: 2px;
}
`;
const FilterSetting = styled.div`
border-top: 1px solid #c2c4c2;
margin-top: 6px;
padding-top: 8px;
font-size: 10pt;
transform: translate(4px)
`;
const FilterButton = styled.button`
background: royalblue;
width: 40px;
height: 40px;
border-radius: 20px;
float: right;
margin: 0 10px;
box-shadow: 0 2px 1px #00000020;
transition: 250ms ease;
transform: translateY(12px);
&:hover {
box-shadow: 0 2px 2px #00000060;
}
`;
const UserList = styled.div`
margin: 32px auto;
margin-bottom: 0;
display: block;
width: fit-content;
`;
const ContactButton = styled.button`
background: white;
border: 2px solid royalblue;
border-radius: 12px;
color: royalblue;
font-weight: 600;
line-height: 20px;
transition: 150ms ease;
width: 100%;
font-size: 10.5pt;
height: 36px;
opacity: 0;
padding: 0px 10px;
clip-path: border-box;
box-sizing: border-box;
& svg {
fill: royalblue;
margin: 0;
margin-right: 6px;
transform: translateY(2px);
}
&:hover {
color: white;
background: royalblue;
}
&:hover svg {
fill: white
}
`;
const UserAppear = keyframes`
0%, 50% {
opacity: 0;
transform: scale(1.05)
}
to {
opacity: 1;
transform: scale(1)
}
`;
const UserCard = styled(Box)`
display: inline-block;
padding: 10px;
padding-top: 20px;
background: white;
width: 200px;
height: 256px;
margin-right: 20px;
margin-bottom: 84px;
text-align: center;
animation: ${UserAppear} 500ms ease;
& h4 {
margin: 10px 0;
font-weight: 600;
}
& p {
margin: 10px 0;
height: 74px;
color: gray;
font-size: 10pt;
}
transition: 150ms ease;
&:hover > ${ContactButton} {
opacity: 1;
padding: 6px 10px;
}
&:hover {
height: 300px;
margin-bottom: 40px;
}
`;
const Badges = styled.div`
height: 0px;
`;
const LeftBadge = styled.div`
float: left;
transform: translate(90%, -100%);
background: lightgray;
border: 3px solid white;
border-radius: 100px;
width: 36px; height: 36px;
`;
const RightBadge = styled(LeftBadge)`
float: right;
transform: translate(-75%, -100%);
background: limegreen;
& p {
transform: translateY(6px);
font-size: 11pt;
font-weight: 600;
color: white;
text-shadow: 0 2px 1px #00000040;
margin: 0;
height: auto;
}
`;
class Users extends React.Component {
render() {
return (
<UserList>
<h2 style={{textAlign: 'center', lineHeight: '11pt', marginBottom: 32}}>
Выбери соседа
<br/>
<br/>
<span style={{ fontSize: '11pt', fontWeight: 500 }}>
Не забывай, с этим человеком<br/>
придется жить бок-о-бок!
</span>
</h2>
{
[...Array(11)].map((_, i) => {
if (i == 5) return <br/>;
return (
<UserCard>
<SVGIcon src='/images/icons/user.svg' width='100' height='100' />
<Badges>
<LeftBadge>
<SVGIcon src='/images/icons/question.svg' style={{margin: '5px 0'}} width='20' height='20' />
</LeftBadge>
<RightBadge>
<p>?</p>
</RightBadge>
</Badges>
<h4 className="inner-element">User, 0</h4>
<p>No description provided.</p>
<ContactButton>
<ChatSVG />
Перейти в чат
</ContactButton>
</UserCard>
);
})
}
</UserList>
)
}
}
class Filters extends React.Component {
render() {
return (
<FilterForm>
<FilterOption>
Совместимость
<FilterSetting>
от
<input type='text' />
до
<input type='text' />
</FilterSetting>
</FilterOption>
<FilterOption>
Возраст
<FilterSetting>
от
<input type='text' />
до
<input type='text' />
</FilterSetting>
</FilterOption>
<FilterButton>
<SVGIcon src='/images/icons/search.svg' width='18' height='18' />
</FilterButton>
</FilterForm>
);
}
}
export default class Tinder extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<>
<Title>
<BackButton>
<SVGIcon src='/images/icons/left-arrow-light.svg' width={10} height={16}/>
Вернуться назад
</BackButton>
<Filters />
</Title>
<div style={{transform: 'translateY(-100px)', position: 'relative', top:0, zIndex: 0}}>
<Users />
<Pagination pages={0} />
</div>
</>
);
}
}

View File

@ -2,6 +2,7 @@ import Favorites from "../pages/Favorites";
import Comparisons from "../pages/Comparisons";
import IndexApartment from "../pages/IndexApartment";
import IndexPage from "../pages/IndexPage";
import Tinder from "../pages/Tinder";
// НА ПРОДАШКЕНЕ СДЕЛАТЬ ПРИВАТНЫЕ МАРШРУТЫ
// export const privateRoutes = [
@ -11,10 +12,11 @@ import IndexPage from "../pages/IndexPage";
export default Object.freeze({
publicRoutes: [
{path: '/', component: <IndexPage />, exact: true},
{path: '/apartment/:id', component: <IndexApartment />, exact: true},
{path: '/favorites', component: <Favorites />, exact: true},
{path: '/comparisons', component: <Comparisons />, exact: true},
{ path: '/', component: <IndexPage />, exact: true },
{ path: '/apartment/:id', component: <IndexApartment />, exact: true },
{ path: '/favorites', component: <Favorites />, exact: true },
{ path: '/comparisons', component: <Comparisons />, exact: true },
{ path: '/tinder', component: <Tinder />, exact: true }
],
privateRoutes: []
})