From be43edc6a6cf9c0ac131f95cc970b1e2048747b5 Mon Sep 17 00:00:00 2001 From: Poyraz Avsever Date: Wed, 11 Mar 2026 11:03:00 +0300 Subject: [PATCH] refactor(blog): drive blog and home sections from markdown data --- app/blog/[slug]/page.tsx | 6 +- app/blog/page.tsx | 14 +- app/page.tsx | 7 +- components/blog-content.tsx | 141 +++++++----- components/blog-detail-content.tsx | 265 +--------------------- components/home-hero.tsx | 20 +- data/blog-engagement.ts | 73 ------ data/blog.ts | 351 +++++++++++++---------------- lib/command-palette-links.ts | 35 ++- lib/home-news.ts | 25 -- 10 files changed, 304 insertions(+), 633 deletions(-) delete mode 100644 data/blog-engagement.ts delete mode 100644 lib/home-news.ts diff --git a/app/blog/[slug]/page.tsx b/app/blog/[slug]/page.tsx index 3308caf..c2a1e95 100644 --- a/app/blog/[slug]/page.tsx +++ b/app/blog/[slug]/page.tsx @@ -1,7 +1,6 @@ import { notFound } from "next/navigation"; import { BlogDetailContent } from "@/components/blog-detail-content"; import { getBlogDetailBySlug } from "@/data/blog-detail"; -import { getBlogEngagementBySlug } from "@/data/blog-engagement"; type BlogDetailPageProps = { params: Promise<{ slug: string }>; @@ -9,12 +8,11 @@ type BlogDetailPageProps = { export default async function BlogDetailPage({ params }: BlogDetailPageProps) { const { slug } = await params; - const post = getBlogDetailBySlug(slug); - const engagement = getBlogEngagementBySlug(slug); + const post = await getBlogDetailBySlug(slug); if (!post) { notFound(); } - return ; + return ; } diff --git a/app/blog/page.tsx b/app/blog/page.tsx index d193013..32597eb 100644 --- a/app/blog/page.tsx +++ b/app/blog/page.tsx @@ -1,5 +1,15 @@ import { BlogContent } from "@/components/blog-content"; +import { getBlogPageData } from "@/data/blog"; -export default function BlogPage() { - return ; +type BlogPageProps = { + searchParams?: Promise<{ page?: string }>; +}; + +export default async function BlogPage({ searchParams }: BlogPageProps) { + const resolved = searchParams ? await searchParams : undefined; + const page = Number(resolved?.page ?? "1"); + const currentPage = Number.isFinite(page) && page > 0 ? Math.floor(page) : 1; + const data = await getBlogPageData(currentPage, 12); + + return ; } diff --git a/app/page.tsx b/app/page.tsx index 3f27958..7805e5e 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,11 +1,14 @@ import { HomeHero } from "@/components/home-hero"; import { HomeVideosSection } from "@/components/home-videos-section"; import { ReferencesSection } from "@/components/references-section"; +import { getHomeBlogNews } from "@/data/blog"; + +export default async function Home() { + const homeNews = await getHomeBlogNews(3); -export default function Home() { return (
- +
diff --git a/components/blog-content.tsx b/components/blog-content.tsx index 155e66d..e8bfdf7 100644 --- a/components/blog-content.tsx +++ b/components/blog-content.tsx @@ -1,5 +1,4 @@ -"use client"; - +import Link from "next/link"; import { Badge, Card, Typography } from "poyraz-ui/atoms"; import { ArticleCard, @@ -11,19 +10,25 @@ import { PaginationNext, PaginationPrevious, } from "poyraz-ui/molecules"; -import { - BLOG_ARTICLES, - BLOG_CATEGORIES, - BLOG_NEWS, - RECENT_COMMENTS, -} from "@/data/blog"; +import type { BlogPageData } from "@/data/blog"; + +type BlogContentProps = { + data: BlogPageData; +}; + +function pageHref(page: number) { + return page <= 1 ? "/blog" : `/blog?page=${page}`; +} + +export function BlogContent({ data }: BlogContentProps) { + const pageNumbers = Array.from({ length: data.totalPages }, (_, index) => index + 1); + const hasArticles = data.articles.length > 0; -export function BlogContent() { return (
- {BLOG_NEWS.map((post) => ( + {data.news.map((post) => ( Kategoriler
- {BLOG_CATEGORIES.map((category, index) => ( + {data.categories.map((category, index) => ( - Son yorumlar -
- {RECENT_COMMENTS.map((comment) => ( - - - {comment.author} - - - {comment.text} - - - {comment.date} - + Podcast İçerikleri +
+ {data.podcastGroups.map((group) => ( + +
+ + {group.title} + + + Tümünü Gör + +
+ +
+ {group.items.map((episode) => ( +
+ + {episode.title} + + + {episode.date} + +
+ ))} +
))}
-
-
- {BLOG_ARTICLES.map((post) => ( - - ))} -
+ {hasArticles ? ( +
+ {data.articles.map((post) => ( + + ))} +
+ ) : ( + + + Henüz blog yazısı bulunmuyor. + + + )} - + - + + + {pageNumbers.map((page) => ( + + + {page} + + + ))} + - - 1 - - - - 2 - - - 3 - - - + = data.totalPages} + /> diff --git a/components/blog-detail-content.tsx b/components/blog-detail-content.tsx index 408964a..f9671f3 100644 --- a/components/blog-detail-content.tsx +++ b/components/blog-detail-content.tsx @@ -5,31 +5,18 @@ import Link from "next/link"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; import { useEffect, useMemo, useRef, useState } from "react"; -import { Icon } from "@iconify/react"; import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; import { vscDarkPlus } from "react-syntax-highlighter/dist/esm/styles/prism"; -import { - Avatar, - AvatarFallback, - AvatarImage, - Badge, - Button, - Card, - Textarea, - Typography, -} from "poyraz-ui/atoms"; -import { Sheet, SheetContent, SheetTitle, SheetTrigger } from "poyraz-ui/molecules"; +import { Badge, Card, Typography } from "poyraz-ui/atoms"; import type { BlogDetail } from "@/data/blog-detail"; -import type { BlogComment, BlogEngagement } from "@/data/blog-engagement"; type BlogDetailContentProps = { post: BlogDetail; - engagement: BlogEngagement; }; function MermaidBlock({ chart }: { chart: string }) { - const [svg, setSvg] = useState(""); - const [error, setError] = useState(""); + const [svg, setSvg] = useState(""); + const [error, setError] = useState(""); const idRef = useRef(`mermaid-${Math.random().toString(36).slice(2)}`); useEffect(() => { @@ -40,6 +27,7 @@ function MermaidBlock({ chart }: { chart: string }) { const mermaid = (await import("mermaid")).default; mermaid.initialize({ startOnLoad: false, theme: "neutral", securityLevel: "loose" }); const { svg: rendered } = await mermaid.render(idRef.current, chart); + if (mounted) { setSvg(rendered); setError(""); @@ -84,88 +72,22 @@ function MermaidBlock({ chart }: { chart: string }) { ); } -export function BlogDetailContent({ post, engagement }: BlogDetailContentProps) { +export function BlogDetailContent({ post }: BlogDetailContentProps) { const scrollerRef = useRef(null); const [progress, setProgress] = useState(0); - const [liked, setLiked] = useState(false); - const [likeCount, setLikeCount] = useState(engagement.likes); - const [comments, setComments] = useState(engagement.comments); - const [commentSheetOpen, setCommentSheetOpen] = useState(false); - const [githubAuthed, setGithubAuthed] = useState(false); - const [draft, setDraft] = useState(""); - const [replyTo, setReplyTo] = useState<{ id: string; author: string } | null>(null); - const progressWidth = useMemo(() => `${Math.min(100, Math.max(0, progress))}%`, [progress]); const handleScroll = () => { - const el = scrollerRef.current; - if (!el) return; + const element = scrollerRef.current; + if (!element) return; - const scrollable = el.scrollHeight - el.clientHeight; + const scrollable = element.scrollHeight - element.clientHeight; if (scrollable <= 0) { setProgress(100); return; } - setProgress((el.scrollTop / scrollable) * 100); - }; - - const toggleLike = () => { - setLiked((prev) => { - const next = !prev; - setLikeCount((count) => (next ? count + 1 : Math.max(0, count - 1))); - return next; - }); - }; - - const handleReplyClick = (id: string, author: string) => { - setReplyTo({ id, author }); - setCommentSheetOpen(true); - }; - - const handleSubmitComment = () => { - if (!githubAuthed) return; - const content = draft.trim(); - if (!content) return; - - if (replyTo) { - setComments((prev) => - prev.map((item) => - item.id === replyTo.id - ? { - ...item, - replies: [ - ...item.replies, - { - id: `reply-${Date.now()}`, - author: "Sen (GitHub)", - avatar: "/logo/logo.jpeg", - date: "Az önce", - content, - likes: 0, - }, - ], - } - : item, - ), - ); - setReplyTo(null); - } else { - setComments((prev) => [ - { - id: `comment-${Date.now()}`, - author: "Sen (GitHub)", - avatar: "/logo/logo.jpeg", - date: "Az önce", - content, - likes: 0, - replies: [], - }, - ...prev, - ]); - } - - setDraft(""); + setProgress((element.scrollTop / scrollable) * 100); }; return ( @@ -210,169 +132,6 @@ export function BlogDetailContent({ post, engagement }: BlogDetailContentProps) /> -
- - - - - - - - -
- Yorumlar -
- -
-
- {comments.map((item) => ( - -
- - - - {item.author.slice(0, 2).toUpperCase()} - - -
-
- - {item.author} - - - {item.date} - -
- - {item.content} - -
- - -
- - {item.replies.length > 0 ? ( -
- {item.replies.map((reply) => ( - -
- - - - {reply.author.slice(0, 2).toUpperCase()} - - -
-
- - {reply.author} - - - {reply.date} - -
- - {reply.content} - -
-
-
- ))} -
- ) : null} -
-
-
- ))} -
- - {!githubAuthed ? ( - - - Yorum yapmadan önce GitHub ile giriş yapman gerekiyor. - - - - ) : null} - - {replyTo ? ( - -
- - {replyTo.author} kullanıcısına yanıt yazıyorsun - - -
-
- ) : null} - - -