Skip to content

Commit

Permalink
Merge pull request #48 from ehdrhelr/fe/feature/reserveForm
Browse files Browse the repository at this point in the history
[FE]예약 폼 모달
  • Loading branch information
hayoung123 authored Jun 2, 2021
2 parents b2d3802 + b8d0dd4 commit ad49712
Show file tree
Hide file tree
Showing 21 changed files with 409 additions and 34 deletions.
1 change: 1 addition & 0 deletions FE/airbnb/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
</head>
<body>
<div id="root"></div>
<div id="modal"></div>
</body>
</html>
4 changes: 1 addition & 3 deletions FE/airbnb/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ function App() {
<MainPage />
</Route>
<Route path='/accommodations'>
<Suspense fallback='loading'>
<ReservePage />
</Suspense>
<ReservePage />
</Route>
</Router>
</StyledApp>
Expand Down
2 changes: 0 additions & 2 deletions FE/airbnb/src/components/header/form/FormGuest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import FormGuestToggle from './guestToggle/FormGuestToggle';
import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil';
import { guestState, isFormOpenedState, reserveInfoSelector } from '../../../recoil/headerAtom';
import { ReactComponent as DeleteBtn } from '../../../assets/svg/Property 1=x-circle.svg';
import { Link } from 'react-router-dom';
import ConditionalLink from '../../util/ConditionalLink';
import { reserveInfoType, clientReserveAPI } from '../../../util/api';

Expand Down Expand Up @@ -45,7 +44,6 @@ const FormGuest = () => {
};

const handleSubmitClick = (e: MouseEvent): void => {
console.log(reserveInfo);
e.stopPropagation();
};

Expand Down
8 changes: 6 additions & 2 deletions FE/airbnb/src/components/header/form/FormPrice.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MouseEvent, useEffect, useRef } from 'react';
import { MouseEvent, Suspense, useEffect, useRef } from 'react';
import { useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil';
import styled from 'styled-components';
import useToggle from '../../../hooks/useToggle';
Expand Down Expand Up @@ -54,7 +54,11 @@ const FormPrice = () => {
{isShowDeleteBtn && open && <DeleteBtn onClick={handleDeleteClick} />}
</HoverBlock>
</StyledFormPrice>
{open && <PriceBar toggleRef={toggleRef} />}
{open && (
<Suspense fallback='loading...'>
<PriceBar toggleRef={toggleRef} />
</Suspense>
)}
</StyledFormPriceWrapper>
);
};
Expand Down
5 changes: 4 additions & 1 deletion FE/airbnb/src/components/header/form/priceBar/PriceBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import PriceChart from './PriceChart';
import { btnPositionType, priceSectionType } from './priceType';
import { ReactComponent as PauseBtn } from '../../../../assets/svg/Property 1=pause-circle.svg';
import { priceData as sampleData } from './sampleData';
import { useRecoilState } from 'recoil';
import { useRecoilState, useRecoilValue } from 'recoil';
import {
fetchPrice,
pauseBtnLastPositionState,
pauseBtnPositionState,
priceState,
Expand All @@ -32,7 +33,9 @@ const PriceBar = ({ toggleRef }: Props) => {
const [btnLastPosition, setBtnLastPosition] = useRecoilState(pauseBtnLastPositionState);
const [priceRange, setPriceRange] = useRecoilState(priceState);
const [priceData, setPriceData] = useState(sampleData);
// const priceData = useRecoilValue(fetchPrice);

console.log(priceData);
const minPrice = getNumberWithComma(priceRange.min);
const maxPrice = getNumberWithComma(priceRange.max);
const priceAverage = getNumberWithComma(getPriceAverage(priceData));
Expand Down
6 changes: 2 additions & 4 deletions FE/airbnb/src/components/header/form/priceBar/PriceChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ const PriceChart = ({ priceSection }: Props) => {

const drawDotsLine = (dots: dotType[]): void => {
if (!canvas || !ctx) return;
const canvasWidth = canvas.width;
const canvasHeight = canvas.height;
ctx.beginPath();
ctx.fillStyle = 'rgba(0,0,0,0.7)';

Expand All @@ -53,9 +51,9 @@ const PriceChart = ({ priceSection }: Props) => {
}

ctx.lineTo(prevX, prevY);
ctx.lineTo(canvasWidth, canvasHeight);
ctx.lineTo(0, canvasHeight);
ctx.fill();
ctx.strokeStyle = 'rgba(0,0,0,0.3)';
ctx.stroke();
ctx.closePath();
};

Expand Down
38 changes: 38 additions & 0 deletions FE/airbnb/src/components/reservePageSkeleton/MapSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import styled from 'styled-components';

interface Props {}

const MapSkeleton = (props: Props) => {
return <StyledMapSkeleton className='skeleton-screen'>loading</StyledMapSkeleton>;
};

export default MapSkeleton;

const StyledMapSkeleton = styled.div`
background-color: #f2f2f2;
position: absolute;
right: 0;
width: 50%;
height: 100%;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(to right, #f2f2f2, #ddd, #f2f2f2);
animation: loading 1s infinite linear;
}
@keyframes loading {
0% {
transform: translateX(0);
}
50%,
100% {
transform: translateX(460px);
}
}
`;
25 changes: 25 additions & 0 deletions FE/airbnb/src/components/reservePageSkeleton/ReserveSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import styled from 'styled-components';

interface Props {}

const ReserveSkeleton = (props: Props) => {
return (
<StyledReserveSkeleton>
<div className='skeleton__img'></div>
<div className='skeleton__desc'>
<div className='skeleton__info'></div>
<div className='skeleton__price'></div>
</div>
</StyledReserveSkeleton>
);
};

export default ReserveSkeleton;

const StyledReserveSkeleton = styled.div`
.skeleton__img,
.skeleton__info,
.skeleton__price {
background-color: f2f2f2;
}
`;
15 changes: 7 additions & 8 deletions FE/airbnb/src/components/reserveRoomList/ReserveRoom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,21 @@ import { roomType } from './roomType';
import ReserveRoomGrade from './ReserveRoomGrade';
import ReserveRoomPrice from './ReserveRoomPrice';
import ReserveForm from './reserveForm/ReserveForm';
import { useState } from 'react';
import { useRef } from 'react';
import useToggle from '../../hooks/useToggle';

interface Props {
roomData: roomType;
}

const ReserveRoom = ({ roomData }: Props) => {
const [open, setOpen] = useState(false);
const { photo } = roomData;

const handleClick = () => {
setOpen(true);
};
const clickRef = useRef(null);
const toggleRef = useRef(null);
const { open } = useToggle({ clickRef, toggleRef });

return (
<StyledReserveRoom onClick={handleClick}>
<StyledReserveRoom ref={clickRef}>
<div className='room__img'>
<img src={photo} alt='' />
</div>
Expand All @@ -34,7 +33,7 @@ const ReserveRoom = ({ roomData }: Props) => {
<ReserveRoomPrice roomData={roomData} />
</div>
</div>
{open && <ReserveForm roomData={roomData} />}
{open && <ReserveForm toggleRef={toggleRef} roomData={roomData} />}
</StyledReserveRoom>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const ReserveRoomList = ({ className }: Props) => {
const reserveRoomList =
roomsData &&
roomsData.map((roomData, idx) => <ReserveRoom key={roomData.id + idx} roomData={roomData} />);
// const reserveRoomList = roomsData && roomsData.map((roomData, idx) => <ReserveSkeleton />);
return (
<StyledReserveRoomList className={className}>
<div className='data__info'>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import styled from 'styled-components';

interface Props {
className: string;
}

const ReserveBtn = ({ className }: Props) => {
return <StyledReserveBtn className={className}>예약하기</StyledReserveBtn>;
};

export default ReserveBtn;

const StyledReserveBtn = styled.button`
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 55px;
border: none;
border-radius: 10px;
background-color: ${({ theme }) => theme.colors.black};
color: ${({ theme }) => theme.colors.white};
font-weight: 700;
`;
Original file line number Diff line number Diff line change
@@ -1,29 +1,74 @@
import { RefObject } from 'react';
import styled from 'styled-components';
import { roomType } from '../roomType';
import ReserveBtn from './ReserveBtn';
import ReserveFormHeader from './ReserveFormHeader';
import ReserveFormInfo from './ReserveFormInfo';
import ReserveFromPrice from './ReserveFromPrice';
import { createPortal } from 'react-dom';
import usePortal from '../../../hooks/usePortal';

interface Props {
toggleRef: RefObject<HTMLDivElement>;
roomData: roomType;
}

const ReserveForm = ({ roomData }: Props) => {
const ReserveForm = ({ toggleRef, roomData }: Props) => {
const { chargePerNight } = roomData;
const portalElement: HTMLDivElement | null = document.querySelector('#modal');
return (
<StyledReserveFormWrapper>
<StyledReserveForm>123</StyledReserveForm>;
</StyledReserveFormWrapper>
portalElement &&
createPortal(
<StyledReserveFormWrapper>
<StyledReserveForm ref={toggleRef}>
<ReserveFormHeader
className='reserve__header'
chargePerNight={chargePerNight}
review={127}
/>
<ReserveFormInfo className='reserve__info' />
<ReserveBtn className='reserve__btn' />
<div className='reserve__warn'>예약 확정 전에는 요금이 청구되지 않습니다.</div>
<ReserveFromPrice chargePerNight={chargePerNight} />
</StyledReserveForm>
</StyledReserveFormWrapper>,
portalElement
)
);
};

export default ReserveForm;

const StyledReserveFormWrapper = styled.div`
z-index: 10;
position: absolute;
position: fixed;
top: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(0, 0, 0, 0.3);
`;

const StyledReserveForm = styled.div`
padding: 36px 24px;
width: 400px;
height: 500px;
background-color: green;
height: 525px;
background-color: ${({ theme }) => theme.colors.white};
border-radius: 10px;
box-shadow: 0px 4px 10px rgba(51, 51, 51, 0.1), 0px 0px 4px rgba(51, 51, 51, 0.05);
.reserve__header {
margin-bottom: 1.5rem;
}
.reserve__info,
.reserve__btn,
.reserve__warn {
margin-bottom: 1rem;
}
.reserve__warn {
text-align: center;
font-size: ${({ theme }) => theme.fontSize.small};
color: ${({ theme }) => theme.colors.gray3};
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import styled from 'styled-components';

interface Props {
className?: string;
chargePerNight: number;
review: number;
}

const ReserveFormHeader = ({ className, chargePerNight, review }: Props) => {
return (
<StyledReserveFormHeader className={className}>
<div>
<span className='price'>{chargePerNight.toLocaleString()}</span>
<span> / 박</span>
</div>
<div>
<span className='review'>후기 {review}</span>
</div>
</StyledReserveFormHeader>
);
};

export default ReserveFormHeader;

const StyledReserveFormHeader = styled.div`
display: flex;
align-items: flex-end;
justify-content: space-between;
.price {
font-size: ${({ theme }) => theme.fontSize.large};
font-weight: bold;
}
.review {
font-size: ${({ theme }) => theme.fontSize.small};
color: ${({ theme }) => theme.colors.gray3};
text-decoration: underline;
}
`;
Loading

0 comments on commit ad49712

Please sign in to comment.