Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FE] 새로운 방 비교 페이지를 퍼블리싱하고 비교 지도를 만든다. #958

Merged
merged 14 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions frontend/src/apis/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export const ENDPOINT = {
CHECKLIST_CUSTOM: '/custom-checklist',
CHECKLIST_ID: (id: number) => `/checklists/${id}`,
CHECKLIST_ID_V1: (id: number) => `/v1/checklists/${id}`,
//compare
CHECKLIST_COMPARE: (roomId1: number, roomId2: number) => `/v1/checklists/compare?id=${roomId1}&id=${roomId2}`,

// like
LIKE: (id: number | ':id') => `/checklists/${id}/like`,
Expand Down
11 changes: 11 additions & 0 deletions frontend/src/assets/assets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ import Retry from '@/assets/icons/common/retry.svg';
import SmallCheck from '@/assets/icons/common/small-check.svg';
import PlusBlack from '@/assets/icons/plusMinus/plus-black.svg';
import PlusWhite from '@/assets/icons/plusMinus/plus-white.svg';

//face-icon
import FaceBadIcon from '@/assets/icons/faceIcon/face-icon-bad.svg';
import FaceGoodIcon from '@/assets/icons/faceIcon/face-icon.good.svg';
import FaceNoneIcon from '@/assets/icons/faceIcon/face-icon.none.svg';
import FaceSosoIcon from '@/assets/icons/faceIcon/face-icon.soso.svg';

// room
import Building from '@/assets/icons/room/building.svg';
import Calendar from '@/assets/icons/room/calendar.svg';
Expand Down Expand Up @@ -77,6 +84,10 @@ export {
DropdownMark,
Error404,
Error500,
FaceBadIcon,
FaceGoodIcon,
FaceNoneIcon,
FaceSosoIcon,
Comment on lines +87 to +90
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

돌아온 얼굴들,,,

Copy link
Contributor Author

@ooherin ooherin Nov 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ㅎㅎㅎㅋㅋ죽지 않고 돌아온~~

InputRequiredDot,
KakaoLogo,
LampIcon,
Expand Down
11 changes: 9 additions & 2 deletions frontend/src/assets/icons/answer/bad.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
const Bad = ({ color, ...rest }: React.SVGProps<SVGSVGElement>) => {
const Bad = ({ color, width, ...rest }: React.SVGProps<SVGSVGElement>) => {
return (
<svg {...rest} width="27" height="28" viewBox="0 0 27 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<svg
{...rest}
width={width ?? '29'}
height={width ?? '29'}
viewBox="0 0 27 28"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M13.5 10.6495L4.41601 1.19969L4.41595 1.19964C3.98849 0.755098 3.40445 0.501547 2.79113 0.501547C2.17782 0.501547 1.59377 0.755098 1.16631 1.19964C0.73948 1.64351 0.502975 2.2415 0.502975 2.86112C0.502975 3.48071 0.73946 4.07867 1.16625 4.52254C1.16627 4.52256 1.16629 4.52258 1.16631 4.5226L10.2775 14.0007L1.16339 23.4758L1.16333 23.4759C0.736505 23.9197 0.5 24.5177 0.5 25.1373C0.5 25.757 0.736506 26.3549 1.16333 26.7988C1.5908 27.2434 2.17484 27.4969 2.78816 27.4969C3.40144 27.4969 3.98546 27.2434 4.41292 26.7989C4.41294 26.7989 4.41296 26.7988 4.41298 26.7988L13.4999 17.352L22.584 26.8019L22.584 26.8019C23.0115 27.2464 23.5956 27.5 24.2089 27.5C24.8222 27.5 25.4062 27.2464 25.8337 26.8019C26.2605 26.358 26.497 25.76 26.497 25.1404C26.497 24.5208 26.2605 23.9228 25.8337 23.4789L16.7224 14.0008L25.8367 4.52105C26.2635 4.07718 26.5 3.47919 26.5 2.85957C26.5 2.23995 26.2635 1.64196 25.8367 1.19809C25.4092 0.75355 24.8252 0.5 24.2118 0.5C23.5985 0.5 23.0145 0.75355 22.587 1.19809L22.587 1.19812L13.5 10.6495Z"
fill={color}
Expand Down
11 changes: 9 additions & 2 deletions frontend/src/assets/icons/answer/good.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
const Good = ({ color, ...rest }: React.SVGProps<SVGSVGElement>) => {
const Good = ({ color, width, ...rest }: React.SVGProps<SVGSVGElement>) => {
return (
<svg {...rest} width="29" height="29" viewBox="0 0 29 29" fill="none" xmlns="http://www.w3.org/2000/svg">
<svg
{...rest}
width={width ?? '29'}
height={width ?? '29'}
viewBox="0 0 29 29"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="14.5" cy="14.5" r="12" stroke={color} strokeWidth="5" />
</svg>
);
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/assets/icons/faceIcon/face-icon-bad.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions frontend/src/assets/icons/faceIcon/face-icon.good.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions frontend/src/assets/icons/faceIcon/face-icon.none.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions frontend/src/assets/icons/faceIcon/face-icon.soso.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions frontend/src/components/RoomCompare/CategoryDetailModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Modal from '@/components/_common/Modal/Modal';

interface Props {
isOpen: boolean;
closeModal: () => void;
}

const CategoryDetailModal = ({ isOpen, closeModal }: Props) => {
return (
<Modal isOpen={isOpen} onClose={closeModal}>
<Modal.header>카테고리 비교</Modal.header>
<Modal.body>
<div>카테고리 비교 내용이 들어갑니다.</div>
</Modal.body>
</Modal>
);
};

export default CategoryDetailModal;
53 changes: 53 additions & 0 deletions frontend/src/components/RoomCompare/CategoryScore.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import styled from '@emotion/styled';

import FaceIcon from '@/components/_common/FaceIcon/FaceIcon';
import FlexBox from '@/components/_common/FlexBox/FlexBox';
import { MIN_GOOD_SCORE, MIN_SOSO_SCORE } from '@/constants/system';
import { boxShadow, flexCenter } from '@/styles/common';

interface Props {
roomId: number;
categoryId: number;
score: number | null;
openCategoryModal: (roomId: number, categoryId: number) => void;
}

const CategoryScore = ({ roomId, categoryId, score, openCategoryModal }: Props) => {
const calcFaceIcon = (score: number | null) => {
if (score === null) return 'NONE';
if (score >= MIN_GOOD_SCORE) return 'GOOD';
if (score >= MIN_SOSO_SCORE) return 'SOSO';
return 'BAD';
};

return (
<FlexBox.Vertical>
<S.CategoryItemBox>
<FaceIcon emotion={calcFaceIcon(score)} />
</S.CategoryItemBox>
<S.CategoryItemBox>
<S.Score onClick={() => openCategoryModal(roomId, categoryId)}>{score === null ? '-' : `${score}%`}</S.Score>
</S.CategoryItemBox>
</FlexBox.Vertical>
);
};

export default CategoryScore;

const S = {
CategoryItemBox: styled.div`
width: 7rem;

${flexCenter}
text-align: center;
`,
Score: styled.span`
width: 4rem;
padding: 6px 8px;
border: 1px solid ${({ theme }) => theme.palette.grey300};

font-size: ${({ theme }) => theme.text.size.small};
border-radius: 8px;
${boxShadow}
`,
};
100 changes: 100 additions & 0 deletions frontend/src/components/RoomCompare/CompareCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import styled from '@emotion/styled';

import SubwayStations from '@/components/_common/Subway/SubwayStations';
import CategoryScore from '@/components/RoomCompare/CategoryScore';
import CompareCardItem from '@/components/RoomCompare/CompareCardItem';
import { EMPTY_INDICATOR } from '@/constants/system';
import { boxShadow, flexColumn, title1, title4 } from '@/styles/common';
import { ChecklistCompare } from '@/types/checklistCompare';

interface Props {
room: ChecklistCompare;
index: number;
openOptionModal: () => void;
openCategoryModal: (roomId: number, categoryId: number) => void;
}

const CompareCard = ({ room, openOptionModal, openCategoryModal }: Props) => {
return (
<S.Container>
<CompareCardItem height={7} label={'주소'} item={<S.Item>{room.address}</S.Item>} />
<CompareCardItem label={'층수'} item={<S.Item>{room.floor ? `${room.floor}층` : EMPTY_INDICATOR}</S.Item>} />
<CompareCardItem
label={'보증금 / 월세'}
item={
<S.Item>
{room.deposit ?? EMPTY_INDICATOR}/{room.rent ?? EMPTY_INDICATOR}
</S.Item>
}
/>
<CompareCardItem
label={'방 구조 / 방 평수'}
item={
<S.Item>{`${room.structure ?? EMPTY_INDICATOR}/${room.size ? `${room.size}평` : EMPTY_INDICATOR}`}</S.Item>
}
/>
<CompareCardItem label={'계약기간'} item={<S.Item>{room.contractTerm}개월</S.Item>} />
<CompareCardItem
label={'가까운 지하철'}
item={<SubwayStations size={'small'} stations={room.nearSubwayStations} />}
/>
<CompareCardItem
label={'옵션'}
item={<S.OptionButton onClick={openOptionModal}>{room.options.length}개</S.OptionButton>}
/>
{/*카테고리별 질문 평점 섹션*/}
{room.categories.map(category => (
<CompareCardItem
key={category.categoryId}
label={category.categoryName}
item={
<CategoryScore
roomId={room.checklistId}
categoryId={category.categoryId}
score={category.score}
openCategoryModal={openCategoryModal}
/>
}
/>
))}
</S.Container>
);
};

export default CompareCard;

const S = {
Container: styled.div`
width: 100%;
padding: 20px 4px;
box-sizing: border-box;
${flexColumn};
align-items: center;
gap: 30px;
`,
RankWrapper: styled.div`
${flexColumn}
gap: 5px;
`,
Rank: styled.div`
${title1}
`,
Item: styled.div`
display: flex;
width: 100%;

font-size: ${({ theme }) => theme.text.size.small};
line-height: 1.5;
letter-spacing: 0.05rem;
text-align: center;
justify-content: center;
word-break: keep-all;
`,
OptionButton: styled.button`
${title4}
padding: 12px 16px;
border: 1px solid ${({ theme }) => theme.palette.grey300};
border-radius: 8px;
${boxShadow}
`,
};
51 changes: 51 additions & 0 deletions frontend/src/components/RoomCompare/CompareCardCategoryItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import styled from '@emotion/styled';
import React from 'react';

import { flexCenter, flexColumn } from '@/styles/common';

interface Props {
label?: string;
isLabeled?: boolean;
item: React.ReactNode;
height?: number;
score: number;
}

const CompareCardItem = ({ label, isLabeled = false, item, height, score }: Props) => {
return (
<S.ItemContainer height={height}>
<S.Label isLabeled={isLabeled}>{label}</S.Label>
<S.ItemText>{item}</S.ItemText>
<S.Score>{score}%</S.Score>
</S.ItemContainer>
);
};

export default CompareCardItem;

const S = {
ItemContainer: styled.div<{ height?: number }>`
width: 100%;
height: ${({ height }) => height && height}rem;
${flexColumn};
gap: 1rem;
align-items: center;
`,
ItemText: styled.div`
height: 100%;

${flexCenter};
font-size: ${({ theme }) => theme.text.size.small};
line-height: 1.5rem;
`,
Score: styled.div`
font-size: ${({ theme }) => theme.text.size.xSmall};
`,
Label: styled.div<{ isLabeled: boolean }>`
height: 1.5rem;
margin-bottom: 0.5rem;

color: ${({ theme }) => theme.palette.grey500};
font-size: ${({ theme }) => theme.text.size.xSmall};
`,
};
49 changes: 49 additions & 0 deletions frontend/src/components/RoomCompare/CompareCardItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import styled from '@emotion/styled';
import React from 'react';

import { flexCenter, flexColumn } from '@/styles/common';

interface Props {
label?: string;
isLabeled?: boolean;
item: React.ReactNode;
height?: number;
}

const CompareCardItem = ({ label, isLabeled = false, item, height }: Props) => {
return (
<S.ItemContainer height={height}>
<S.Label isLabeled={isLabeled}>{label}</S.Label>
<S.ItemText>{item}</S.ItemText>
</S.ItemContainer>
);
};

export default CompareCardItem;

const S = {
ItemContainer: styled.div<{ height?: number }>`
width: 100%;
height: ${({ height }) => height && height}rem;
${flexColumn};
gap: 1rem;
align-items: center;
`,
ItemText: styled.div`
height: 100%;

${flexCenter};
font-size: ${({ theme }) => theme.text.size.small};
line-height: 1.5rem;
`,
Score: styled.div`
font-size: ${({ theme }) => theme.text.size.xSmall};
`,
Label: styled.div<{ isLabeled: boolean }>`
height: 1.5rem;
margin-bottom: 0.5rem;

color: ${({ theme }) => theme.palette.grey500};
font-size: ${({ theme }) => theme.text.size.xSmall};
`,
};
Loading
Loading