Skip to content

Commit

Permalink
feat: delete comment functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
warmachine028 committed Nov 16, 2024
1 parent 5fa32ad commit 24666f4
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 4 deletions.
16 changes: 14 additions & 2 deletions client/src/components/comments/Comment.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import type { CommentData } from '@/types'
import Link from 'next/link'
import { UserTooltip } from '../users'
import { Avatar } from '@/components'
import Link from 'next/link'
import { formatRelativeDate } from '@/lib/utils'
import { useSession } from '@/hooks'
import { CommentMoreButton } from '.'

interface CommentProps {
comment: CommentData
}

const Comment = ({ comment }: CommentProps) => {
const { user } = useSession()

return (
<div className="flex gap-3 py-3">
<div className="group/comment flex gap-3 py-3">
<span className="hidden sm:inline">
<UserTooltip user={comment.author}>
<Link href={`/users/${comment.author.userName}`}>
Expand All @@ -29,8 +33,16 @@ const Comment = ({ comment }: CommentProps) => {
</div>
<p>{comment.content}</p>
</div>
{comment.authorId === user.id && (
<CommentMoreButton
comment={comment}
className="ms-auto opacity-0 transition-opacity group-hover/comment:opacity-100"
/>
)}
</div>
)
}

Comment.displayName = 'Comment'

export default Comment
91 changes: 91 additions & 0 deletions client/src/components/comments/CommentMoreButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { CommentData } from '@/types'
import { useState } from 'react'
import { DeleteCommentDialog } from '.'
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '../ui/dropdown-menu'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/tooltip'
import { Button } from '../ui/button'
import { CircleCheckBig, Info, MoreHorizontal, Trash2, TriangleAlert } from 'lucide-react'
import { cn } from '@/lib/utils'

interface CommentMoreButtonProps {
comment: CommentData
className?: string
}

const CommentMoreButton = ({ comment, className }: CommentMoreButtonProps) => {
const [showDeleteDialog, setShowDeleteDialog] = useState(false)
return (
<TooltipProvider>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button size="icon" variant="ghost" className={cn(className, 'data-[state=open]:opacity-100')}>
<MoreHorizontal className="size-5 text-muted-foreground" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<Tooltip>
<TooltipTrigger asChild>
<DropdownMenuItem onClick={() => setShowDeleteDialog(true)}>
<span className="flex items-center gap-3 text-destructive">
<Trash2 className="size-4" />
Delete
</span>
</DropdownMenuItem>
</TooltipTrigger>
<TooltipContent side="left">
<p>Destructive action</p>
</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<DropdownMenuItem>
<span className="flex items-center gap-3 text-success">
<CircleCheckBig className="size-4" />
Success
</span>
</DropdownMenuItem>
</TooltipTrigger>
<TooltipContent side="left">
<p>Success action</p>
</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<DropdownMenuItem>
<span className="flex items-center gap-3 text-info">
<Info className="size-4" />
Info
</span>
</DropdownMenuItem>
</TooltipTrigger>
<TooltipContent side="left">
<p>Info action</p>
</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<DropdownMenuItem>
<span className="flex items-center gap-3 text-warning">
<TriangleAlert className="size-4" />
Warning
</span>
</DropdownMenuItem>
</TooltipTrigger>
<TooltipContent side="left">
<p>Warning action</p>
</TooltipContent>
</Tooltip>
</DropdownMenuContent>
</DropdownMenu>
<DeleteCommentDialog
comment={comment}
open={showDeleteDialog}
onClose={() => setShowDeleteDialog(false)}
/>
</TooltipProvider>
)
}

CommentMoreButton.displayName = 'CommentMoreButton'

export default CommentMoreButton
2 changes: 2 additions & 0 deletions client/src/components/comments/Comments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,6 @@ const Comments = ({ post }: CommentProps) => {
)
}

Comments.displayName = 'Comments'

export default Comments
52 changes: 52 additions & 0 deletions client/src/components/comments/DeleteCommentDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
'use client'

import { CommentData } from '@/types'
import { useDeleteCommentMutation } from '@/hooks'
import { Dialog, DialogHeader, DialogContent, DialogTitle, DialogDescription, DialogFooter } from '../ui/dialog'
import { LoadingButton } from '@/components'
import { Button } from '../ui/button'

interface DeleteCommentDialogProps {
comment: CommentData
open: boolean
onClose: () => void
}

const DeleteCommentDialog = ({ comment, open, onClose }: DeleteCommentDialogProps) => {
const mutation = useDeleteCommentMutation()

const handleOpenChange = (open: boolean) => {
if (!open || mutation.isPending) {
onClose()
}
}

return (
<Dialog open={open} onOpenChange={handleOpenChange}>
<DialogContent>
<DialogHeader>
<DialogTitle>Delete comment?</DialogTitle>
<DialogDescription>
Are you sure you want to delete this comment? This action can't be undone.
</DialogDescription>
</DialogHeader>
<DialogFooter>
<LoadingButton
variant="destructive"
onClick={() => mutation.mutate(comment.id, { onSuccess: onClose })}
loading={mutation.isPending}
>
Delete
</LoadingButton>
<Button variant="outline" onClick={onClose} disabled={mutation.isPending}>
Cancel
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
)
}

DeleteCommentDialog.displayName = 'DeleteCommentDialog'

export default DeleteCommentDialog
1 change: 1 addition & 0 deletions client/src/components/comments/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ const CommentInput = ({ post }: InputProps) => {
)
}

CommentInput.displayName = 'CommentInput'
export default CommentInput
2 changes: 2 additions & 0 deletions client/src/components/comments/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export { default as Comments } from './Comments'
export { default as Input } from './Input'
export { default as Comment } from './Comment'
export { default as CommentMoreButton } from './CommentMoreButton'
export { default as DeleteCommentDialog } from './DeleteCommentDialog'
2 changes: 1 addition & 1 deletion client/src/components/posts/PostMoreButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { PostData } from '@/types'
import { useState } from 'react'
import DeletePostDialog from './DeletePostDialog'
import { DeletePostDialog } from '.'
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '../ui/dropdown-menu'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/tooltip'
import { Button } from '../ui/button'
Expand Down
2 changes: 1 addition & 1 deletion client/src/hooks/useDeleteCommentMutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const useDeleteCommentMutation = () => {
return useMutation({
mutationFn: deleteComment,
onSuccess: async (deletedComment) => {
const queryKey: QueryKey = ['comments', deletedComment.id]
const queryKey: QueryKey = ['comments', deletedComment.postId]
await queryClient.cancelQueries({ queryKey })
queryClient.setQueryData<InfiniteData<CommentsPage, string | null>>(queryKey, (data) => {
if (!data) {
Expand Down

1 comment on commit 24666f4

@vercel
Copy link

@vercel vercel bot commented on 24666f4 Nov 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.