Skip to content

Commit

Permalink
[feat] data fetching 리뷰 상세 / 작성 (#67)
Browse files Browse the repository at this point in the history
* .

* feat: data fetching review
  • Loading branch information
choipureum authored Jan 10, 2023
1 parent e18d28a commit e31f303
Show file tree
Hide file tree
Showing 36 changed files with 389 additions and 305 deletions.
5 changes: 0 additions & 5 deletions cypress/e2e/3-review/edit.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ describe('리뷰 edit 페이지 테스트', () => {
});
context('form 기능 테스트', () => {
it('데이터 입력 및 등록 버튼 누를 시 정상적으로 응답해야 한다.', () => {
cy.get('.review--select__theme').click();
cy.wait(300);
cy.get('.review--select__theme > ul > li:nth-child(3)').click();
cy.get('.review .chips--item__2').click();
cy.get(
'section.review--form > div:nth-child(2) > div > button:nth-child(3)'
).click();
Expand All @@ -40,7 +36,6 @@ describe('리뷰 edit 페이지 테스트', () => {
'have.text',
'12 / 240'
);
cy.get('.review--form > .review--form__submit').click();
});
});
});
Expand Down
2 changes: 0 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import CertifyEditPage from '@pages/certify/edit';
import DetailPage from '@pages/detail';
import MyAccountPage from '@pages/myAccount';
import LikeListPage from '@pages/myAccount/like';
import TypiCodePage from '@pages/typiCode';
import NotFoundPage from '@pages/NotFound';
import GlobalStyle from '@styles/Global';

Expand All @@ -36,7 +35,6 @@ function App() {
<Header />
<GlobalStyle />
<Routes>
<Route path="typicode" element={<TypiCodePage />} />
<Route index element={<CafeListPage />} />
<Route
path="review/detail/:themeId"
Expand Down
38 changes: 24 additions & 14 deletions src/components/atom/LikeBtn/index.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,45 @@
import styled from '@emotion/styled';
import { Like } from '@src/assets/svg/icon';
import { useState } from 'react';
import { CustomTheme as theme } from '@styles/Theme';

const POSITION_ENUM = {
BOTTOM: 'bottom',
RIGHT: 'right',
};

interface Props {
isLiked: boolean;
count: number;
position?: string | undefined;
}

export default function LikeBtn({ isLiked, count }: Props) {
const [active, setActive] = useState(isLiked);
const [reviewCount, setReviewCount] = useState(count);

export default function LikeBtn({
isLiked,
count,
position = POSITION_ENUM.BOTTOM,
}: Props) {
const likeColor = () =>
active ? theme.color.primary.purple : theme.color.grayscale.gray_300;

const likeHandler = () => {
setActive(!active);
setReviewCount(active ? count : count + 1);
};
isLiked ? theme.color.primary.purple : theme.color.grayscale.gray_300;

return (
<LikeBtnWrapper onClick={likeHandler}>
<LikeBtnWrapper position={position}>
<Like fill={likeColor()} className="like--btn" />
<ReviewLikeCount isLiked={active}>{reviewCount}</ReviewLikeCount>
<ReviewLikeCount isLiked={isLiked}>{count}</ReviewLikeCount>
</LikeBtnWrapper>
);
}

const LikeBtnWrapper = styled.button`
const LikeBtnWrapper = styled.button<{ position: string }>`
cursor: pointer;
display: ${(props) =>
props.position === POSITION_ENUM.RIGHT ? 'flex' : 'relative'};
p {
margin-top: ${(props) =>
props.position === POSITION_ENUM.RIGHT ? '5px' : '0px'};
margin-left: ${(props) =>
props.position === POSITION_ENUM.RIGHT ? '4px' : '0px'};
}
&:hover {
.like--btn {
Expand Down
1 change: 1 addition & 0 deletions src/components/atom/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { default as BoldTextSpan } from './BoldTextSpan';
export { default as Button } from './Button';
export { default as LikeBtn } from './LikeBtn';
export { default as LoadingSpinner } from './LoadingSpinner';
21 changes: 9 additions & 12 deletions src/components/blocks/Menu/index.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,27 @@
import React, { useEffect, useState } from 'react';
import React, { useEffect, useState, Dispatch, SetStateAction } from 'react';
import { MenuListItemType } from '@src/types/common';
import * as S from './style';
import { DownArrow, UpArrow } from '../../../assets/svg/icon';

type MenuPropsType = {
list: MenuListItemType[];
onClickItem?: () => void;
setSelectedOption: Dispatch<SetStateAction<string>>;
};

export default function Menu({ list, onClickItem }: MenuPropsType) {
export default function Menu({ list, setSelectedOption }: MenuPropsType) {
const [isOpen, setIsOpen] = useState(false);
const [selectedItem, setSelectedItem] = useState<string>();
const [selectedItemId, setSelectedItemId] = useState<number | null>(0);
const [selectedItem, setSelectedItem] = useState<string | null>('');

function menuBtnClick() {
setIsOpen(!isOpen);
}
const menuBtnClick = () => setIsOpen(!isOpen);

function getItemId(e: React.MouseEvent<HTMLLIElement, MouseEvent>) {
setSelectedItemId(+e.currentTarget.id);
}

function itemClick(e: React.MouseEvent<HTMLButtonElement>) {
setSelectedItem(e.currentTarget.innerText);

if (onClickItem) onClickItem();
function itemClick(el: MenuListItemType) {
setSelectedItem(el.name);
setSelectedOption(el.value || '');
setIsOpen(false);
}

Expand All @@ -50,7 +47,7 @@ export default function Menu({ list, onClickItem }: MenuPropsType) {
onClick={(e) => getItemId(e)}
aria-hidden="true"
>
<S.MenuItem onClick={(e) => itemClick(e)} type="button">
<S.MenuItem onClick={() => itemClick(el)} type="button">
{el.name}
</S.MenuItem>
</li>
Expand Down
4 changes: 4 additions & 0 deletions src/components/blocks/SelectBox/index.style.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ const Select = styled.select`
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
:disabled {
background-color: ${({ theme }) => `${theme.color.grayscale.gray_500}`};
}
`;

const SelectButton = styled.button`
Expand Down
12 changes: 9 additions & 3 deletions src/components/blocks/SelectBox/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,19 @@ interface Props {
options: ReviewThemeType[];
selectedOption: string;
setSelectedOption: Dispatch<SetStateAction<string>>;
disabled?: boolean;
width: string | number;
maxHeight: number;
name: string;
handleSelectOptionClick: any;
handleSelectOptionClick?: any;
[x: string]: any;
}

export default function SelectBox({
options,
selectedOption,
setSelectedOption,
disabled = false,
width,
maxHeight,
name,
Expand All @@ -44,7 +46,7 @@ export default function SelectBox({
const handleOpenSelectBox = (e: TouchEvent | MouseEvent) => {
e.preventDefault();
const target = e.target as HTMLLabelElement;
let state = true;
let state = !disabled;

if (clickSelectedBox && target.nodeName === 'SELECT') state = !state;

Expand Down Expand Up @@ -76,7 +78,11 @@ export default function SelectBox({
className="review--select__theme"
>
<SelectContainer>
<Select value={selectedOption} onChange={handleSelectBox}>
<Select
value={selectedOption}
onChange={handleSelectBox}
disabled={disabled}
>
{options.map((option) => (
<option key={option.themeId} value={option.title}>
{option.title}
Expand Down
4 changes: 2 additions & 2 deletions src/components/blocks/UserInfo/index.style.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const ReviewUserInfoBlock = styled.div`
}
`;

const ReviewUserNickName = styled.span`
const ReviewUserLevel = styled.span`
color: ${({ theme }) => theme.color.legacyGrayscale.gray_700};
`;

Expand Down Expand Up @@ -79,7 +79,7 @@ export {
ReviewUserThemeGenre,
ReviewUserInfo,
ReviewUserInfoBlock,
ReviewUserNickName,
ReviewUserLevel,
ReviewUserBadge,
ReviewModifiedAt,
ReviewReport,
Expand Down
28 changes: 22 additions & 6 deletions src/components/blocks/UserInfo/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { useCallback } from 'react';
import { generateUUID } from '@src/lib/util';
import { UserInfoType } from '@src/types/review';
import { BoldTextSpan, LikeBtn } from '@components/atom';
import { ROLE_USER_RANK } from '@constants/common';
import { CustomTheme as theme } from '@src/styles/Theme';
import { useReviewLikeMutation } from '@hooks/queries/review';
import {
ReviewUserInfoSection,
ReviewUserInfoContainer,
Expand All @@ -11,14 +13,28 @@ import {
ReviewUserThemeGenre,
ReviewUserInfo,
ReviewUserInfoBlock,
ReviewUserNickName,
ReviewUserLevel,
ReviewUserBadge,
ReviewModifiedAt,
ReviewReport,
ReviewLikeContainer,
} from './index.style';

export default function UserInfo({ userInfo }: { userInfo: UserInfoType }) {
export default function UserInfo({
userInfo,
contentId,
}: {
userInfo: UserInfoType;
contentId: number;
}) {
const { mutate: handleLikeMutate } = useReviewLikeMutation({
reviewId: contentId,
});

const handleLikeClick = useCallback(() => {
handleLikeMutate();
}, [handleLikeMutate]);

const getBadgeColorHex = (level: string) => {
if (level === 'LEVEL1') return theme.color.primary.green;
if (level === 'LEVEL2') return theme.color.primary.kakao;
Expand Down Expand Up @@ -46,11 +62,11 @@ export default function UserInfo({ userInfo }: { userInfo: UserInfoType }) {
</ReviewUserTheme>
<ReviewUserInfo>
<ReviewUserInfoBlock>
<ReviewUserNickName>{userInfo.writerNickname}</ReviewUserNickName>
<ReviewUserLevel>{userInfo.writerNickname}</ReviewUserLevel>
<ReviewUserBadge
color={getBadgeColorHex(ROLE_USER_RANK[userInfo.nickname])}
color={getBadgeColorHex(ROLE_USER_RANK[userInfo.writerLevel])}
>
{userInfo.nickname}
{userInfo.writerLevel}
</ReviewUserBadge>
</ReviewUserInfoBlock>
<ReviewUserInfoBlock>
Expand All @@ -61,7 +77,7 @@ export default function UserInfo({ userInfo }: { userInfo: UserInfoType }) {
</ReviewUserInfoBlock>
</ReviewUserInfo>
</ReviewUserInfoContainer>
<ReviewLikeContainer>
<ReviewLikeContainer onClick={handleLikeClick}>
<LikeBtn isLiked={userInfo.isLiked} count={userInfo.likeCount} />
</ReviewLikeContainer>
</ReviewUserInfoSection>
Expand Down
Loading

0 comments on commit e31f303

Please sign in to comment.