Refactor code structure for improved readability and maintainability
This commit is contained in:
parent
afbf913aec
commit
3c600c06f9
11 changed files with 47 additions and 130 deletions
|
|
@ -1,30 +0,0 @@
|
|||
import { notFound } from "next/navigation";
|
||||
import { readdirSync } from "fs";
|
||||
import { join } from "path";
|
||||
|
||||
export async function generateStaticParams() {
|
||||
const blogDir = join(process.cwd(), "src/app/blog/posts");
|
||||
const files = readdirSync(blogDir).filter((file) => file.endsWith(".mdx"));
|
||||
|
||||
return files.map((file) => ({
|
||||
slug: file.replace(".mdx", ""),
|
||||
}));
|
||||
}
|
||||
|
||||
export default async function BlogPost({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ slug: string }>;
|
||||
}) {
|
||||
const { slug } = await params;
|
||||
|
||||
try {
|
||||
const Post = (
|
||||
await import(`@/app/blog/posts/${slug}.mdx`)
|
||||
).default;
|
||||
|
||||
return <Post />;
|
||||
} catch {
|
||||
notFound();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
import type { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Blog",
|
||||
description: "My thoughts and experiences",
|
||||
};
|
||||
|
||||
export default function BlogLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<article className="min-h-screen max-w-3xl mx-auto px-6 py-12">
|
||||
<div className="prose prose-invert max-w-none">
|
||||
{children}
|
||||
</div>
|
||||
</article>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
title: "삣삐"
|
||||
description: "삣삐"
|
||||
date: "2025-11-20"
|
||||
tags: ["삣삐"]
|
||||
---
|
||||
|
||||
# 삣삐
|
||||
|
|
@ -164,3 +164,22 @@
|
|||
"Segoe UI Symbol", sans-serif;
|
||||
}
|
||||
}
|
||||
|
||||
.image-scale {
|
||||
transition-property:scale,border-radius box-shadow;
|
||||
transition-duration:.7s;
|
||||
transition-timing-function:var(--ease-out-expo)
|
||||
}
|
||||
@media (hover:hover) {
|
||||
.image-scale:hover {
|
||||
--tw-scale-x:105%;
|
||||
--tw-scale-y:105%;
|
||||
--tw-scale-z:105%;
|
||||
scale:var(--tw-scale-x)var(--tw-scale-y);
|
||||
border-radius:var(--radius-lg)
|
||||
}
|
||||
}
|
||||
.image-scale:hover {
|
||||
z-index:10;
|
||||
box-shadow:0 15px 45px #0006
|
||||
}
|
||||
|
|
@ -1,16 +1,33 @@
|
|||
import BlogList from "@/components/BlogList";
|
||||
import NeoFetch from "@/components/NeoFetch";
|
||||
import Projects from "@/components/Projects";
|
||||
import TimelineComponent from "@/components/timeline";
|
||||
import Top from "@/components/Top";
|
||||
import Image from "next/image";
|
||||
|
||||
export default async function BlogIndex() {
|
||||
return (
|
||||
<main className="min-h-screen">
|
||||
<Top />
|
||||
<section id="terminal" className="h-screen">
|
||||
<NeoFetch />
|
||||
<div className="px-12 mt-8">
|
||||
<main className="min-h-screen w-screen">
|
||||
<section id="top" className="max-w-3xl w-full mx-auto px-4">
|
||||
<div className="flex flex-row items-center w-full h-full gap-6 mt-8">
|
||||
<Image
|
||||
src="/Frame.svg"
|
||||
alt="logo"
|
||||
className="w-fit h-fit"
|
||||
width={30}
|
||||
height={30}
|
||||
/>
|
||||
<h1 className="font-ntype text-3xl">
|
||||
<a href="mailto:me@imnya.ng">me@imnya.ng</a>
|
||||
</h1>
|
||||
</div>
|
||||
<figure className="my-8 w-full h-auto">
|
||||
<picture className="block bg-gray-100 rounded-xl aspect-3-2 overflow-hidden image-scale object-shadowed mt-8">
|
||||
<Image src="/1500x500.jpg" alt="test image" className="object-cover object-center transition-transform duration-300 hover:scale-105" width={3168} height={1344} />
|
||||
</picture>
|
||||
</figure>
|
||||
</section>
|
||||
<section id="about" className="h-screen max-w-3xl mx-auto px-4">
|
||||
<div className=" mt-8">
|
||||
<h1 className="text-2xl font-bold mb-4 w-full">💕 About</h1>
|
||||
<p>오직 <strong>호기심과 실행력</strong>으로만 성장해 온 <strong>개발자, 정보보안전문가</strong> 남현석입니다.</p>
|
||||
<p><strong>초등학교 시절 운영체제</strong>에 흥미를 느껴 컴퓨터를 시작했고, 이후 프로그래밍에 관심을 갖게 되었습니다.</p>
|
||||
|
|
@ -23,9 +40,7 @@ export default async function BlogIndex() {
|
|||
</div>
|
||||
|
||||
<TimelineComponent />
|
||||
<div className="px-12 mt-8 w-full lg:w-2/3 xl:w-1/2">
|
||||
<BlogList />
|
||||
</div>
|
||||
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,55 +0,0 @@
|
|||
import Link from "next/link";
|
||||
import { getPosts, type Post } from "@/lib/blog";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { ArrowRight } from "lucide-react";
|
||||
|
||||
|
||||
export default async function BlogList() {
|
||||
const posts = await getPosts();
|
||||
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
{posts.length === 0 ? (
|
||||
<div className="rounded-lg border bg-background px-4 py-3">
|
||||
<p className="text-muted-foreground text-center">No posts yet...</p>
|
||||
</div>
|
||||
) : (
|
||||
posts.map((post) => (
|
||||
<Link
|
||||
key={post.slug}
|
||||
href={`/blog/${post.slug}`}
|
||||
className="block group"
|
||||
>
|
||||
<div className="rounded-lg border bg-background px-4 py-3 hover:bg-muted transition-colors">
|
||||
<div className="flex justify-between items-start gap-4 mb-2">
|
||||
<div className="flex-1">
|
||||
<h3 className="font-semibold group-hover:text-primary transition-colors">
|
||||
{post.title}
|
||||
</h3>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
{post.date}
|
||||
</p>
|
||||
</div>
|
||||
<ArrowRight className="h-4 w-4 opacity-0 group-hover:opacity-100 transition-opacity shrink-0" />
|
||||
</div>
|
||||
{post.description && (
|
||||
<p className="text-sm text-muted-foreground mb-2">
|
||||
{post.description}
|
||||
</p>
|
||||
)}
|
||||
{post.tags && post.tags.length > 0 && (
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
{post.tags.map((tag) => (
|
||||
<Badge key={tag} variant="secondary" className="text-xs">
|
||||
{tag}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Link>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ const projects = [
|
|||
|
||||
export default function Projects() {
|
||||
return (
|
||||
<section className="break-keep break-words w-full lg:w-2/3 xl:w-1/2">
|
||||
<section className="break-keep break-words w-full">
|
||||
<div className="space-y-8">
|
||||
{projects.map((project, idx) => (
|
||||
<div className="space-y-2" key={idx}>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export default function TimelineComponent() {
|
|||
return (
|
||||
<div
|
||||
id="timeline"
|
||||
className="w-full lg:w-2/3 xl:w-1/2 flex flex-col items-center justify-center px-12 mt-8"
|
||||
className="w-full flex flex-col items-center justify-center mt-8"
|
||||
>
|
||||
<div className="w-full">
|
||||
<h1 className="text-2xl font-bold mb-4 w-full">🌠 수상 및 교육</h1>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue