Skip to content

Commit

Permalink
feat: add series
Browse files Browse the repository at this point in the history
  • Loading branch information
ooooorobo committed Feb 12, 2024
1 parent 8203c8d commit 21218cc
Show file tree
Hide file tree
Showing 15 changed files with 248 additions and 122 deletions.
1 change: 1 addition & 0 deletions contentlayer.config.ts
Expand Up @@ -10,6 +10,7 @@ export const Post = defineDocumentType(() => ({
description: { type: "string", required: false },
date: { type: "date", required: true },
tags: { type: "string", required: true }, //{ type: "list", of: { type: "string" }, required: true },
seriesId: { type: "string" },
},
computedFields: {
url: {
Expand Down
6 changes: 3 additions & 3 deletions src/api/og/route.tsx
@@ -1,11 +1,11 @@
import { ImageResponse } from "next/og";
import { getPostDetail } from "@src/business/post";
import { getPostDetail } from "@src/entities/post";

export const runtime = "edge";

export async function GET(request: Request) {
const fontData = await fetch(
"https://github.com/ooooorobo/oooooroblog/raw/main/assets/EASTARJET-Medium.ttf",
"https://github.com/ooooorobo/oooooroblog/raw/main/assets/EASTARJET-Medium.ttf"
).then((res) => res.arrayBuffer());
const { searchParams } = new URL(request.url);

Expand Down Expand Up @@ -37,6 +37,6 @@ export async function GET(request: Request) {
height: 630,
fonts: [{ name: "Easterjet", data: fontData, style: "normal" }],
emoji: "twemoji",
},
}
);
}
4 changes: 2 additions & 2 deletions src/app/page.tsx
@@ -1,7 +1,7 @@
"use client";
import styled from "styled-components";
import { useEffect } from "react";
import { getAllPostMeta } from "@src/business/post";
import { getAllPostMeta } from "@src/entities/post";
import PostList from "@src/components/main/PostList";
import { StorageKey } from "@src/constants/constants";
import Profile from "@src/components/main/Profile";
Expand All @@ -11,7 +11,7 @@ export default function Page() {

useEffect(() => {
const scroll = parseInt(
sessionStorage.getItem(StorageKey.MAIN_SCROLL_Y) ?? "0",
sessionStorage.getItem(StorageKey.MAIN_SCROLL_Y) ?? "0"
);
window.scrollTo({ top: scroll, behavior: "auto" });
}, []);
Expand Down
2 changes: 1 addition & 1 deletion src/app/posts/[slug]/layout.tsx
@@ -1,6 +1,6 @@
import { PropsWithChildren } from "react";
import { Metadata } from "next";
import { getPostDetail } from "@src/business/post";
import { getPostDetail } from "@src/entities/post";
import { PostPageProps } from "@src/app/posts/[slug]/page";

export function generateMetadata({
Expand Down
27 changes: 20 additions & 7 deletions src/app/posts/[slug]/page.tsx
Expand Up @@ -8,8 +8,8 @@ import components from "@src/components/mdx/MDXComponents";
import Profile from "@src/components/main/Profile";
import SidePost from "@src/components/post/SidePost";
import Comment from "@src/components/post/Comment";
import { getPostDetail, getPostMeta } from "@src/business/post";
import { FadeIn } from "@src/styles/animation";
import { getPostDetail, getPostMeta } from "@src/entities/post";
import { SeriesPostTitleList } from "@src/components/series/SeriesPostTitleList";

export type PostPageProps = { params: { slug: string } };

Expand Down Expand Up @@ -41,9 +41,26 @@ export default function PostPage({ params: { slug } }: PostPageProps) {
/>
<WavyLine />
</PostHeader>
{post.seriesId && (
<CommentWrapper>
<SeriesPostTitleList
seriesId={post.seriesId}
currentPostId={post.id}
/>
</CommentWrapper>
)}
<Article>
<MDXContent components={components} />
</Article>
{post.seriesId && (
<CommentWrapper>
<SeriesPostTitleList
seriesId={post.seriesId}
currentPostId={post.id}
defaultOpen={true}
/>
</CommentWrapper>
)}
<ProfileWrapper>
<Profile />
<WavyLine />
Expand All @@ -57,16 +74,12 @@ export default function PostPage({ params: { slug } }: PostPageProps) {
}

const PostHeader = styled.div`
animation: ${FadeIn("0%")} 1.4s;
padding: 0 1rem;
margin-top: 10rem;
margin-bottom: 3rem;
`;

const Article = styled.article`
animation: ${FadeIn("0%")} 1.4s;
max-width: 760px;
margin: 0 auto 5rem auto;
padding: 0 1rem;
Expand All @@ -84,5 +97,5 @@ const ProfileWrapper = styled.div`
const CommentWrapper = styled.div`
max-width: 760px;
margin: auto;
padding: 0 1rem;
padding: 0 1rem 1.5rem 1rem;
`;
43 changes: 0 additions & 43 deletions src/business/post.ts

This file was deleted.

2 changes: 0 additions & 2 deletions src/components/main/PostListElement.tsx
Expand Up @@ -23,11 +23,9 @@ export default function PostListElementComponent({
))}
</div>
<Link href={"/" + post.slug} onClick={onClickPost}>

<Title>{post.meta.title}</Title>
<Description>{post.meta.description}</Description>
<Info>{postedAt}</Info>

</Link>
</Wrapper>
);
Expand Down
74 changes: 74 additions & 0 deletions src/components/series/SeriesPostTitleList.tsx
@@ -0,0 +1,74 @@
import Link from "next/link";
import { css, styled } from "styled-components";
import { getPostBySeriesId } from "@src/entities/post";
import { SeriesMap } from "@src/entities/series/consts/series";

export const SeriesPostTitleList = ({
seriesId,
currentPostId,
defaultOpen = false,
}: {
seriesId: string;
currentPostId?: number;
defaultOpen?: boolean;
}) => {
const series = SeriesMap.get(seriesId);
if (!series) return <></>;

const posts = getPostBySeriesId(seriesId);

return (
<Container open={defaultOpen}>
<Title>
<SeriesTitle>{series.title}</SeriesTitle> 시리즈의 다른 글
</Title>
<ol>
{posts.map((post) => (
<ListItem
key={post.meta.index}
highlighted={post.meta.index === currentPostId}
>
<Link href={"/" + post.slug}>{post.meta.title}</Link>
</ListItem>
))}
</ol>
</Container>
);
};

const Container = styled.details`
background-color: ${({ theme }) => theme.colors.bg.secondary};
padding: 24px;
border-radius: 10px;
ol {
padding-inline-start: 1.2rem;
margin-block-end: 0;
margin-block-start: 12px;
}
`;

const Title = styled.summary`
font-size: ${({ theme }) => theme.fontSizes.m};
`;

const SeriesTitle = styled.span`
font-weight: bold;
margin-left: 4px;
`;

const ListItem = styled.li<{ highlighted: boolean }>`
color: ${({ theme }) => theme.colors.text.placeholder};
${({ highlighted, theme }) =>
highlighted &&
css`
color: ${theme.colors.primaryLight};
`}
&:hover {
text-decoration: underline;
color: ${({ theme, highlighted }) =>
highlighted ? theme.colors.primaryBrighter : theme.colors.text.primary};
}
`;
52 changes: 52 additions & 0 deletions src/entities/post.ts
@@ -0,0 +1,52 @@
import { compareDesc } from "date-fns";
import { Post, allPosts } from "contentlayer/generated";
import { PostListElement } from "@src/types/post";

const getSortedPosts = (type: "desc" | "asc" = "desc") => {
return allPosts.sort((a, b) => {
const compareByDate =
compareDesc(new Date(a.date), new Date(b.date)) *
(type === "desc" ? 1 : -1);
if (compareByDate !== 0) return compareByDate;
return b.id - a.id;
});
};

const convertPostToPostListElement = (meta: Post) => {
return {
slug: meta.url,
meta: {
index: meta.id,
title: meta.title,
description: meta.description || "",
postedAt: meta.date,
category: "",
series: "",
tags: [],
keywords: [],
},
} satisfies PostListElement;
};

export const getAllPostMeta = (): PostListElement[] => {
return getSortedPosts().map(convertPostToPostListElement);
};

export const getPostDetail = (slug: string) => {
const sorted = getSortedPosts();
const postIdx = sorted.findIndex((post) => post._raw.flattenedPath === slug);
return {
postIdx,
detail: sorted[postIdx],
};
};

export const getPostMeta = (idx: number) => {
return getSortedPosts()[idx];
};

export const getPostBySeriesId = (seriesId: string) => {
return getSortedPosts("asc")
.filter((post) => post.seriesId === seriesId)
.map(convertPostToPostListElement);
};
12 changes: 12 additions & 0 deletions src/entities/series/consts/series.ts
@@ -0,0 +1,12 @@
import { Series } from "../types/Series";

export const SeriesMap = new Map<Series["id"], Series>([
[
"web-frontend-test",
{ id: "web-frontend-test", title: "프론트엔드 테스트 가이드" },
],
[
"custom-ssr-server",
{ id: "custom-ssr-server", title: "직접 만들어 보는 SSR 서버" },
],
]);
4 changes: 4 additions & 0 deletions src/entities/series/types/Series.ts
@@ -0,0 +1,4 @@
export type Series = {
id: string;
title: string;
};

0 comments on commit 21218cc

Please sign in to comment.