mirror of
https://github.com/r-freeman/portfolio.git
synced 2024-11-21 18:45:41 +00:00
Added Article navigation
All checks were successful
Build And Publish / BuildAndPublish (push) Successful in 2m44s
All checks were successful
Build And Publish / BuildAndPublish (push) Successful in 2m44s
This commit is contained in:
parent
9bd9188921
commit
c963803320
7
app/api/articles/route.ts
Normal file
7
app/api/articles/route.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import {getAllArticles} from '@/lib/getAllArticles'
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const articles = await getAllArticles()
|
||||
|
||||
return new Response(JSON.stringify(articles), {status: 200})
|
||||
}
|
@ -5,6 +5,7 @@ import {Prose} from '@/components/ui/Prose'
|
||||
import {Views} from '@/components/ui/Views'
|
||||
import {ArrowDownIcon} from '@/components/icons/ArrowDownIcon'
|
||||
import {formatDate} from '@/lib/formatDate'
|
||||
import ArticleNav from '@/components/ui/ArticleNav'
|
||||
|
||||
type ArticleLayout = {
|
||||
title: string
|
||||
@ -12,7 +13,6 @@ type ArticleLayout = {
|
||||
description: string
|
||||
slug: string
|
||||
children?: ReactNode
|
||||
ogImage?: string
|
||||
}
|
||||
|
||||
const gradients = [
|
||||
@ -26,10 +26,8 @@ const gradients = [
|
||||
export function ArticleLayout({
|
||||
title,
|
||||
date,
|
||||
description,
|
||||
slug,
|
||||
children,
|
||||
ogImage
|
||||
}: ArticleLayout) {
|
||||
|
||||
return (
|
||||
@ -60,6 +58,7 @@ export function ArticleLayout({
|
||||
</header>
|
||||
<Prose className="mt-8" data-mdx-content>{children}</Prose>
|
||||
</article>
|
||||
<ArticleNav slug={slug}/>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
|
85
components/ui/ArticleNav.tsx
Normal file
85
components/ui/ArticleNav.tsx
Normal file
@ -0,0 +1,85 @@
|
||||
'use client'
|
||||
|
||||
import React, {ReactElement, useEffect, useState} from 'react'
|
||||
import fetcher from '@/lib/fetcher'
|
||||
import useSWR from 'swr'
|
||||
import {Card} from '@/components/ui/Card'
|
||||
|
||||
|
||||
type Article = {
|
||||
slug: string
|
||||
authors: string
|
||||
title: string
|
||||
date: string
|
||||
description: string
|
||||
}
|
||||
|
||||
type FetchArticlesResponse = {
|
||||
data: Article[]
|
||||
error: string
|
||||
isLoading: boolean
|
||||
}
|
||||
|
||||
type ArticleNavProps = {
|
||||
slug: string
|
||||
}
|
||||
|
||||
type PaginationProps = {
|
||||
next: Article | null
|
||||
prev: Article | null
|
||||
}
|
||||
|
||||
function useFetchArticles() {
|
||||
const {data, error, isLoading} = useSWR(`/api/articles/`, fetcher) as FetchArticlesResponse
|
||||
|
||||
return {
|
||||
articles: data,
|
||||
isLoading,
|
||||
isError: error
|
||||
}
|
||||
}
|
||||
|
||||
export default function ArticleNav({slug}: ArticleNavProps): ReactElement | null {
|
||||
const {articles, isLoading, isError} = useFetchArticles()
|
||||
const [{next, prev}, setPagination] = useState<PaginationProps>({next: null, prev: null})
|
||||
|
||||
useEffect(() => {
|
||||
const findAdjacentArticles = (articles: Article[], slug: string) => {
|
||||
if (articles) {
|
||||
const index = articles.findIndex(article => article.slug === slug)
|
||||
const next = index > 0 ? articles[index - 1] : null
|
||||
const prev = index < articles.length - 1 ? articles[index + 1] : null
|
||||
|
||||
setPagination({next, prev})
|
||||
}
|
||||
}
|
||||
|
||||
findAdjacentArticles(articles, slug)
|
||||
}, [articles, slug])
|
||||
|
||||
if (isError) return null
|
||||
|
||||
return (
|
||||
<section className="mt-24">
|
||||
<ul
|
||||
role="list"
|
||||
className="grid grid-cols-1 gap-x-12 gap-y-16 sm:grid-cols-2"
|
||||
>
|
||||
{prev !== null &&
|
||||
<Card as="li" key={prev.slug}>
|
||||
<h2 className="text-base font-semibold transition group-hover:text-indigo-500 text-zinc-800 dark:text-zinc-100">
|
||||
<Card.Link href={`/writing/${prev.slug}`}>{prev.title}</Card.Link>
|
||||
</h2>
|
||||
</Card>
|
||||
}
|
||||
{next !== null &&
|
||||
<Card as="li" key={next.slug}>
|
||||
<h2 className="text-base font-semibold transition group-hover:text-indigo-500 text-zinc-800 dark:text-zinc-100">
|
||||
<Card.Link href={`/writing/${next.slug}`}>{next.title}</Card.Link>
|
||||
</h2>
|
||||
</Card>
|
||||
}
|
||||
</ul>
|
||||
</section>
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue
Block a user