diff --git a/frontend/src/components/ArticleTag/ArticleTag.stories.tsx b/frontend/src/components/ArticleTag/ArticleTag.stories.tsx index 85613b94..1d7bcccb 100644 --- a/frontend/src/components/ArticleTag/ArticleTag.stories.tsx +++ b/frontend/src/components/ArticleTag/ArticleTag.stories.tsx @@ -10,6 +10,6 @@ const Template: ComponentStory = (args) => { - // TODO 이 함수를 util로 분리하는게 좋을지 고민 - const getBadgeColor = (id: number) => { - const colorCount = BADGE_COLORS.length; - return BADGE_COLORS[id % colorCount]; - }; - +const ArticleTag = ({ color, content, size = 'sm' }: Props) => { return ( - + {content} diff --git a/frontend/src/components/GroupArticleCard/GroupArticleCard.stories.tsx b/frontend/src/components/GroupArticleCard/GroupArticleCard.stories.tsx index 8d6b5776..26a9c843 100644 --- a/frontend/src/components/GroupArticleCard/GroupArticleCard.stories.tsx +++ b/frontend/src/components/GroupArticleCard/GroupArticleCard.stories.tsx @@ -1,6 +1,6 @@ import { ComponentMeta, ComponentStory } from '@storybook/react'; import GroupArticleCard from '.'; -import { dummyArticle } from '@constants/dummy'; +import { dummyArticlePreview } from '@constants/dummy'; import { ArticleStatus } from '@constants/article'; export default { @@ -11,14 +11,14 @@ export default { const Template: ComponentStory = (args) => ; export const NormalCard = Template.bind({}); -NormalCard.args = { article: dummyArticle }; +NormalCard.args = { article: dummyArticlePreview }; export const LongTitleCard = Template.bind({}); LongTitleCard.args = { - article: { ...dummyArticle, title: '길어지는 제목입니다. 제목이 길어서 잘려요.' }, + article: { ...dummyArticlePreview, title: '길어지는 제목입니다. 제목이 길어서 잘려요.' }, }; export const ClosedCard = Template.bind({}); ClosedCard.args = { - article: { ...dummyArticle, status: ArticleStatus.SUCCEED }, + article: { ...dummyArticlePreview, status: ArticleStatus.SUCCEED }, }; diff --git a/frontend/src/components/GroupArticleCard/index.tsx b/frontend/src/components/GroupArticleCard/index.tsx index 76b1e307..ffc674e1 100644 --- a/frontend/src/components/GroupArticleCard/index.tsx +++ b/frontend/src/components/GroupArticleCard/index.tsx @@ -1,8 +1,8 @@ import { Image } from '@mantine/core'; -import { ArticleType } from '@typings/types'; +import { ArticlePreviewType } from '@typings/types'; import ArticleTag from '@components/ArticleTag'; import StatCounter from '@components/StatCounter'; -import { ArticleStatus } from '@constants/article'; +import { ArticleStatus, ArticleStatusKr } from '@constants/article'; import { CapacityText, CardWrapper, @@ -12,9 +12,10 @@ import { TitleText, ClosedText, } from '@components/GroupArticleCard/styles'; +import { getCommonBadgeColor, getStatusBadgeColor } from '../../utils/colors'; interface Props { - article: ArticleType; + article: ArticlePreviewType; } const GroupArticleCard = ({ article }: Props) => { @@ -28,8 +29,18 @@ const GroupArticleCard = ({ article }: Props) => { {'thumbnail-image'} - - + + + {article.title} diff --git a/frontend/src/constants/article.ts b/frontend/src/constants/article.ts index d747e2b7..69b1ab0b 100644 --- a/frontend/src/constants/article.ts +++ b/frontend/src/constants/article.ts @@ -1,7 +1,13 @@ enum ArticleStatus { + PROGRESS = 'PROGRESS', + SUCCEED = 'SUCCEED', + FAIL = 'FAIL', +} + +enum ArticleStatusKr { PROGRESS = '모집중', - SUCCEED = '모집성공', - FAIL = '모집중단', + SUCCEED = '모집완료', + FAIL = '모집증단', } -export { ArticleStatus }; +export { ArticleStatus, ArticleStatusKr }; diff --git a/frontend/src/constants/category.ts b/frontend/src/constants/category.ts new file mode 100644 index 00000000..1c06fd1b --- /dev/null +++ b/frontend/src/constants/category.ts @@ -0,0 +1,17 @@ +enum Category { + STUDY = 'STUDY', + PROJECT = 'PROJECT', + COMPETITION = 'COMPETITION', + MEAL = 'MEAL', + ETC = 'ETC', +} + +enum CategoryKr { + STUDY = '스터디', + PROJECT = '프로젝트', + COMPETITION = '공모전', + MEAL = '식사', + ETC = '기타', +} + +export { Category, CategoryKr }; diff --git a/frontend/src/constants/color.ts b/frontend/src/constants/color.ts index 11065700..cfb17fb7 100644 --- a/frontend/src/constants/color.ts +++ b/frontend/src/constants/color.ts @@ -1,14 +1,11 @@ -const BADGE_COLORS = [ - 'cyan', - 'green', - 'yellow', - 'orange', - 'grape', - 'red', - 'indigo', - 'violet', - 'lime', - 'teal', -]; +import { ArticleStatus } from '@constants/article'; -export { BADGE_COLORS }; +const BADGE_COLORS = ['cyan', 'green', 'yellow', 'orange', 'grape', 'violet', 'teal', 'pink']; + +const STATUS_COLOR = { + [ArticleStatus.PROGRESS]: 'lime', + [ArticleStatus.SUCCEED]: 'indigo', + [ArticleStatus.FAIL]: 'red', +}; + +export { BADGE_COLORS, STATUS_COLOR }; diff --git a/frontend/src/constants/dummy.ts b/frontend/src/constants/dummy.ts index 2074b2a2..e23e7d4f 100644 --- a/frontend/src/constants/dummy.ts +++ b/frontend/src/constants/dummy.ts @@ -1,8 +1,29 @@ -import { ArticleType } from '@typings/types'; +import { ArticlePreviewType, ArticleType } from '@typings/types'; import { Location } from '@constants/location'; import { ArticleStatus } from '@constants/article'; +import { Category } from '@constants/category'; // TODO 개발용 dummy data, 추후 삭제 +const dummyArticlePreview: ArticlePreviewType = { + id: 1, + title: '모집 테스트1', + location: { + id: 2, + name: Location.BUSAN, + }, + category: { + id: 1, + name: Category.STUDY, + }, + commentCount: 31, + scrapCount: 12, + thumbnail: 'https://avatars.githubusercontent.com/u/90585081?v=4', + maxCapacity: 5, + currentCapacity: 3, + status: ArticleStatus.PROGRESS, + createdAt: '2021-04-03T18:45:19Z', +}; + const dummyArticle: ArticleType = { id: 1, title: '모집 테스트1', @@ -12,8 +33,12 @@ const dummyArticle: ArticleType = { }, category: { id: 1, - name: '스터디', + name: Category.STUDY, }, + contents: '
test
', + authorId: 1, + authorName: 'JHPark_GOD', + authorThumbnail: 'https://avatars.githubusercontent.com/u/90585081?v=4', commentCount: 31, scrapCount: 12, thumbnail: 'https://avatars.githubusercontent.com/u/90585081?v=4', @@ -23,4 +48,4 @@ const dummyArticle: ArticleType = { createdAt: '2021-04-03T18:45:19Z', }; -export { dummyArticle }; +export { dummyArticlePreview, dummyArticle }; diff --git a/frontend/src/constants/location.ts b/frontend/src/constants/location.ts index 2729d624..ee865324 100644 --- a/frontend/src/constants/location.ts +++ b/frontend/src/constants/location.ts @@ -1,4 +1,24 @@ enum Location { + SEOUL = 'SEOUL', + INCHEON = 'INCHEON', + BUSAN = 'BUSAN', + DAEGU = 'DAEGU', + GWANGJU = 'GWANGJU', + DAEJEON = 'DAEJEON', + ULSAN = 'ULSAN', + SEJONG = 'SEJONG', + GYEONGGI = 'GYEONGGI', + GANGWON = 'GANGWON', + CHUNGBUK = 'CHUNGBUK', + CHUNGNAM = 'CHUNGNAM', + JEONBUK = 'JEONBUK', + JEONNAM = 'JEONNAM', + GYEONGBUK = 'GYEONGBUK', + GYEONGNAM = 'GYEONGNAM', + JEJU = 'JEJU', +} + +enum LocationKr { SEOUL = '서울', INCHEON = '인천', BUSAN = '부산', @@ -18,4 +38,4 @@ enum Location { JEJU = '제주', } -export { Location }; +export { Location, LocationKr }; diff --git a/frontend/src/pages/article/[id].tsx b/frontend/src/pages/article/[id].tsx new file mode 100644 index 00000000..f011122d --- /dev/null +++ b/frontend/src/pages/article/[id].tsx @@ -0,0 +1,199 @@ +import PageLayout from '@components/common/PageLayout'; +import { Avatar, Progress, TypographyStylesProvider } from '@mantine/core'; +import styled from '@emotion/styled'; +import { dummyArticle } from '@constants/dummy'; +import ArticleTag from '@components/ArticleTag'; +import { getCommonBadgeColor, getStatusBadgeColor } from '../../utils/colors'; +import { ArticleStatusKr } from '@constants/article'; +import { CategoryKr } from '@constants/category'; +import { LocationKr } from '@constants/location'; +import { useTheme } from '@emotion/react'; +import StatCounter from '@components/StatCounter'; +import { IconList } from '@tabler/icons'; + +const ArticleDetail = () => { + const { + colors: { indigo, gray }, + } = useTheme(); + + const { + authorName, + title, + status, + authorThumbnail, + createdAt, + category, + location, + contents, + currentCapacity, + maxCapacity, + commentCount, + } = dummyArticle; + + return ( + + + + + + + {authorName} + + + + {title} + + + + + + + + 모집 현황 + + {currentCapacity}명 / {maxCapacity}명 + + + + + 신청자 확인 + + + + + + + + + + + +
댓글영역
+
+
+
+ ); +}; + +export default ArticleDetail; + +const PageWrapper = styled.div` + display: flex; + flex-direction: column; +`; + +const DetailWrapper = styled.div` + display: flex; + flex-direction: column; + gap: 1.6rem; + padding: 1.6rem; +`; + +const ProfileWrapper = styled.div` + display: flex; + gap: 1.2rem; + align-items: center; +`; + +const ProfileTextWrapper = styled.div` + display: flex; + flex-direction: column; + gap: 0.8rem; +`; + +const Author = styled.span` + font-size: 1.6rem; + font-weight: 700; +`; + +const Time = styled.span` + font-size: 1.2rem; + font-weight: 700; + color: ${({ theme }) => theme.colors.gray[4]}; +`; + +const Title = styled.span` + font-size: 2rem; + font-weight: 800; +`; + +const TagWrapper = styled.div` + display: flex; + gap: 0.8rem; +`; + +const ParticipantWrapper = styled.div` + display: flex; + justify-content: space-between; +`; + +const StatusWrapper = styled.div` + display: flex; + gap: 0.8rem; +`; + +const StatusText = styled.span` + font-size: 1.4rem; + font-weight: 700; + color: ${({ theme }) => theme.colors.gray[4]}; +`; + +const CountText = styled.span` + font-size: 1.4rem; + font-weight: 700; +`; + +const ParticipantButton = styled.button` + display: flex; + gap: 4px; + padding: 0; + height: 1.7rem; + align-items: center; + border: none; + background-color: ${({ theme }) => theme.white}; + &:hover { + cursor: pointer; + } +`; + +const ViewText = styled.span` + font-size: 1.4rem; + font-weight: 700; + color: ${({ theme }) => theme.colors.gray[6]}; +`; + +const ContentBox = styled.div` + width: 100%; + min-height: 200px; + padding: 1.6rem; + border: 1px solid ${({ theme }) => theme.colors.gray[2]}; + border-radius: 8px; +`; + +const CommentWrapper = styled.div` + display: flex; + flex-direction: column; +`; + +const Divider = styled.div` + width: 100%; + height: 0.05rem; + background-color: ${({ theme }) => theme.colors.gray[4]}; +`; diff --git a/frontend/src/pages/My.tsx b/frontend/src/pages/my.tsx similarity index 100% rename from frontend/src/pages/My.tsx rename to frontend/src/pages/my.tsx diff --git a/frontend/src/pages/Notification.tsx b/frontend/src/pages/notification.tsx similarity index 100% rename from frontend/src/pages/Notification.tsx rename to frontend/src/pages/notification.tsx diff --git a/frontend/src/pages/test.tsx b/frontend/src/pages/test.tsx index 5c22d7f7..e9ccdaf9 100644 --- a/frontend/src/pages/test.tsx +++ b/frontend/src/pages/test.tsx @@ -20,7 +20,7 @@ const Test = () => { }); return ( - + {testData.map((data, index) => ( {data} ))} diff --git a/frontend/src/typings/types.ts b/frontend/src/typings/types.ts index 1e164d35..7a078e8d 100644 --- a/frontend/src/typings/types.ts +++ b/frontend/src/typings/types.ts @@ -1,9 +1,28 @@ import { Location } from '@constants/location'; import { ArticleStatus } from '@constants/article'; +import { Category } from '@constants/category'; + +interface ArticlePreviewType { + id: number; + title: string; + location: LocationType; + category: CategoryType; + commentCount: number; + scrapCount: number; + thumbnail: string; + maxCapacity: number; + currentCapacity: number; + status: ArticleStatus; + createdAt: string; +} interface ArticleType { id: number; title: string; + contents: string; + authorId: number; + authorName: string; + authorThumbnail: string; location: LocationType; category: CategoryType; commentCount: number; @@ -22,7 +41,7 @@ interface LocationType { interface CategoryType { id: number; - name: string; + name: Category; } interface TestResponseType { @@ -31,4 +50,4 @@ interface TestResponseType { currentId: number; } -export type { ArticleType, LocationType, CategoryType, TestResponseType }; +export type { ArticlePreviewType, ArticleType, LocationType, CategoryType, TestResponseType }; diff --git a/frontend/src/utils/colors.ts b/frontend/src/utils/colors.ts new file mode 100644 index 00000000..332df2e3 --- /dev/null +++ b/frontend/src/utils/colors.ts @@ -0,0 +1,13 @@ +import { BADGE_COLORS, STATUS_COLOR } from '@constants/color'; +import { ArticleStatus } from '@constants/article'; + +const getCommonBadgeColor = (id: number) => { + const colorCount = BADGE_COLORS.length; + return BADGE_COLORS[id % colorCount]; +}; + +const getStatusBadgeColor = (status: ArticleStatus) => { + return STATUS_COLOR[status]; +}; + +export { getCommonBadgeColor, getStatusBadgeColor };