Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4e4bc18

Browse files
committed
Add a way to edit comment
1 parent 6c0c11b commit 4e4bc18

File tree

5 files changed

+294
-64
lines changed

5 files changed

+294
-64
lines changed

src/components/HomePageFeed.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ export function HomePageFeedUpdate({
265265
<UpdateCommentsList>
266266
{update.comments.data.map((comment, index) => (
267267
<UpdateComment
268+
updateId={update.id}
268269
key={comment.id}
269270
comment={comment}
270271
isLastComment={

src/components/goals/EditComment.tsx

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import { User } from 'src/pages/members'
2+
import { Avatar, Button, TextArea } from '@/ui'
3+
import { useForm } from 'react-hook-form'
4+
import { useSession } from 'next-auth/client'
5+
import { useMutation, useQueryClient } from 'react-query'
6+
import toast, { Toaster } from 'react-hot-toast'
7+
import { useRef, useState } from 'react'
8+
import { Markdown, A } from '@/components'
9+
10+
type Inputs = {
11+
description: string
12+
}
13+
14+
export default function EditComment({
15+
updateId,
16+
comment,
17+
cancelEditMode,
18+
}: {
19+
updateId: string
20+
comment: { id: string; description: string }
21+
cancelEditMode: () => void
22+
}) {
23+
const [descriptionStorage, setDescriptionStorage] = useState(
24+
comment.description
25+
)
26+
const queryClient = useQueryClient()
27+
const [session, loading] = useSession()
28+
const { handleSubmit, register, errors, reset } = useForm<Inputs>()
29+
const toastId = useRef('')
30+
const { mutate } = useMutation(
31+
(data: Inputs) =>
32+
fetch(`/api/fauna/goals/edit-comment`, {
33+
method: 'POST',
34+
headers: {
35+
'Content-Type': 'application/json',
36+
},
37+
body: JSON.stringify({
38+
id: comment.id,
39+
description: data.description,
40+
}),
41+
}).then((res) => {
42+
if (!res.ok) {
43+
throw new Error('Something went wrong!!')
44+
}
45+
return res.json()
46+
}),
47+
{
48+
onSuccess: () => {
49+
toast.success('You have successfully updated your comment.', {
50+
id: toastId.current,
51+
})
52+
queryClient.refetchQueries('/api/fauna/all-updates')
53+
cancelEditMode()
54+
reset()
55+
},
56+
onError: () => {
57+
toast.error('Something went wrong!!!', { id: toastId.current })
58+
},
59+
}
60+
)
61+
const onSubmit = (data: Inputs) => {
62+
const id = toast.loading('Saving your comment...')
63+
toastId.current = id
64+
mutate(data)
65+
setDescriptionStorage('')
66+
}
67+
if (loading) {
68+
return <p>loading...</p>
69+
}
70+
return (
71+
<>
72+
<Toaster />
73+
<div className="mt-6">
74+
<div className="flex space-x-3">
75+
<div className="flex-shrink-0">
76+
<div className="relative">
77+
<A href={`/${(session.user as User).username}`}>
78+
<Avatar
79+
src={(session.user as User).image}
80+
alt={(session.user as User).account?.firstName}
81+
/>
82+
</A>
83+
</div>
84+
</div>
85+
<div className="min-w-0 flex-1">
86+
<form onSubmit={handleSubmit(onSubmit)}>
87+
<TextArea
88+
ref={register({ required: true })}
89+
label="Comment"
90+
defaultValue={comment.description}
91+
name="description"
92+
hideLabel={true}
93+
rows={3}
94+
placeholder="Give suggestions or ask questions related to the update."
95+
hasError={Boolean(errors.description)}
96+
errorMessage="Comment is required!!!"
97+
helpText="[Basic Markdown](/markdown) is supported."
98+
onKeyDown={(e) => {
99+
if (e.code === 'Enter' && (e.metaKey || e.ctrlKey)) {
100+
handleSubmit(onSubmit)()
101+
}
102+
}}
103+
onChange={(e) => {
104+
setDescriptionStorage(e.target.value)
105+
}}
106+
></TextArea>
107+
{descriptionStorage && (
108+
<div className="prose max-w-none mt-2 border rounded p-4">
109+
<Markdown>{descriptionStorage}</Markdown>
110+
</div>
111+
)}
112+
113+
<div className="mt-6 flex items-center justify-end space-x-4">
114+
<Button onClick={() => cancelEditMode()}>Cancel</Button>
115+
<Button variant="solid" variantColor="brand" type="submit">
116+
Add Comment
117+
</Button>
118+
</div>
119+
</form>
120+
</div>
121+
</div>
122+
</div>
123+
</>
124+
)
125+
}
Lines changed: 118 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1-
import { Avatar } from '@/ui'
1+
import { Avatar, Menu } from '@/ui'
22
import React, { useState } from 'react'
3-
import { Markdown, A, LikeModal, useLikes } from '@/components'
3+
import { Markdown, A, LikeModal, useLikes, EditComment } from '@/components'
44
import { DateTime } from 'luxon'
55
import { UpdateCommentType } from 'src/pages'
66
import { useSession } from 'next-auth/client'
77
import classNames from 'classnames'
8-
import { ThumbsUp } from 'phosphor-react'
8+
import {
9+
DotsThreeOutlineVertical,
10+
Pencil,
11+
ThumbsUp,
12+
Trash,
13+
} from 'phosphor-react'
14+
import { User } from 'src/pages/members'
915

1016
export type GoalUpdateType = {
1117
id: string
@@ -14,14 +20,17 @@ export type GoalUpdateType = {
1420
}
1521

1622
export default function UpdateComment({
23+
updateId,
1724
comment,
1825
children,
1926
isLastComment = false,
2027
}: {
28+
updateId: string
2129
children: string
2230
comment: UpdateCommentType
2331
isLastComment?: boolean
2432
}) {
33+
const [isInEditMode, setIsInEditMode] = useState(false)
2534
const postedOn = DateTime.fromMillis(comment.createdAt)
2635
const [session] = useSession()
2736
const [isLikeModalOpen, setIsLikeModalOpen] = useState(false)
@@ -43,75 +52,120 @@ export default function UpdateComment({
4352
})
4453
return (
4554
<li>
46-
<div className="relative pb-6">
47-
<div className="relative flex items-start space-x-3">
48-
<div className="relative">
49-
<A href={`/${comment.postedBy.username}`}>
50-
<Avatar
51-
src={comment.postedBy.image}
52-
alt={comment.postedBy.account?.firstName}
53-
/>
54-
</A>
55-
</div>
56-
<div className="min-w-0 flex-1">
57-
<div>
58-
<div className="text-sm">
59-
<a
60-
href={`/${comment.postedBy.username}`}
61-
className="font-medium text-gray-900"
62-
>
63-
{comment.postedBy.account?.firstName ?? comment.postedBy.name}
64-
</a>
65-
</div>
66-
<p className="mt-0.5 text-sm text-gray-500">
67-
Posted on{' '}
68-
<time dateTime={postedOn.toISO()}>
69-
{postedOn.toLocaleString(DateTime.DATE_MED_WITH_WEEKDAY)}
70-
</time>
71-
</p>
55+
{isInEditMode ? (
56+
<EditComment
57+
updateId={updateId}
58+
comment={comment}
59+
cancelEditMode={() => setIsInEditMode(false)}
60+
/>
61+
) : (
62+
<div className="relative pb-6">
63+
<div className="relative flex items-start space-x-3">
64+
<div className="relative">
65+
<A href={`/${comment.postedBy.username}`}>
66+
<Avatar
67+
src={comment.postedBy.image}
68+
alt={comment.postedBy.account?.firstName}
69+
/>
70+
</A>
7271
</div>
73-
<div className="mt-2 text-sm text-gray-700">
74-
<div className="prose prose-sm max-w-none">
75-
<Markdown>{children}</Markdown>
72+
<div className="min-w-0 flex-1">
73+
<div className="flex space-x-3">
74+
<div className="flex-1">
75+
<div className="text-sm">
76+
<a
77+
href={`/${comment.postedBy.username}`}
78+
className="font-medium text-gray-900"
79+
>
80+
{comment.postedBy.account?.firstName ??
81+
comment.postedBy.name}
82+
</a>
83+
</div>
84+
<p className="mt-0.5 text-sm text-gray-500">
85+
Posted on{' '}
86+
<time dateTime={postedOn.toISO()}>
87+
{postedOn.toLocaleString(DateTime.DATE_MED_WITH_WEEKDAY)}
88+
</time>
89+
</p>
90+
</div>
91+
{session && (session.user as User).id === comment.postedBy.id && (
92+
<div className="flex-shrink-0 self-center flex">
93+
<div className="relative inline-block text-left">
94+
<Menu
95+
trigger={
96+
<button className="-m-2 p-2 rounded-full flex items-center text-gray-400 hover:text-gray-600">
97+
<span className="sr-only">Open quick actions</span>
98+
<DotsThreeOutlineVertical
99+
className="h-5 w-5"
100+
aria-hidden={true}
101+
/>
102+
</button>
103+
}
104+
>
105+
<Menu.Item
106+
icon={Pencil}
107+
onClick={() => setIsInEditMode(true)}
108+
>
109+
Edit
110+
</Menu.Item>
111+
<Menu.Item
112+
icon={Trash}
113+
onClick={() => {
114+
// deleteUpdate()
115+
// const id = toast.loading('Deleting your update...')
116+
// toastId.current = id
117+
}}
118+
>
119+
Delete
120+
</Menu.Item>
121+
</Menu>
122+
</div>
123+
</div>
124+
)}
125+
</div>
126+
<div className="mt-2 text-sm text-gray-700">
127+
<div className="prose prose-sm max-w-none">
128+
<Markdown>{children}</Markdown>
129+
</div>
76130
</div>
77-
</div>
78131

79-
<div className="mt-3 flex justify-between space-x-8">
80-
<div className="flex space-x-6">
81-
<span className="inline-flex items-center text-sm">
82-
<button
83-
className="inline-flex space-x-2 text-gray-400 hover:text-gray-500"
84-
onClick={() => {
85-
if (!session) {
86-
setIsLikeModalOpen(true)
87-
return
88-
}
89-
toggleLike()
90-
}}
91-
>
92-
<ThumbsUp
93-
className={classNames(
94-
'h-5 w-5',
95-
hasLiked && 'text-brand-600'
96-
)}
97-
weight={hasLiked ? 'bold' : 'regular'}
132+
<div className="mt-3 flex justify-between space-x-8">
133+
<div className="flex space-x-6">
134+
<span className="inline-flex items-center text-sm">
135+
<button
136+
className="inline-flex space-x-2 text-gray-400 hover:text-gray-500"
137+
onClick={() => {
138+
if (!session) {
139+
setIsLikeModalOpen(true)
140+
return
141+
}
142+
toggleLike()
143+
}}
144+
>
145+
<ThumbsUp
146+
className={classNames(
147+
'h-5 w-5',
148+
hasLiked && 'text-brand-600'
149+
)}
150+
weight={hasLiked ? 'bold' : 'regular'}
151+
/>
152+
<span className="font-medium text-gray-900">
153+
{likesCount}
154+
</span>
155+
<span className="sr-only">likes</span>
156+
</button>
157+
<LikeModal
158+
user={comment.postedBy}
159+
isOpen={isLikeModalOpen}
160+
setIsOpen={setIsLikeModalOpen}
98161
/>
99-
<span className="font-medium text-gray-900">
100-
{likesCount}
101-
</span>
102-
<span className="sr-only">likes</span>
103-
</button>
104-
<LikeModal
105-
user={comment.postedBy}
106-
isOpen={isLikeModalOpen}
107-
setIsOpen={setIsLikeModalOpen}
108-
/>
109-
</span>
162+
</span>
163+
</div>
110164
</div>
111165
</div>
112166
</div>
113167
</div>
114-
</div>
168+
)}
115169
</li>
116170
)
117171
}

src/components/goals/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ export { default as UpdateComment } from './UpdateComment'
1212
export { default as NewComment } from './NewComment'
1313
export { default as UpdateComments, UpdateCommentsList } from './UpdateComments'
1414
export { default as EditUpdate } from './EditUpdate'
15+
export { default as EditComment } from './EditComment'

0 commit comments

Comments
 (0)