Skip to content

Commit

Permalink
마이페이지 구현 (#185)
Browse files Browse the repository at this point in the history
* feat: 마이페이지 관련 타입추가

* feat: 마이페이지 관련 msw 데이터 및 핸들러 추가

* feat: MyPage 페이지 컴포넌트 추가

* feat: ProfileRunnerPostItem 컴포넌트 추가

* feat: ListFilter 컴포넌트 추가

* feat: 마이페이지 페이지 라우팅 추가

* refactor: list태그div에서ul로 수정

* fix : 페이지 상수에 / 추가

* refactor: runnerProfile 타입명에 Get추가

* refactor: Profile 타입을 따로 분리

* refactor: iternator 명 수정

---------

Co-authored-by: 상규 <[email protected]>
  • Loading branch information
tkdrb12 and 상규 authored Aug 3, 2023
1 parent 6dab025 commit c495995
Show file tree
Hide file tree
Showing 8 changed files with 447 additions and 0 deletions.
76 changes: 76 additions & 0 deletions frontend/src/components/ListFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { ListSelectOption } from '@/types/select';
import React from 'react';
import styled, { css, keyframes } from 'styled-components';

interface Props {
options: ListSelectOption[];
selectOption: (value: string | number) => void;
width?: string;
}

const ListFilter = ({ options, selectOption, width }: Props) => {
const makeHandleClickOption = (value: string | number) => () => {
if (options.filter((option) => option.value === value).length === 0) return;

selectOption(value);
};

return (
<S.FilterContainer>
<S.FilterList $width={width}>
{options.map((option) => (
<S.FilterItem key={option.value} onClick={makeHandleClickOption(option.value)} isSelected={option.selected}>
{option.label}
</S.FilterItem>
))}
</S.FilterList>
</S.FilterContainer>
);
};

export default ListFilter;

const appear = keyframes`
0% {
transform: scaleX(0);
}
100% {
transform: scaleX(1);
}
`;

const underLine = css`
content: '';
margin-top: 5px;
height: 3px;
width: calc(100% + 10px);
background-color: var(--baton-red);
animation: 0.3s ease-in ${appear};
`;

const S = {
FilterContainer: styled.div``,

FilterList: styled.ul<{ $width?: string }>`
display: flex;
justify-content: space-between;
width: ${({ $width }) => $width ?? '920px'};
`,

FilterItem: styled.li<{ isSelected: boolean }>`
display: flex;
flex-direction: column;
align-items: center;
font-size: 26px;
font-weight: 700;
color: ${({ isSelected }) => (isSelected ? 'var(--baton-red)' : 'var(--gray-700)')};
&::after {
${({ isSelected }) => (isSelected ? underLine : null)}
}
cursor: pointer;
`,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import Button from '@/components/common/Button';
import Label from '@/components/common/Label';
import { REVIEW_STATUS_LABEL_TEXT } from '@/constants';
import { ProfileRunnerPost } from '@/types/profile';
import React from 'react';
import styled from 'styled-components';

interface Props extends ProfileRunnerPost {}

const ProfileRunnerPostItem = ({ runnerPostId, title, deadline, reviewStatus, tags }: Props) => {
const handleClickFeedbackButton = () => {
alert('준비중인 기능입니다');
};

return (
<S.RunnerPostItemContainer>
<S.LeftSideContainer>
<S.PostTitle>{title}</S.PostTitle>
<S.DeadLineContainer>
<S.DeadLine>{deadline} 까지</S.DeadLine>
<Label colorTheme={reviewStatus === 'DONE' ? 'GRAY' : reviewStatus === 'IN_PROGRESS' ? 'RED' : 'WHITE'}>
{REVIEW_STATUS_LABEL_TEXT[reviewStatus]}
</Label>
</S.DeadLineContainer>
<S.TagContainer>
{tags.map((tag, index) => (
<span key={index}>#{tag}</span>
))}
</S.TagContainer>
</S.LeftSideContainer>
<S.RightSideContainer>
{reviewStatus === 'DONE' ? (
<Button
colorTheme="WHITE"
fontWeight={700}
width={'180px'}
height={'40px'}
onClick={handleClickFeedbackButton}
>
피드백 작성
</Button>
) : null}
</S.RightSideContainer>
</S.RunnerPostItemContainer>
);
};

export default ProfileRunnerPostItem;

const S = {
RunnerPostItemContainer: styled.li`
display: flex;
justify-content: space-between;
width: 1200px;
height: 206px;
padding: 35px 40px;
border: 0.5px solid var(--gray-500);
border-radius: 12px;
box-shadow: 1px 2px 3px rgba(0, 0, 0, 0.2);
cursor: pointer;
`,

PostTitle: styled.p`
margin-bottom: 15px;
font-size: 28px;
font-weight: 700;
`,

DeadLineContainer: styled.div`
display: flex;
align-items: baseline;
gap: 10px;
`,

DeadLine: styled.p`
margin-bottom: 60px;
color: var(--gray-600);
`,

TagContainer: styled.div`
& span {
margin-right: 10px;
font-size: 14px;
color: var(--gray-600);
}
`,

LeftSideContainer: styled.div``,

RightSideContainer: styled.div`
display: flex;
flex-direction: column;
justify-content: end;
`,
};
31 changes: 31 additions & 0 deletions frontend/src/mocks/data/runnerProfile.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"profile": {
"name": "도리토스",
"imageUrl": "profile.jpg",
"githubUrl": "github.com/shb03323",
"introduction": "안녕하세요 디투입니다."
},
"runnerPosts": [
{
"runnerPostId": 1,
"title": "제목",
"deadline": "마감기한",
"tags": ["java", "JAVA"],
"reviewStatus": "DONE"
},
{
"runnerPostId": 2,
"title": "제목2",
"deadline": "마감기한2",
"tags": ["java", "자바"],
"reviewStatus": "NOT_STARTED"
},
{
"runnerPostId": 3,
"title": "제목3",
"deadline": "마감기한3",
"tags": ["java", "자바"],
"reviewStatus": "NOT_STARTED"
}
]
}
5 changes: 5 additions & 0 deletions frontend/src/mocks/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { rest } from 'msw';
import runnerPostList from './data/runnerPostList.json';
import runnerPostDetails from './data/runnerPostDetails.json';
import supporterCardList from './data/supporterCardList.json';
import runnerProfile from './data/runnerProfile.json';

export const handlers = [
rest.post('*/posts/runner/test', async (req, res, ctx) => {
Expand Down Expand Up @@ -42,4 +43,8 @@ export const handlers = [

return res(ctx.delay(300), ctx.status(201), ctx.set('Content-Type', 'application/json'));
}),

rest.get('*/profile/runner', async (req, res, ctx) => {
return res(ctx.status(200), ctx.set('Content-Type', 'application/json'), ctx.json(runnerProfile));
}),
];
Loading

0 comments on commit c495995

Please sign in to comment.