pompy.dev/apps/blog/src/pages/Page/Page.tsx

140 lines
3.2 KiB
TypeScript

import { useState, useEffect } from "react"
import { Helmet } from "react-helmet-async"
import { useLocation } from "react-router-dom"
import styled from "styled-components"
import MainContent from "../../components/MainContent"
import PostCard from "../../components/PostCard"
import Loading from "../../components/Loading"
import TagList from "../../components/TagList"
import Tag from "../../components/Tag"
import NotFound from "../NotFound"
import SeriesControlButtons from "./SeriesControlButtons"
import {
categorizePageType,
fetchContent,
PageType,
parsePageData,
} from "./helper"
import Meta from "./Meta"
import Toc from "./Toc"
import type { PageData } from "@developomp-site/blog-content/src/types/types"
import contentMap from "../../contentMap"
const StyledTitle = styled.h1`
margin-bottom: 1rem;
word-wrap: break-word;
`
const ProjectImage = styled.img`
max-width: 100%;
`
export default function Page() {
const { pathname } = useLocation()
const [pageData, setPageData] = useState<PageData | undefined>(undefined)
const [pageType, setPageType] = useState<PageType>(PageType.POST)
const [isLoading, setIsLoading] = useState(true)
// this code runs if either the url or the locale changes
useEffect(() => {
const content_id = pathname.replace(/\/$/, "") // remove trailing slash
const pageType = categorizePageType(content_id)
fetchContent(pageType, content_id).then((fetched_content) => {
if (!fetched_content) {
// stop loading without fetching pageData so 404 page will display
setIsLoading(false)
return
}
setPageData(parsePageData(fetched_content, pageType, content_id))
setPageType(pageType)
setIsLoading(false)
})
}, [pathname])
if (isLoading) return <Loading />
if (!pageData) return <NotFound />
return (
<>
<Helmet>
<title>pomp | {pageData.title}</title>
<meta property="og:title" content={pageData.title} />
<meta property="og:type" content="website" />
<meta property="og:image" content="/icon/icon.svg" />
</Helmet>
<MainContent>
{/* next/previous series post buttons */}
{pageType == PageType.SERIES && (
<SeriesControlButtons
seriesHome={pageData.seriesHome}
prevURL={pageData.prev}
nextURL={pageData.next}
/>
)}
<StyledTitle>{pageData.title}</StyledTitle>
<small>
{/* Post tags */}
{pageData.tags.length > 0 && (
<TagList direction="left">
{pageData.tags.map((tag) => {
return (
<div key={pageData?.title + tag}>
<Tag text={tag} />
</div>
)
})}
</TagList>
)}
<br />
{/* Post metadata */}
{[PageType.POST, PageType.SERIES, PageType.SERIES_HOME].includes(
pageType
) && <Meta fetchedPage={pageData} />}
</small>
<hr />
{/* add table of contents if it exists */}
<Toc data={pageData.toc} />
{/* page content */}
<div
dangerouslySetInnerHTML={{
__html: pageData.content,
}}
/>
</MainContent>
{/* series post list */}
{pageType == PageType.SERIES_HOME &&
pageData.order.map((post) => {
return (
<PostCard
key={post}
postData={{
content_id: post,
...contentMap.posts[post],
}}
/>
)
})}
</>
)
}