rewrote page logic and renamed type

This commit is contained in:
Kim, Jimin 2022-01-08 19:30:10 +09:00
parent 67241cf3cb
commit d31dff53ae
3 changed files with 190 additions and 73 deletions

View file

@ -6,7 +6,7 @@ import {
faHourglass,
} from "@fortawesome/free-solid-svg-icons"
import { FetchedPage } from "../../../types/types"
import { PageData } from "../../../types/types"
import theming from "../../styles/theming"
const StyledMetaContainer = styled.div`
@ -17,7 +17,7 @@ const StyledMetaContainer = styled.div`
})};
`
const Meta = (props: { fetchedPage: FetchedPage }) => {
const Meta = (props: { fetchedPage: PageData }) => {
return (
<StyledMetaContainer>
<FontAwesomeIcon icon={faCalendar} />

View file

@ -3,7 +3,7 @@ import { Helmet } from "react-helmet-async"
import { useLocation } from "react-router-dom"
import styled from "styled-components"
import { FetchedPage, Map } from "../../../types/types"
import { PageData, Map } from "../../../types/types"
import MainContent from "../../components/MainContent"
import Loading from "../../components/Loading"
@ -15,6 +15,7 @@ import NextPrevButtons from "./NextPrevButtons"
import Meta from "./Meta"
import Toc from "./Toc"
import portfolio from "../../data/portfolio.json"
import _map from "../../data/map.json"
import { useEffect } from "react"
@ -24,105 +25,219 @@ const StyledTitle = styled.h1`
margin-bottom: 1rem;
`
enum PageType {
POST,
SERIES,
PORTFOLIO_PROJECT,
UNSEARCHABLE,
}
interface SeriesData {
seriesHome: string
prev?: string
next?: string
}
const fetchContent = async (pageType: PageType, url: string) => {
try {
if (pageType == PageType.UNSEARCHABLE) {
return await import(`../../data/content/unsearchable${url}.json`)
}
return await import(`../../data/content${url}.json`)
} catch (err) {
return
}
}
const categorizePageType = (url: string): PageType => {
if (url.startsWith("/post")) return PageType.POST
if (url.startsWith("/series")) return PageType.SERIES
if (url.startsWith("/portfolio")) return PageType.PORTFOLIO_PROJECT
return PageType.UNSEARCHABLE
}
const Page = () => {
const [fetchedPage, setFetchPage] = useState<FetchedPage | undefined>(
undefined
)
const [isPageUnsearchable, setIsPageUnsearchable] = useState(false)
const [isSeries, setIsSeries] = useState(false)
const location = useLocation()
const [pageData, setPageData] = useState<PageData | undefined>(undefined)
const [pageType, setPageType] = useState<PageType>(PageType.POST)
const [isLoading, setIsLoading] = useState(true)
// only used when the page is a series post
// todo: merge with pageData
const [seriesData, setSeriesData] = useState<SeriesData | undefined>(
undefined
)
const [isLoading, setIsLoading] = useState(true)
const location = useLocation()
const fetchContent = async (
isContentUnsearchable: boolean,
url: string
) => {
return isContentUnsearchable
? await import(`../../data/content/unsearchable${url}.json`)
: await import(`../../data/content${url}.json`)
}
useEffect(() => {
let _isSeries = false
const url = location.pathname.replace(/\/$/, "") // remove trailing slash
if (url.startsWith("/series")) _isSeries = true
const _pageType = categorizePageType(url)
if (_isSeries) {
/**
* Test if url is a valid one
*/
let show404 = false
switch (_pageType) {
case PageType.POST: {
if (!map.posts[url]) show404 = true
break
}
case PageType.SERIES: {
if (!(url.slice(0, url.lastIndexOf("/")) in map.series))
show404 = true
break
}
case PageType.PORTFOLIO_PROJECT: {
if (!(url in portfolio.projects)) show404 = true
break
}
case PageType.UNSEARCHABLE: {
if (!map.unsearchable[url]) show404 = true
break
}
}
if (show404) {
setIsLoading(false)
return
}
/**
* Get page data
*/
const pageData: PageData = {
title: "No title",
date: "Unknown date",
readTime: "Unknown read time",
wordCount: 0,
tags: [],
toc: undefined,
content: "No content",
}
fetchContent(_pageType, url).then((fetched_content) => {
if (!fetched_content) {
setIsLoading(false)
return
}
switch (_pageType) {
case PageType.POST: {
const post = map.posts[url]
pageData.content = fetched_content.content
pageData.toc = fetched_content.toc
pageData.title = post.title
pageData.date = post.date
pageData.readTime = post.readTime
pageData.wordCount = post.wordCount
pageData.tags = post.tags || []
break
}
case PageType.SERIES: {
const seriesURL = url.slice(0, url.lastIndexOf("/"))
if (seriesURL in map.series) {
const _curr: number = map.series[seriesURL].order.indexOf(url)
const _prev = _curr - 1
const _next = _curr + 1
const curr = map.series[seriesURL].order.indexOf(url)
const prev = curr - 1
const next = curr + 1
setSeriesData({
seriesHome: seriesURL,
prev:
_prev >= 0
? map.series[seriesURL].order[_prev]
prev >= 0
? map.series[seriesURL].order[prev]
: undefined,
next:
_next < map.series[seriesURL].order.length
? map.series[seriesURL].order[_next]
next < map.series[seriesURL].order.length
? map.series[seriesURL].order[next]
: undefined,
})
const post = map.posts[url]
pageData.content = fetched_content.content
pageData.toc = fetched_content.toc
pageData.title = post.title
pageData.date = post.date
pageData.readTime = post.readTime
pageData.wordCount = post.wordCount
pageData.tags = post.tags || []
break
}
case PageType.PORTFOLIO_PROJECT: {
const data =
portfolio.projects[
url as keyof typeof portfolio.projects
]
console.log(fetched_content)
pageData.content = fetched_content.content
pageData.toc = fetched_content.toc
pageData.title = data.name
// todo: add portfolio data
/*
"image": "/img/portfolio/developomp.com.png",
"overview": "my website for blogging, portfolio, and resume.",
"badges": [
"typescript",
"javascript",
"nodedotjs",
"firebase",
"react",
"html5",
"css3"
],
"repo": "https://github.com/developomp/developomp-site"
*/
break
}
case PageType.UNSEARCHABLE: {
pageData.title = map.unsearchable[url].title
pageData.content = fetched_content.content
break
}
}
// fetch page
const MapPost = map.posts[url]
const fetchedPage: FetchedPage = {
...MapPost,
toc: undefined,
content: "",
tags: [] as string[],
}
setPageType(_pageType)
setPageData(pageData)
let _isUnsearchable = false
if (!MapPost) {
_isUnsearchable = true
setIsPageUnsearchable(_isUnsearchable)
if (!map.unsearchable[url]) {
setIsLoading(false)
return
}
}
fetchContent(_isUnsearchable, url).then((fetched_content) => {
fetchedPage.content = fetched_content.content || "No content"
fetchedPage.toc = fetched_content.toc
fetchedPage.title = _isUnsearchable
? map.unsearchable[url].title
: fetchedPage?.title || "No title"
if (!_isUnsearchable)
fetchedPage.date = fetchedPage?.date || "Unknown date"
setIsSeries(_isSeries)
setFetchPage(fetchedPage)
setIsLoading(false)
})
}, [location])
if (isLoading) return <Loading />
if (!fetchedPage) return <NotFound />
if (!pageData) return <NotFound />
return (
<>
<Helmet>
<title>pomp | {fetchedPage.title}</title>
<title>pomp | {pageData.title}</title>
<meta property="og:title" content={fetchedPage.title} />
<meta property="og:title" content={pageData.title} />
<meta property="og:type" content="website" />
<meta
property="og:image"
@ -131,7 +246,7 @@ const Page = () => {
</Helmet>
<MainContent>
{isSeries ? (
{pageType == PageType.SERIES ? (
<NextPrevButtons
prevURL={seriesData?.prev}
nextURL={seriesData?.next}
@ -139,15 +254,15 @@ const Page = () => {
) : (
<br />
)}
<StyledTitle>{fetchedPage.title}</StyledTitle>
<StyledTitle>{pageData.title}</StyledTitle>
<small>
{/* Post tags */}
{!!fetchedPage.tags.length && (
{!!pageData.tags.length && (
<TagList direction="left">
{fetchedPage.tags.map((tag) => {
{pageData.tags.map((tag) => {
return (
<td key={fetchedPage?.title + tag}>
<td key={pageData?.title + tag}>
<Tag text={tag} />
</td>
)
@ -158,18 +273,20 @@ const Page = () => {
<br />
{/* Post metadata */}
{!isPageUnsearchable && <Meta fetchedPage={fetchedPage} />}
{pageType != PageType.UNSEARCHABLE && (
<Meta fetchedPage={pageData} />
)}
</small>
<hr />
{/* add table of contents if it exists */}
<Toc data={fetchedPage.toc} />
<Toc data={pageData.toc} />
{/* page content */}
<div
dangerouslySetInnerHTML={{
__html: fetchedPage.content,
__html: pageData.content,
}}
/>
</MainContent>

View file

@ -53,7 +53,7 @@ export interface PostData {
tags?: string[]
}
export interface FetchedPage {
export interface PageData {
title: string
date: string
readTime: string