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

공지사항 목록 컴포넌트 / 공지사항 상세 컴포넌트 UI 구현 / 공지사항 ROUTER 설정 #749

Merged
merged 21 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
7a9a4a4
feat: (#741) 모바일 버전 공지사항 목록 구현
Gilpop8663 Oct 13, 2023
7f841f3
feat: (#741) PC 버전 공지사항 리스트 스타일 구현
Gilpop8663 Oct 13, 2023
efc71a3
feat: (#741) 공지사항 세부 내용 컴포넌트 구현
Gilpop8663 Oct 15, 2023
b69cf4b
feat: 공지사항 리스트 페이지 구현
Gilpop8663 Oct 15, 2023
de57115
feat: (#741) 공지사항 세부 페이지 구현
Gilpop8663 Oct 15, 2023
962d1ae
feat: (#741) 공지사항 목록, 상세 페이지 router 설정
Gilpop8663 Oct 15, 2023
5b1f7f9
feat: (#741) 공지사항 웹 접근성 개선
Gilpop8663 Oct 15, 2023
6118863
style: (#741) 공지사항 목록에서는 채널톡 안보이도록 설정 및 padding 속성 설정
Gilpop8663 Oct 15, 2023
94de948
style: (#741) 공지사항 목록 ...이 짧게 설정되어서 width 값 재설정
Gilpop8663 Oct 15, 2023
3c60fa1
chore: (#741) 디자인 변경으로 인한 공지사항 보러가기 삭제
Gilpop8663 Oct 16, 2023
4795a40
Merge branch 'dev' of https://github.com/woowacourse-teams/2023-votog…
Gilpop8663 Oct 17, 2023
98375d0
refactor: (#741) 홈과 공지사항 목록 url을 PATH로 변경
Gilpop8663 Oct 17, 2023
4000618
refactor :(#741) 공지사항 목록을 감싸는 부모를 div에서 main으로 변경
Gilpop8663 Oct 17, 2023
bb9881b
refactor: (#741) 날짜를 string에서 StringDate로 타입 변경
Gilpop8663 Oct 17, 2023
0f730f9
style: (#741) 데스크탑일때 홈으로 버튼 안보이도록 설정
Gilpop8663 Oct 17, 2023
9ce18cd
chore: (#741) 읽은 사람에게 혼동을 주는 주석 제거
Gilpop8663 Oct 17, 2023
41aec0a
chore: (#741) router의 :id를 :noticeId로 이름 변경
Gilpop8663 Oct 17, 2023
284b2e1
refactor: (#741) StringDateOnly 타입 추가 및 api에서 생성 날짜를 변환시켜 날짜만 존재하도록 수정
Gilpop8663 Oct 17, 2023
60464df
refactor: (#741) Response를 Omit하여 만든 타입의 가독성을 높이기 위해 Response 타입을 이동
Gilpop8663 Oct 17, 2023
fd69f50
refactor: (#741) StringDateOnly Type 이름 변경
Gilpop8663 Oct 18, 2023
4d83d1a
chore: (#741) dev 브런치와 충돌 해결
Gilpop8663 Oct 18, 2023
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import type { Meta, StoryObj } from '@storybook/react';

import NoticeDetail from '.';

const meta: Meta<typeof NoticeDetail> = {
component: NoticeDetail,
};

const MOCK_NOTICE_DETAIL = {
title: '🎉보투게더 출시 기념 이벤트 종료',
content: `안녕하세요, 보투게더(VoTogether)는 우아한테크코스에서 진행한 프로젝트로, 투표 중심의 커뮤니티 플랫폼입니다!

🤷‍♂️: 돈이 부족한 취준생인데 알바를 병행하는게 좋을까요, 최대한 절약하는게 좋을까요?
🤷‍♀️: 요즘 체력이 떨어지는데 어떤 운동을 시작하면 좋을까요?
🤷‍♂️: 오늘의 점심 메뉴는 뭐가 좋을까?
다 함께, 즐겁게, 심플하게! 보투게더를 이용해 보세요!

✅ 보투게더(VoTogether)는 투표를 통해 의견을 공유하고, 일상의 재미를 발견하는 커뮤니티 서비스예요.

🖋 고민이 있으신가요? 글을 써보세요!
😆 심심하신가요? 투표를 해보세요!
❔ 궁금하신가요? 관심사를 탐색해 보세요!

보투게더는 사람들의 다양한 주제로 질문하고 답변하면서, 사람들의 반응을 확인할 수 있다는 점에서 특별해요.
자, 이제 보투게더를 이용할 준비되셨나요? 😆😃
나의 이야기가 우리의 이야기가 되는 공간, 보투게더에서 우리 함께해요! 👍

🚀보투게더 출시 이벤트 종료 및 상품 수령 대상자 공지
보투게더 서비스의 런칭 기념 이벤트에 참여해주신 많은 분들 감사드립니다!!
랭킹 순위에서 보투게더 팀원(관리자)은 제외하고 집계되었으며, 상품 수령 대상 닉네임은 아래와 같습니다.

⭐ 게시글을 가장 많이 작성🖋️해주신 이용자! - Swimminggoggles
⭐ 작성한 게시글에 가장 많은 투표✅를 해주신 이용자! - 익명의스내기
⭐ 최고 인기글🔥을 작성하신 이용자! - 익명의익명

위 닉네임들에 해당하시는 분들은 상품 수령을 위하여,보투게더 사이트에 로그인된 화면 인증샷을 채널톡으로 보내주시기 바랍니다!
앞으로도 보투게더 서비스에 많은 관심과 사랑 부탁드립니다. 감사합니다😊😄`,
createdAt: '2023-09-23 18:23',
};

export default meta;
type Story = StoryObj<typeof NoticeDetail>;

export const Default: Story = {
render: () => <NoticeDetail {...MOCK_NOTICE_DETAIL} />,
};
47 changes: 47 additions & 0 deletions frontend/src/components/notice/NoticeDetail/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useNavigate } from 'react-router-dom';

import SquareButton from '@components/common/SquareButton';

import * as S from './style';

interface NoticeDetailProps {
title: string;
content: string;
createdAt: string;
Copy link
Collaborator

Choose a reason for hiding this comment

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

혹시 그 StringDate로 하지 않으신 이유가 있으신가요??

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Notice 타입을 다른 PR에서 해서 타입 적용하는데 어려움이 있었어요 ㅠㅠ

제안해주신대로 StringDate로 변경했습니다

}

export default function NoticeDetail({ title, content, createdAt }: NoticeDetailProps) {
const navigate = useNavigate();
const createdDate = createdAt.slice(0, 10);

return (
<S.Container>
<S.Category tabIndex={0}>VoTogether 공지사항</S.Category>
<S.Title tabIndex={0}>{title}</S.Title>
<S.CreatedAt tabIndex={0}>작성일 : {createdDate}</S.CreatedAt>
<S.Content tabIndex={0}>{content}</S.Content>
<S.ButtonContainer>
<S.ButtonWrapper>
<SquareButton
theme="fill"
onClick={() => {
navigate('/');
}}
>
홈으로 가기
</SquareButton>
</S.ButtonWrapper>
<S.ButtonWrapper>
<SquareButton
theme="blank"
onClick={() => {
navigate('/notices');
}}
Copy link
Member

Choose a reason for hiding this comment

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

PATH.NOTICE 어떠신가요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

좋은 제안 감사합니다

>
{`공지사항\n목록으로 가기`}
</SquareButton>
</S.ButtonWrapper>
</S.ButtonContainer>
</S.Container>
);
}
72 changes: 72 additions & 0 deletions frontend/src/components/notice/NoticeDetail/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { styled } from 'styled-components';

import { theme } from '@styles/theme';

export const Container = styled.div`
display: flex;
flex-direction: column;

width: 100%;
max-width: 600px;
padding-top: 48px;

@media (min-width: ${theme.breakpoint.sm}) {
padding-top: 30px;
}
`;

export const Category = styled.span`
font: var(--text-body);
`;

export const Title = styled.h1`
margin-top: 20px;

font: var(--text-title);
Copy link
Collaborator

Choose a reason for hiding this comment

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

이거 조금 작은거 같은데 제가 알림 PR에다가 이거보다 큰 --text-page-title인가,, 만들었는데 나중에 그걸로 바꿔도 좋을 것 같아요.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

좋아요!

`;

export const CreatedAt = styled.span`
margin: 20px 0;

font: var(--text-body);
font-size: 1.4rem;
text-align: right;

color: var(--text-dark-gray);
`;

export const Content = styled.p`
font: var(--text-body);

white-space: pre-wrap;
`;

export const ButtonContainer = styled.div`
Copy link
Collaborator

Choose a reason for hiding this comment

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

데스크탑에서는 하단에 홈으로 가기 버튼이 없어도 괜찮을 것 같아요!!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

아래와 같이 수정해보았습니다~

image

image

display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
gap: 20px;

margin-top: 50px;

@media (min-width: ${theme.breakpoint.sm}) {
flex-direction: row;
gap: 80px;

padding: 0 100px;
}
`;

export const ButtonWrapper = styled.div`
display: flex;
width: 100%;
height: 40px;

@media (min-width: ${theme.breakpoint.sm}) {
width: 140px;
height: 60px;

white-space: pre-wrap;
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { Meta, StoryObj } from '@storybook/react';

import NoticeItem from '.';

const meta: Meta<typeof NoticeItem> = {
component: NoticeItem,
decorators: [storyFn => <div style={{ width: '576px' }}>{storyFn()}</div>],
};

export default meta;
type Story = StoryObj<typeof NoticeItem>;

const MOCK_NOTICE_ITEM = {
id: 1,
title: '방방뛰는 코끼리',
createdAt: '2022-01-11 12:23',
};

export const Default: Story = {
render: () => <NoticeItem {...MOCK_NOTICE_ITEM} />,
};
24 changes: 24 additions & 0 deletions frontend/src/components/notice/NoticeList/NoticeItem/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { PATH } from '@constants/path';

import * as S from './style';

interface NoticeItemProps {
id: number;
title: string;
/**
* yyyy-mm-dd 형식
*/
createdAt: string;
Copy link
Collaborator

Choose a reason for hiding this comment

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

DateString처럼 이것도 타입 강화하는건 어떻게 생각하시나요?

}
export default function NoticeItem({ id, title, createdAt }: NoticeItemProps) {
const createdDate = createdAt.slice(0, 10);
Copy link
Collaborator

Choose a reason for hiding this comment

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

들어오는 내용이 yyyy-mm-dd 형식인데 방어코드로 한번 더 잘라주는 건가요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

시간은 안보여주는 디자인으로 구현해서 잘라서 보여줬어요

yyyy-mm-dd 형식으로욤

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

헷갈리는 주석을 때문에 혼동이 와서 주석을 삭제했어요 🔥


return (
<S.Container>
<S.DetailLink to={`${PATH.NOTICES}/${id}`}>
<S.Title>{title}</S.Title>
<S.CreatedAt>{createdDate}</S.CreatedAt>
</S.DetailLink>
</S.Container>
);
}
56 changes: 56 additions & 0 deletions frontend/src/components/notice/NoticeList/NoticeItem/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Link } from 'react-router-dom';

import { styled } from 'styled-components';

import { theme } from '@styles/theme';

export const Container = styled.li``;

export const DetailLink = styled(Link)`
display: flex;
flex-direction: column;
width: 100%;

padding: 10px 15px;

@media (min-width: ${theme.breakpoint.sm}) {
flex-direction: row;
justify-content: space-between;

padding: 16px 20px;
}
`;

export const Title = styled.span`
width: 100%;
display: -webkit-box;

text-overflow: ellipsis;
word-break: break-word;

overflow: hidden;

-webkit-line-clamp: 1;
-webkit-box-orient: vertical;

font: var(--text-body);

transition: color 0.2s ease-in-out;
Copy link
Collaborator

Choose a reason for hiding this comment

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

옹 hover를 위한 애니메이션인가요???

  &:hover {
    color: rgba(51, 122, 183, 1);
  }

여기 안에 넣지 않으신 이유가 있나요??

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

hover안에 transition을 두면 마우스를 치웠을 때는 transition 속성이 작동하지 않아서 hover 밖에 위치시켜주었어요


&:hover {
color: rgba(51, 122, 183, 1);
}
`;

export const CreatedAt = styled.span`
font: var(--text-body);
font-size: 1.4rem;

text-align: right;

color: var(--text-dark-gray);

@media (min-width: ${theme.breakpoint.sm}) {
width: 90px;
}
`;
47 changes: 47 additions & 0 deletions frontend/src/components/notice/NoticeList/NoticeList.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import type { Meta, StoryObj } from '@storybook/react';

import NoticeList from '.';

const meta: Meta<typeof NoticeList> = {
component: NoticeList,
decorators: [storyFn => <div style={{ width: '576px' }}>{storyFn()}</div>],
};

const MOCK_NOTICE_LIST = [
{
id: 1,
title: '방방뛰는 코끼리 엄청나게 긴 게시글 공지사항입니다.',
createdAt: '2022-01-11 12:23',
},
{
id: 2,
title: '방방뛰는 코끼리',
createdAt: '2022-01-11 12:23',
},
{
id: 3,
title: '방방뛰는 코끼리',
createdAt: '2022-01-11 12:23',
},
{
id: 4,
title: '방방뛰는 코끼리',
createdAt: '2022-01-11 12:23',
},
{
id: 5,
title: '방방뛰는 코끼리',
createdAt: '2022-01-11 12:23',
},
];

export default meta;
type Story = StoryObj<typeof NoticeList>;

export const Default: Story = {
render: () => (
<div style={{ width: '100vw', padding: '15px' }}>
<NoticeList noticeList={MOCK_NOTICE_LIST} />
</div>
),
};
23 changes: 23 additions & 0 deletions frontend/src/components/notice/NoticeList/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import NoticeItem from './NoticeItem';
import * as S from './style';

interface NoticeListProps {
noticeList: {
id: number;
title: string;
/**
* yyyy-mm-dd 형식
*/
createdAt: string;
Copy link
Member

Choose a reason for hiding this comment

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

StringDate 타입 재사용 어떠신가요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

제안해주신대로 적용해보았습니다

Copy link
Collaborator

Choose a reason for hiding this comment

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

모든 공지 컴포넌트에서 yyyy-mm-dd 형식으로 사용된다면 api에서 처음에 데이터를 변환해주시는건 어떻게 생각하세요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

제안해주신대로 api에서 데이터를 변환시켜 주었습니다 👍👍👍

구현하는 과정에서 StringDateOnly 타입이 추가되었어요

/**
 * yyyy-mm-dd HH-MM
 */
export type StringDate = `${number}-${number}-${number} ${number}:${number}`;

/**
 * yyyy-mm-dd
 */
export type StringDateOnly = `${number}-${number}-${number}`;

}[];
}

export default function NoticeList({ noticeList }: NoticeListProps) {
return (
<S.Container>
{noticeList.map(notice => (
<NoticeItem key={notice.id} {...notice} />
))}
</S.Container>
);
}
16 changes: 16 additions & 0 deletions frontend/src/components/notice/NoticeList/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { styled } from 'styled-components';

export const Container = styled.ul`
width: 100%;

border-radius: 5px;
border: 1px solid rgba(0, 0, 0, 0.2);

> li {
border-bottom: 1px solid rgba(0, 0, 0, 0.2);

&:last-child {
border-bottom: none;
}
}
`;
1 change: 1 addition & 0 deletions frontend/src/constants/path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const BASE_PATH = {
SEARCH: '/search',
RANKING: '/ranking',
ANNOUNCEMENT: '/announcements',
NOTICES: '/notices',
};

export const PATH = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { Meta, StoryObj } from '@storybook/react';

import NoticeDetailPage from '.';

const meta: Meta<typeof NoticeDetailPage> = {
component: NoticeDetailPage,
};

export default meta;
type Story = StoryObj<typeof NoticeDetailPage>;

export const Default: Story = {
render: () => <NoticeDetailPage />,
};
Loading
Loading