diff --git a/public/icons/calendar.svg b/public/icons/calendar.svg index 2554b039..12aeecd2 100644 --- a/public/icons/calendar.svg +++ b/public/icons/calendar.svg @@ -1,6 +1,6 @@ - + - + diff --git a/public/icons/comments.svg b/public/icons/comments.svg index 16580f05..76f31742 100644 --- a/public/icons/comments.svg +++ b/public/icons/comments.svg @@ -1,3 +1,3 @@ - - + + diff --git a/public/icons/members.svg b/public/icons/members.svg index b738b72d..f1791911 100644 --- a/public/icons/members.svg +++ b/public/icons/members.svg @@ -1,3 +1,3 @@ - - + + diff --git a/src/stories/bookGroup/DetailMyGroup.stories.tsx b/src/stories/bookGroup/DetailMyGroup.stories.tsx new file mode 100644 index 00000000..684b01e8 --- /dev/null +++ b/src/stories/bookGroup/DetailMyGroup.stories.tsx @@ -0,0 +1,39 @@ +import { Meta, StoryObj } from '@storybook/react'; + +import DetailMyGroup from '@/v1/bookgroup/DetailMyGroup'; + +const meta: Meta = { + title: 'bookgroup/DetailMyGroup', + component: DetailMyGroup, + tags: ['autodocs'], +}; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + title: '프롱이 리팩터링 스터디', + description: + '제1차 프롱이 기수연합 독서 스터디 입니다. 마틴 파울러의 저서 ‘리팩터링 2판’과 함께 진행합니다.', + book: { + title: '리팩터링 2판', + bookImageSrc: 'https://image.yes24.com/goods/89649360/XL', + }, + date: { + start: '2023-10-31', + end: '2023-11-27', + }, + memberCount: 3, + owner: { + name: '소피아', + profileImageSrc: '', + }, + isPublic: false, + commentCount: 12, + handleClick: () => { + alert('모임 상세 페이지로 이동'); + }, + }, +}; diff --git a/src/v1/bookgroup/DetailMyGroup.tsx b/src/v1/bookgroup/DetailMyGroup.tsx new file mode 100644 index 00000000..8ca3f666 --- /dev/null +++ b/src/v1/bookgroup/DetailMyGroup.tsx @@ -0,0 +1,249 @@ +import Image from 'next/image'; + +import Badge from '@/ui/Base/Badge'; +import { IconCalendar, IconMembers, IconComments } from '@public/icons'; + +interface DetailMyGroupProps { + title: string; + description: string; + book: { title: string; bookImageSrc: string }; + date: { start: string; end: string }; + owner: { name: string; profileImageSrc: string }; + memberCount: number; + commentCount: number; + isPublic: boolean; + handleClick: () => void; +} + +type BookGroupStatus = 'before' | 'dday' | 'ongoing' | 'end'; + +const getBookGroupStatus = (ddayByStart: number, ddayByEnd: number) => { + if (ddayByStart > 0) { + return { + status: 'before' as const, + ddayCount: ddayByStart, + }; + } else if (ddayByStart === 0 && ddayByEnd > 0) { + return { + status: 'dday' as const, + }; + } else if (ddayByStart < 0 && ddayByEnd >= 0) { + return { + status: 'ongoing' as const, + }; + } else { + return { + status: 'end' as const, + }; + } +}; + +const toDayFromMillseconds = (value: number) => { + return Math.ceil(value / (1000 * 60 * 60 * 24)); +}; + +const DetailMyGroup = ({ + title, + description, + book, + date, + owner, + memberCount, + commentCount, + isPublic, + handleClick, +}: DetailMyGroupProps) => { + const ddayByStart = toDayFromMillseconds( + new Date(date.start).getTime() - new Date().getTime() + ); + const ddayByEnd = toDayFromMillseconds( + new Date(date.end).getTime() - new Date().getTime() + ); + + const { ...ddayProps } = getBookGroupStatus(ddayByStart, ddayByEnd); + + return ( +
+
+ + +
+
+
+ + + +
+ +
+ + +
+
+
+
+ +
+
+
+ ); +}; + +export default DetailMyGroup; + +const getDdayBadgeInfo = (status: BookGroupStatus, ddayCount?: number) => { + switch (status) { + case 'before': + return { + colorScheme: 'main' as const, + isFilled: true, + text: `D-${ddayCount}`, + }; + case 'dday': + return { + colorScheme: 'main' as const, + isFilled: false, + text: 'D-day', + }; + case 'ongoing': + return { + colorScheme: 'main' as const, + isFilled: true, + text: '진행중', + }; + case 'end': + return { + colorScheme: 'grey' as const, + isFilled: true, + text: '모임종료', + }; + } +}; + +const Dday = ({ + status, + ddayCount, +}: { + status: BookGroupStatus; + ddayCount?: number; +}) => { + const { text, ...badgeProps } = getDdayBadgeInfo(status, ddayCount); + + return ( + + {text} + + ); +}; + +const Public = ({ isPublic }: { isPublic: boolean }) => ( + + {isPublic ? '공개' : '비공개'} + +); + +const Title = ({ title }: { title: string }) => { + return ( +
+ {title} +
+ ); +}; + +const Description = ({ description }: { description: string }) => { + return ( +
+ {description} +
+ ); +}; + +const Duration = ({ start, end }: { start: string; end: string }) => { + return ( +
+
+ +
+
+ + {start} - {end} + +
+
+ ); +}; + +const Owner = ({ + name, + profileImageSrc, +}: { + name: string; + profileImageSrc: string; +}) => { + return ( +
+ {/* 아바타 컴포넌트로 변경 예정 */} +
+ {profileImageSrc && {name}} +
+
+ {name} +
+
+ ); +}; + +const MemberCount = ({ memberCount }: { memberCount: number }) => { + return ( +
+ + + + + {memberCount} + +
+ ); +}; + +const CommentCount = ({ commentCount }: { commentCount: number }) => { + return ( +
+
+ +
+ + {commentCount} + +
+ ); +}; + +const Book = ({ + bookImageSrc, + title, +}: { + bookImageSrc: string; + title: string; +}) => { + return ( +
+
+ {bookImageSrc && ( + {title} + )} +
+
+ ); +}; diff --git a/tailwind.config.js b/tailwind.config.js index 7ae38948..bb9fda5b 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -7,6 +7,7 @@ module.exports = { './src/app/**/*.{ts,tsx}', './src/stories/**/*.{ts,tsx}', './.storybook/**/*.{ts,tsx}', + './src/v1/**/*.{ts,tsx}', ], theme: { extend: {