Skip to content

Commit d64a110

Browse files
authored
[#188] ✨ 댓글 컴포넌트 구현 (#223)
* [#188] 🌱 complete initail setup of Comment component * [#188] ✨ add siren icon component * [#188] ✨ implement Comment component * [#188] ✨ implement CommentList component * [#188] 🔧 add annotation * [#188] ✨ create Comment domain index file * [#188] 🗑️ delete comment component * [#188] ✨ implement temporary UI for Comment * [#98] ♻️ change name field type to string * [#188] ✨ add trashbin icon component * [#188] ✨ control dropdown menu permissions based on user information
1 parent f77a777 commit d64a110

File tree

8 files changed

+260
-23
lines changed

8 files changed

+260
-23
lines changed

src/app/(pages)/test-page/page.tsx

Lines changed: 73 additions & 21 deletions
Large diffs are not rendered by default.

src/assets/IconList.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,11 @@ import IcSearchEmpty from './icons/ic-search-empty.svg'
5050
import IcSearch from './icons/ic-search.svg'
5151
import IcSetting from './icons/ic-setting.svg'
5252
import IcShare from './icons/ic-share.svg'
53+
import IcSiren from './icons/ic-siren.svg'
5354
import IcSmallClose from './icons/ic-sm-close.svg'
5455
import IcStar from './icons/ic-star.svg'
5556
import IcStart from './icons/ic-start.svg'
57+
import IcTrashBin from './icons/ic-trashbin.svg'
5658
import IcWorkbag from './icons/ic-workbag.svg'
5759
import IcTextBold from './icons/text-editor/ic-text-bold.svg'
5860
import IcTextCenterAlign from './icons/text-editor/ic-text-center-align.svg'
@@ -142,6 +144,8 @@ export {
142144
IcInsta,
143145
IcNotion,
144146
IcSmallClose,
147+
IcSiren,
148+
IcTrashBin,
145149
IcChevronUp,
146150
IcChevronDown,
147151
IcPeopleMinus,

src/assets/icons/ic-siren.svg

Lines changed: 4 additions & 0 deletions
Loading

src/assets/icons/ic-trashbin.svg

Lines changed: 5 additions & 0 deletions
Loading

src/components/comment/Comment.tsx

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { SubmitHandler, useForm } from 'react-hook-form'
2+
3+
import { cn } from '@/lib/utils'
4+
5+
import { Form } from '@/components/shared/form'
6+
7+
import { Button } from '../common/button'
8+
9+
interface CommentProps {
10+
variant: 'comment' | 'reply'
11+
size: 'sm' | 'lg'
12+
className?: string
13+
}
14+
15+
interface CommentFormValue {
16+
comment: string
17+
}
18+
19+
export const Comment = ({
20+
variant = 'comment',
21+
size = 'lg',
22+
className,
23+
}: CommentProps): JSX.Element => {
24+
const placeholder =
25+
variant === 'comment' ? '댓글을 입력해보세요!' : '답글을 입력해보세요!'
26+
const commentStyle = cn(
27+
cn(
28+
{
29+
'w-1080': size === 'lg',
30+
'w-1000': size === 'sm',
31+
},
32+
className
33+
)
34+
)
35+
36+
const methods = useForm<CommentFormValue>({
37+
defaultValues: {
38+
comment: '',
39+
},
40+
})
41+
42+
const onSubmit: SubmitHandler<CommentFormValue> = data => {
43+
// TODO: 댓글 데이터를 서버로 전송하는 로직 추가
44+
console.log('댓글 내용 콘솔 테스트', data)
45+
}
46+
47+
return (
48+
<Form
49+
methods={methods}
50+
onSubmit={methods.handleSubmit(onSubmit)}
51+
className='flex gap-x-8'
52+
>
53+
<Form.TextArea
54+
name='comment'
55+
size='lg'
56+
placeholder={placeholder}
57+
className={commentStyle}
58+
/>
59+
<div className='flex items-end'>
60+
<Button
61+
type='submit'
62+
backgroundColor='transparentBlue'
63+
textColor='blue'
64+
size='sm'
65+
>
66+
등록
67+
</Button>
68+
</div>
69+
</Form>
70+
)
71+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import Image from 'next/image'
2+
3+
import { IcEdit, IcKebabMenu, IcSiren, IcTrashBin } from '@/assets/IconList'
4+
5+
import { useAuthStore } from '@/stores/useAuthStore'
6+
7+
import { Dropdown } from '../common/dropdown'
8+
import { Text } from '../common/text'
9+
10+
interface Writer {
11+
id: number
12+
nickname: string
13+
imageUrl: string
14+
}
15+
16+
interface CommentListProps {
17+
writer: Writer
18+
content: string
19+
createdAt: string
20+
}
21+
22+
export const CommentList = ({
23+
writer,
24+
content,
25+
createdAt,
26+
}: CommentListProps): JSX.Element => {
27+
const user = useAuthStore(state => state.user)
28+
29+
return (
30+
<div className='m-auto flex w-1104 justify-between pt-20'>
31+
<div className='flex gap-x-8'>
32+
<Image
33+
alt='프로필 이미지'
34+
src={writer.imageUrl}
35+
width='48'
36+
height='48'
37+
className='mb-10 rounded-full'
38+
/>
39+
<div className='flex flex-col gap-y-10'>
40+
<div className='flex gap-x-10'>
41+
<Text.Title variant='title2' color='gray800' weight='700'>
42+
{writer.nickname}
43+
</Text.Title>
44+
<Text.Body variant='body2' color='gray600'>
45+
{createdAt}
46+
</Text.Body>
47+
</div>
48+
<div className='flex gap-x-8'>
49+
<Text.Body variant='body2' color='highlight'>
50+
{/* TODO: 이 부분 API 어떻게 가져와야 할 지 */}
51+
@망곰아 사랑해
52+
</Text.Body>
53+
<Text.Body variant='body2' color='gray800'>
54+
{content}
55+
</Text.Body>
56+
</div>
57+
</div>
58+
</div>
59+
<Dropdown className='relative'>
60+
<Dropdown.Trigger className='flex h-24 w-24 items-center justify-center'>
61+
<IcKebabMenu width={24} height={24} />
62+
</Dropdown.Trigger>
63+
<Dropdown.Menu position='dropdown' alignment='right' className='w-156'>
64+
{user?.id === writer.id ? (
65+
<>
66+
<Dropdown.Item onClick={() => console.log('신고하기')}>
67+
<div className='flex items-center gap-x-4'>
68+
<IcEdit width={24} height={24} />
69+
<Text.Body variant='body2' color='gray800'>
70+
수정하기
71+
</Text.Body>
72+
</div>
73+
</Dropdown.Item>
74+
<Dropdown.Item onClick={() => console.log('신고하기')}>
75+
<div className='flex items-center gap-x-4'>
76+
<IcTrashBin width={24} height={24} />
77+
<Text.Body variant='body2' color='gray800'>
78+
삭제하기
79+
</Text.Body>
80+
</div>
81+
</Dropdown.Item>
82+
</>
83+
) : (
84+
<Dropdown.Item onClick={() => console.log('신고하기')}>
85+
<div className='flex items-center gap-x-4'>
86+
<IcSiren width={24} height={24} />
87+
<Text.Body variant='body2' color='gray800'>
88+
신고하기
89+
</Text.Body>
90+
</div>
91+
</Dropdown.Item>
92+
)}
93+
</Dropdown.Menu>
94+
</Dropdown>
95+
</div>
96+
)
97+
}

src/components/comment/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { Comment } from './Comment'
2+
import { CommentList } from './CommentList'
3+
4+
export { Comment, CommentList }

src/components/shared/form/Form.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ const FormPassword = ({
8181
name,
8282
...props
8383
}: {
84-
name: FormField
84+
name: string
8585
rules?: Record<string, unknown>
8686
} & Omit<TextInputProps, 'type'>): JSX.Element => {
8787
const {
@@ -108,7 +108,7 @@ const FormPassword = ({
108108
const FormTextArea = ({
109109
name,
110110
...props
111-
}: { name: FormField } & TextAreaProps): JSX.Element => {
111+
}: { name: string } & TextAreaProps): JSX.Element => {
112112
const {
113113
register,
114114
formState: { errors },

0 commit comments

Comments
 (0)