1
- import { Box , Flex , Text } from "@chakra-ui/react" ;
1
+ import {
2
+ Box ,
3
+ Button ,
4
+ Flex ,
5
+ FormControl ,
6
+ Input ,
7
+ Modal ,
8
+ ModalBody ,
9
+ ModalCloseButton ,
10
+ ModalContent ,
11
+ ModalFooter ,
12
+ ModalHeader ,
13
+ ModalOverlay ,
14
+ Text ,
15
+ useDisclosure ,
16
+ } from "@chakra-ui/react" ;
2
17
import { useState } from "react" ;
3
18
import { useRecoilValue } from "recoil" ;
4
19
import userAtom from "../atoms/userAtom" ;
@@ -7,9 +22,13 @@ import useShowToast from "../hooks/useShowToast";
7
22
const Actions = ( { post : post_ } ) => {
8
23
const user = useRecoilValue ( userAtom ) ;
9
24
const [ liked , setLiked ] = useState ( post_ . likes . includes ( user ?. _id ) ) ;
10
- const showToast = useShowToast ( ) ;
11
25
const [ post , setPost ] = useState ( post_ ) ;
12
26
const [ isLiking , setIsLiking ] = useState ( false ) ;
27
+ const [ isReplying , setIsReplying ] = useState ( false ) ;
28
+ const [ reply , setReply ] = useState ( "" ) ;
29
+
30
+ const showToast = useShowToast ( ) ;
31
+ const { isOpen, onOpen, onClose } = useDisclosure ( ) ;
13
32
14
33
const handleLikeAndUnlike = async ( ) => {
15
34
if ( ! user ) return showToast ( "Error" , "You must be logged in to like a post" , "error" ) ;
@@ -41,6 +60,32 @@ const Actions = ({ post: post_ }) => {
41
60
}
42
61
} ;
43
62
63
+ const handleReply = async ( ) => {
64
+ if ( ! user ) return showToast ( "Error" , "You must be logged in to reply to a post" , "error" ) ;
65
+ if ( isReplying ) return ;
66
+ setIsReplying ( true ) ;
67
+ try {
68
+ const res = await fetch ( "/api/posts/reply/" + post . _id , {
69
+ method : "PUT" ,
70
+ headers : {
71
+ "Content-Type" : "application/json" ,
72
+ } ,
73
+ body : JSON . stringify ( { text : reply } ) ,
74
+ } ) ;
75
+ const data = await res . json ( ) ;
76
+ if ( data . error ) return showToast ( "Error" , data . error , "error" ) ;
77
+
78
+ setPost ( { ...post , replies : [ ...post . replies , data . reply ] } ) ;
79
+ showToast ( "Success" , "Reply posted successfully" , "success" ) ;
80
+ onClose ( ) ;
81
+ setReply ( "" ) ;
82
+ } catch ( error ) {
83
+ showToast ( "Error" , error . message , "error" ) ;
84
+ } finally {
85
+ setIsReplying ( false ) ;
86
+ }
87
+ } ;
88
+
44
89
return (
45
90
< Flex flexDirection = 'column' >
46
91
< Flex gap = { 3 } my = { 2 } onClick = { ( e ) => e . preventDefault ( ) } >
@@ -61,61 +106,28 @@ const Actions = ({ post: post_ }) => {
61
106
> </ path >
62
107
</ svg >
63
108
64
- < svg aria-label = 'Comment' color = '' fill = '' height = '20' role = 'img' viewBox = '0 0 24 24' width = '20' >
65
- < title > Comment</ title >
66
- < path
67
- d = 'M20.656 17.008a9.993 9.993 0 1 0-3.59 3.615L22 22Z'
68
- fill = 'none'
69
- stroke = 'currentColor'
70
- strokeLinejoin = 'round'
71
- strokeWidth = '2'
72
- > </ path >
73
- </ svg >
74
-
75
109
< svg
76
- aria-label = 'Repost'
77
- color = 'currentColor'
78
- fill = 'currentColor'
79
- height = '20'
80
- role = 'img'
81
- viewBox = '0 0 24 24'
82
- width = '20'
83
- >
84
- < title > Repost</ title >
85
- < path
86
- fill = ''
87
- d = 'M19.998 9.497a1 1 0 0 0-1 1v4.228a3.274 3.274 0 0 1-3.27 3.27h-5.313l1.791-1.787a1 1 0 0 0-1.412-1.416L7.29 18.287a1.004 1.004 0 0 0-.294.707v.001c0 .023.012.042.013.065a.923.923 0 0 0 .281.643l3.502 3.504a1 1 0 0 0 1.414-1.414l-1.797-1.798h5.318a5.276 5.276 0 0 0 5.27-5.27v-4.228a1 1 0 0 0-1-1Zm-6.41-3.496-1.795 1.795a1 1 0 1 0 1.414 1.414l3.5-3.5a1.003 1.003 0 0 0 0-1.417l-3.5-3.5a1 1 0 0 0-1.414 1.414l1.794 1.794H8.27A5.277 5.277 0 0 0 3 9.271V13.5a1 1 0 0 0 2 0V9.271a3.275 3.275 0 0 1 3.271-3.27Z'
88
- > </ path >
89
- </ svg >
90
-
91
- < svg
92
- aria-label = 'Share'
110
+ aria-label = 'Comment'
93
111
color = ''
94
- fill = 'rgb(243, 245, 247) '
112
+ fill = ''
95
113
height = '20'
96
114
role = 'img'
97
115
viewBox = '0 0 24 24'
98
116
width = '20'
117
+ onClick = { onOpen }
99
118
>
100
- < title > Share</ title >
101
- < line
102
- fill = 'none'
103
- stroke = 'currentColor'
104
- strokeLinejoin = 'round'
105
- strokeWidth = '2'
106
- x1 = '22'
107
- x2 = '9.218'
108
- y1 = '3'
109
- y2 = '10.083'
110
- > </ line >
111
- < polygon
119
+ < title > Comment</ title >
120
+ < path
121
+ d = 'M20.656 17.008a9.993 9.993 0 1 0-3.59 3.615L22 22Z'
112
122
fill = 'none'
113
- points = '11.698 20.334 22 3.001 2 3.001 9.218 10.084 11.698 20.334'
114
123
stroke = 'currentColor'
115
124
strokeLinejoin = 'round'
116
125
strokeWidth = '2'
117
- > </ polygon >
126
+ > </ path >
118
127
</ svg >
128
+
129
+ < RepostSVG />
130
+ < ShareSVG />
119
131
</ Flex >
120
132
121
133
< Flex gap = { 2 } alignItems = { "center" } >
@@ -127,8 +139,84 @@ const Actions = ({ post: post_ }) => {
127
139
{ post . likes . length } likes
128
140
</ Text >
129
141
</ Flex >
142
+
143
+ < Modal isOpen = { isOpen } onClose = { onClose } >
144
+ < ModalOverlay />
145
+ < ModalContent >
146
+ < ModalHeader > </ ModalHeader >
147
+ < ModalCloseButton />
148
+ < ModalBody pb = { 6 } >
149
+ < FormControl >
150
+ < Input
151
+ placeholder = 'Reply goes here..'
152
+ value = { reply }
153
+ onChange = { ( e ) => setReply ( e . target . value ) }
154
+ />
155
+ </ FormControl >
156
+ </ ModalBody >
157
+
158
+ < ModalFooter >
159
+ < Button colorScheme = 'blue' size = { "sm" } mr = { 3 } isLoading = { isReplying } onClick = { handleReply } >
160
+ Reply
161
+ </ Button >
162
+ </ ModalFooter >
163
+ </ ModalContent >
164
+ </ Modal >
130
165
</ Flex >
131
166
) ;
132
167
} ;
133
168
134
169
export default Actions ;
170
+
171
+ const RepostSVG = ( ) => {
172
+ return (
173
+ < svg
174
+ aria-label = 'Repost'
175
+ color = 'currentColor'
176
+ fill = 'currentColor'
177
+ height = '20'
178
+ role = 'img'
179
+ viewBox = '0 0 24 24'
180
+ width = '20'
181
+ >
182
+ < title > Repost</ title >
183
+ < path
184
+ fill = ''
185
+ d = 'M19.998 9.497a1 1 0 0 0-1 1v4.228a3.274 3.274 0 0 1-3.27 3.27h-5.313l1.791-1.787a1 1 0 0 0-1.412-1.416L7.29 18.287a1.004 1.004 0 0 0-.294.707v.001c0 .023.012.042.013.065a.923.923 0 0 0 .281.643l3.502 3.504a1 1 0 0 0 1.414-1.414l-1.797-1.798h5.318a5.276 5.276 0 0 0 5.27-5.27v-4.228a1 1 0 0 0-1-1Zm-6.41-3.496-1.795 1.795a1 1 0 1 0 1.414 1.414l3.5-3.5a1.003 1.003 0 0 0 0-1.417l-3.5-3.5a1 1 0 0 0-1.414 1.414l1.794 1.794H8.27A5.277 5.277 0 0 0 3 9.271V13.5a1 1 0 0 0 2 0V9.271a3.275 3.275 0 0 1 3.271-3.27Z'
186
+ > </ path >
187
+ </ svg >
188
+ ) ;
189
+ } ;
190
+
191
+ const ShareSVG = ( ) => {
192
+ return (
193
+ < svg
194
+ aria-label = 'Share'
195
+ color = ''
196
+ fill = 'rgb(243, 245, 247)'
197
+ height = '20'
198
+ role = 'img'
199
+ viewBox = '0 0 24 24'
200
+ width = '20'
201
+ >
202
+ < title > Share</ title >
203
+ < line
204
+ fill = 'none'
205
+ stroke = 'currentColor'
206
+ strokeLinejoin = 'round'
207
+ strokeWidth = '2'
208
+ x1 = '22'
209
+ x2 = '9.218'
210
+ y1 = '3'
211
+ y2 = '10.083'
212
+ > </ line >
213
+ < polygon
214
+ fill = 'none'
215
+ points = '11.698 20.334 22 3.001 2 3.001 9.218 10.084 11.698 20.334'
216
+ stroke = 'currentColor'
217
+ strokeLinejoin = 'round'
218
+ strokeWidth = '2'
219
+ > </ polygon >
220
+ </ svg >
221
+ ) ;
222
+ } ;
0 commit comments