Skip to content

Commit

Permalink
feat: delete comment mutation
Browse files Browse the repository at this point in the history
  • Loading branch information
warmachine028 committed Nov 16, 2024
1 parent 789f024 commit 40f9173
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 23 deletions.
16 changes: 8 additions & 8 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"uploadthing": "7.3.0",
"zod": "3.24.0-canary.20241107T043915"
},
"description": "A full-stack social media web app built on NextJS 15 for the Next Fans",
"devDependencies": {
"@eslint/js": "^9.14.0",
"@prisma/extension-accelerate": "^1.2.1",
Expand All @@ -79,17 +80,10 @@
},
"license": "MIT",
"name": "next-book",
"description": "A full-stack social media web app built on NextJS 15 for the Next Fans",
"overrides": {
"@types/react": "npm:[email protected]",
"@types/react-dom": "npm:[email protected]"
},
"tags": [
"nextjs",
"nextjs15",
"socialmedia",
"fullstack"
],
"private": true,
"scripts": {
"build": "next build",
Expand All @@ -103,6 +97,12 @@
"prisma:studio": "prisma studio",
"start": "next start"
},
"tags": [
"nextjs",
"nextjs15",
"socialmedia",
"fullstack"
],
"type": "module",
"version": "0.1.0"
}
}
14 changes: 10 additions & 4 deletions client/src/components/comments/Comments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ interface CommentProps {
}

const Comments = ({ post }: CommentProps) => {
const { data, fetchNextPage, hasNextPage, isFetching, isSuccess } = useInfiniteQuery({
const { data, fetchNextPage, hasNextPage, isFetching, isSuccess, isError } = useInfiniteQuery({
queryKey: ['comments', post.id],
queryFn: ({ pageParam }) =>
kyInstance
Expand All @@ -30,7 +30,7 @@ const Comments = ({ post }: CommentProps) => {
<Input post={post} />
<ScrollArea className="divide-y">
{isFetching && (
<div className="my-3 flex w-full items-center justify-center gap-2 text-center text-sm">
<div className="flex w-full items-center justify-center gap-2 py-3 text-center text-sm">
<Loader2 className="animate-spin text-primary" />
<span className="text-muted-foreground">Loading comments...</span>
</div>
Expand All @@ -45,8 +45,14 @@ const Comments = ({ post }: CommentProps) => {
Load previous comments
</Button>
)}
{isSuccess && comments.length === 0 && (
<p className="text-center text-muted-foreground">No comments yet.</p>
{isSuccess &&
!comments.length && ( //
<p className="my-3 text-center text-muted-foreground">No comments yet.</p>
)}
{isError && (
<p className="text-center font-semibold text-destructive">
An error occurred while loading comments.
</p>
)}
{comments.map((comment) => (
<Comment key={comment.id} comment={comment} />
Expand Down
5 changes: 2 additions & 3 deletions client/src/components/comments/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import { type ChangeEvent, type FormEvent, useState } from 'react'
import { Input } from '../ui/input'
import { Button } from '../ui/button'
import { Loader2, SendHorizonal } from 'lucide-react'
import Avatar from '../Avatar'
import UserTooltip from '../users/Tooltip'
import { Avatar } from '@/components'
import Link from 'next/link'

interface InputProps {
Expand Down Expand Up @@ -34,7 +33,7 @@ const CommentInput = ({ post }: InputProps) => {
<Button type="submit" variant="ghost" size="icon" disabled={!input.trim() || isPending}>
{isPending ?
<Loader2 className="animate-spin" />
: <SendHorizonal />}
: <SendHorizonal className="text-primary" />}
</Button>
</form>
)
Expand Down
30 changes: 22 additions & 8 deletions client/src/components/comments/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,7 @@ import { prisma } from '@/lib'
import { validateRequest } from '@/auth'
import { createCommentSchema } from '@/lib/validation'

export const createComment = async ({
post,
content
}: {
//
post: PostData
content: string
}) => {
export const createComment = async ({ post, content }: { post: PostData; content: string }) => {
const { user } = await validateRequest()
if (!user) {
throw new Error('Unauthorized: You are not logged in')
Expand All @@ -29,3 +22,24 @@ export const createComment = async ({
include: getCommentDataInclude(user.id)
})
}

export const deleteComment = async (id: string) => {
const { user } = await validateRequest()

if (!user) {
throw new Error('Unauthorized: You are not logged in')
}

const comment = await prisma.comment.findUnique({ where: { id } })

if (!comment) {
throw new Error('Comment not found')
}
if (comment.authorId !== user.id) {
throw new Error('Unauthorized: You are not the author of this comment')
}
return prisma.comment.delete({
where: { id },
include: getCommentDataInclude(user.id)
})
}
1 change: 1 addition & 0 deletions client/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export { default as useCreatePostMutation } from './useCreatePostMutation'
export { default as useMediaUpload } from './useMediaUpload'
export { default as useCreateCommentMutation } from './useCreateCommentMutation'
export { useUploadThing } from '@/lib/uploadthing'
export { default as useDeleteCommentMutation } from './useDeleteCommentMutation'
43 changes: 43 additions & 0 deletions client/src/hooks/useDeleteCommentMutation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type { CommentsPage } from '@/types'
import { useQueryClient, useMutation, QueryKey, InfiniteData } from '@tanstack/react-query'
import { useToast } from '.'
import { deleteComment } from '@/components/comments/actions'

const useDeleteCommentMutation = () => {
const { toast } = useToast()
const queryClient = useQueryClient()

return useMutation({
mutationFn: deleteComment,
onSuccess: async (deletedComment) => {
const queryKey: QueryKey = ['comments', deletedComment.id]
await queryClient.cancelQueries({ queryKey })
queryClient.setQueryData<InfiniteData<CommentsPage, string | null>>(queryKey, (data) => {
if (!data) {
return
}
return {
pageParams: data.pageParams,
pages: data.pages.map((page) => ({
previousCursor: page.previousCursor,
comments: page.comments.filter((c) => c.id !== deletedComment.id)
}))
}
})

toast({
variant: 'success',
description: 'Comment deleted'
})
},
onError: (error) => {
console.error(error)
toast({
variant: 'destructive',
description: 'Failed to delete comment. Please try again.'
})
}
})
}

export default useDeleteCommentMutation

1 comment on commit 40f9173

@vercel
Copy link

@vercel vercel bot commented on 40f9173 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.