Render comments on server
All checks were successful
Build And Publish / BuildAndPublish (push) Successful in 3m18s

This commit is contained in:
Ryan Freeman 2025-03-27 20:53:49 +00:00
parent fd33bcced9
commit f8d668e4f3
4 changed files with 32 additions and 47 deletions

View File

@ -1,32 +0,0 @@
import {createClient} from '@/lib/supabase/server'
import {NextResponse} from 'next/server'
export async function GET(request: Request, {params}: { params: Promise<{ slug: string }> }) {
const {slug} = await params
if (typeof slug !== 'undefined') {
try {
const supabase = await createClient()
const {data: comments, error} = await supabase
.from('comments')
.select(`
id,
content,
published,
created_at,
user:users!inner(id, name, image),
article:articles!inner(id, title, slug)
`)
.eq('article.slug', slug)
.eq('published', true)
.order('created_at', {ascending: false})
if (comments !== null && comments?.length > 0) {
return NextResponse.json({comments: comments})
}
return NextResponse.json([])
} catch (e) {
return new Response(JSON.stringify({status: 'Internal Server Error'}), {status: 500})
}
}
return new Response(JSON.stringify({status: 'Not Found'}), {status: 404})
}

View File

@ -8,6 +8,7 @@ import {formatDate} from '@/lib/formatDate'
import ArticleNav from '@/components/ui/ArticleNav'
import Comments from '@/components/ui/Comments'
import {getAllArticles} from '@/lib/getAllArticles'
import {getComments} from '@/lib/getComments'
type ArticleLayout = {
title: string
@ -50,6 +51,7 @@ export async function ArticleLayout({
slug,
children
}: ArticleLayout) {
const comments = await getComments(slug)
const articles = await getAllArticles(false)
const {prev, next} = findAdjacentArticles(articles, slug)
@ -81,7 +83,7 @@ export async function ArticleLayout({
</header>
<Prose className="mt-8" data-mdx-content>{children}</Prose>
</article>
<Comments slug={slug}/>
<Comments slug={slug} comments={comments}/>
<ArticleNav prev={prev} next={next}/>
</div>
</div>

View File

@ -3,9 +3,7 @@
import React, {ReactNode, useActionState} from 'react'
import {useSession} from 'next-auth/react'
import Image from 'next/image'
import useSWR from 'swr'
import clsx from 'clsx'
import fetcher from '@/lib/fetcher'
import {formatDate} from '@/lib/formatDate'
import {addComment, loginWithGitHub} from '@/app/actions/comments'
import {Button} from '@/components/ui/Button'
@ -65,7 +63,7 @@ Comments.Status = function Status({children}: CommentsStatusProps) {
return (
<p aria-live="polite" role="status"
className={clsx('text-base font-semibold',
className={clsx('text-sm font-semibold',
!isError ? 'text-green-800 dark:text-green-600' : 'text-red-800 dark:text-red-600')}>
{children}
</p>
@ -134,21 +132,14 @@ Comments.Form = function Form({slug}: CommentsProps) {
type CommentsProps = {
slug: string
comments?: any
}
export default function Comments({slug}: CommentsProps) {
const {data, isLoading, error} = useSWR(`/api/comments/${slug}`, fetcher) as {
data: { comments: Comment[] },
isLoading: boolean,
error: string
}
if (error) return null
export default function Comments({slug, comments}: CommentsProps) {
return (
<div className="mt-24">
{!isLoading &&
<Comments.List comments={data?.comments}/>
{comments &&
<Comments.List comments={comments}/>
}
<Comments.Form slug={slug}/>
</div>

24
lib/getComments.ts Normal file
View File

@ -0,0 +1,24 @@
import {createClient} from '@/lib/supabase/client'
export async function getComments(slug: string) {
try {
const supabase = await createClient()
const {data: comments, error} = await supabase
.from('comments')
.select(`
id,
content,
published,
created_at,
user:users!inner(id, name, image),
article:articles!inner(id, title, slug)
`)
.eq('article.slug', slug)
.eq('published', true)
.order('created_at', {ascending: false})
return comments
} catch (error) {
console.error(error)
}
}