Refactor navigation links to use Next.js routing and improve post handling
- Updated AboutButton to navigate to the about page using Next.js router. - Changed HeaderButtons and MobileNav to link directly to the about page. - Modified Home component to exclude the 'about' post from the posts list. - Added a helper function to strip YAML frontmatter from post summaries. - Enhanced API routes to handle reading and writing markdown files for posts.
This commit is contained in:
98
src/app/about/page.tsx
Normal file
98
src/app/about/page.tsx
Normal file
@@ -0,0 +1,98 @@
|
||||
"use client";
|
||||
|
||||
import React, { useEffect, useState } from "react";
|
||||
|
||||
interface Post {
|
||||
slug: string;
|
||||
title: string;
|
||||
date: string;
|
||||
tags: string[];
|
||||
summary?: string;
|
||||
content: string;
|
||||
createdAt: string;
|
||||
author: string;
|
||||
}
|
||||
|
||||
export default function AboutPage() {
|
||||
const [post, setPost] = useState<Post | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const loadAbout = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const response = await fetch("/api/posts/about");
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
setPost(data);
|
||||
} catch (error) {
|
||||
setError(error instanceof Error ? error.message : "Unknown error");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
loadAbout();
|
||||
}, []);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="min-h-screen bg-white flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4"></div>
|
||||
<p className="text-gray-600">Lade About...</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className="min-h-screen bg-white flex items-center justify-center">
|
||||
<div className="text-center max-w-md mx-auto p-6">
|
||||
<div className="text-red-500 text-6xl mb-4">⚠️</div>
|
||||
<h1 className="text-2xl font-bold text-gray-900 mb-4">Fehler beim Laden</h1>
|
||||
<p className="text-gray-600 mb-6">{error}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!post) {
|
||||
return (
|
||||
<div className="min-h-screen bg-white flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<div className="text-red-500 text-6xl mb-4">❌</div>
|
||||
<h1 className="text-2xl font-bold text-gray-900 mb-4">About nicht gefunden</h1>
|
||||
<p className="text-gray-600 mb-6">Die About-Seite konnte nicht gefunden werden.</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-white">
|
||||
<main className="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<article className="bg-white rounded-lg shadow-sm border p-6 sm:p-8">
|
||||
<header className="mb-8">
|
||||
<h1 className="text-3xl sm:text-4xl font-bold text-gray-900 mb-4 leading-tight">
|
||||
{post.title || "About"}
|
||||
</h1>
|
||||
{post.summary && (
|
||||
<p className="text-lg text-gray-700 mb-6 leading-relaxed">
|
||||
{post.summary}
|
||||
</p>
|
||||
)}
|
||||
</header>
|
||||
<div
|
||||
className="prose prose-lg max-w-none prose-headings:text-gray-900 prose-p:text-gray-700 prose-a:text-blue-600 prose-a:no-underline hover:prose-a:underline prose-strong:text-gray-900 prose-code:text-gray-800 prose-code:bg-gray-100 prose-code:px-1 prose-code:py-0.5 prose-code:rounded prose-pre:bg-gray-900 prose-pre:text-gray-100"
|
||||
dangerouslySetInnerHTML={{ __html: post.content }}
|
||||
/>
|
||||
</article>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user