fix: fixed category filtering problem
This commit is contained in:
+7
-3
@@ -2,14 +2,18 @@ import { BlogContent } from "@/components/blog-content";
|
||||
import { getBlogPageData } from "@/data/blog";
|
||||
|
||||
type BlogPageProps = {
|
||||
searchParams?: Promise<{ page?: string }>;
|
||||
searchParams?: Promise<{ page?: string | string[]; category?: string | string[] }>;
|
||||
};
|
||||
|
||||
export default async function BlogPage({ searchParams }: BlogPageProps) {
|
||||
const resolved = searchParams ? await searchParams : undefined;
|
||||
const page = Number(resolved?.page ?? "1");
|
||||
const pageParam = Array.isArray(resolved?.page) ? resolved?.page[0] : resolved?.page;
|
||||
const categoryParam = Array.isArray(resolved?.category)
|
||||
? resolved?.category[0]
|
||||
: resolved?.category;
|
||||
const page = Number(pageParam ?? "1");
|
||||
const currentPage = Number.isFinite(page) && page > 0 ? Math.floor(page) : 1;
|
||||
const data = await getBlogPageData(currentPage, 12);
|
||||
const data = await getBlogPageData(currentPage, 12, categoryParam);
|
||||
|
||||
return <BlogContent data={data} />;
|
||||
}
|
||||
|
||||
+42
-14
@@ -16,8 +16,30 @@ type BlogContentProps = {
|
||||
data: BlogPageData;
|
||||
};
|
||||
|
||||
function pageHref(page: number) {
|
||||
return page <= 1 ? "/blog" : `/blog?page=${page}`;
|
||||
function pageHref(page: number, category: string) {
|
||||
const params = new URLSearchParams();
|
||||
|
||||
if (page > 1) {
|
||||
params.set("page", String(page));
|
||||
}
|
||||
|
||||
if (category !== "All") {
|
||||
params.set("category", category);
|
||||
}
|
||||
|
||||
const query = params.toString();
|
||||
return query ? `/blog?${query}` : "/blog";
|
||||
}
|
||||
|
||||
function categoryHref(category: string) {
|
||||
if (category === "All") {
|
||||
return "/blog";
|
||||
}
|
||||
|
||||
const params = new URLSearchParams();
|
||||
params.set("category", category);
|
||||
|
||||
return `/blog?${params.toString()}`;
|
||||
}
|
||||
|
||||
export function BlogContent({ data }: BlogContentProps) {
|
||||
@@ -45,14 +67,15 @@ export function BlogContent({ data }: BlogContentProps) {
|
||||
<Card className="rounded-sm border-border p-4">
|
||||
<Typography variant="large">Kategoriler</Typography>
|
||||
<div className="mt-3 flex flex-wrap gap-2">
|
||||
{data.categories.map((category, index) => (
|
||||
<Badge
|
||||
key={category}
|
||||
variant={index === 0 ? "default" : "outline"}
|
||||
className="rounded-sm"
|
||||
>
|
||||
{category}
|
||||
</Badge>
|
||||
{data.categories.map((category) => (
|
||||
<Link key={category} href={categoryHref(category)}>
|
||||
<Badge
|
||||
variant={category === data.selectedCategory ? "default" : "outline"}
|
||||
className="cursor-pointer rounded-sm"
|
||||
>
|
||||
{category}
|
||||
</Badge>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
@@ -114,7 +137,9 @@ export function BlogContent({ data }: BlogContentProps) {
|
||||
) : (
|
||||
<Card className="rounded-sm border-border p-5">
|
||||
<Typography variant="p" className="text-muted-foreground">
|
||||
Henüz blog yazısı bulunmuyor.
|
||||
{data.selectedCategory === "All"
|
||||
? "Henüz blog yazısı bulunmuyor."
|
||||
: `"${data.selectedCategory}" kategorisinde henüz blog yazısı bulunmuyor.`}
|
||||
</Typography>
|
||||
</Card>
|
||||
)}
|
||||
@@ -123,14 +148,17 @@ export function BlogContent({ data }: BlogContentProps) {
|
||||
<PaginationContent className="justify-start">
|
||||
<PaginationItem>
|
||||
<PaginationPrevious
|
||||
href={pageHref(Math.max(1, data.currentPage - 1))}
|
||||
href={pageHref(Math.max(1, data.currentPage - 1), data.selectedCategory)}
|
||||
aria-disabled={data.currentPage <= 1}
|
||||
/>
|
||||
</PaginationItem>
|
||||
|
||||
{pageNumbers.map((page) => (
|
||||
<PaginationItem key={page}>
|
||||
<PaginationLink href={pageHref(page)} isActive={page === data.currentPage}>
|
||||
<PaginationLink
|
||||
href={pageHref(page, data.selectedCategory)}
|
||||
isActive={page === data.currentPage}
|
||||
>
|
||||
{page}
|
||||
</PaginationLink>
|
||||
</PaginationItem>
|
||||
@@ -138,7 +166,7 @@ export function BlogContent({ data }: BlogContentProps) {
|
||||
|
||||
<PaginationItem>
|
||||
<PaginationNext
|
||||
href={pageHref(Math.min(data.totalPages, data.currentPage + 1))}
|
||||
href={pageHref(Math.min(data.totalPages, data.currentPage + 1), data.selectedCategory)}
|
||||
aria-disabled={data.currentPage >= data.totalPages}
|
||||
/>
|
||||
</PaginationItem>
|
||||
|
||||
@@ -4,7 +4,7 @@ category: "Yazilim"
|
||||
date: "2026-02-01"
|
||||
readTime: "8 min read"
|
||||
author: "Poyraz Avsever"
|
||||
excerpt: "Bu yazida temel kavramlari, pratik ornekleri ve uygulayabileceginiz ipuclarini sade bir dille bulabilirsiniz."
|
||||
excerpt: "Yazılım geliştirme sürecinde yalnızca kod yazmıyoruz; aynı zamanda takım iletişimini ve proje geçmişini...."
|
||||
coverImage: "https://miro.medium.com/v2/resize:fit:1400/format:webp/1*WQOgajPE2m4aYuVC3SZoFQ.jpeg"
|
||||
---
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ category: "Testing"
|
||||
date: "2026-02-22"
|
||||
readTime: "9 min read"
|
||||
author: "Poyraz Avsever"
|
||||
excerpt: "Bu yazida temel kavramlari, pratik ornekleri ve uygulayabileceginiz ipuclarini sade bir dille bulabilirsiniz."
|
||||
excerpt: "Frontend tarafında kaliteyi korumanın en sağlam yolu testtir. Bu yazıda, farklı amaçlara hizmet eden..."
|
||||
coverImage: "https://miro.medium.com/v2/resize:fit:1400/format:webp/0*uNpkjRqVlaB2WbDl.png"
|
||||
---
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ category: "TypeScript"
|
||||
date: "2026-02-18"
|
||||
readTime: "8 min read"
|
||||
author: "Poyraz Avsever"
|
||||
excerpt: "Bu yazida temel kavramlari, pratik ornekleri ve uygulayabileceginiz ipuclarini sade bir dille bulabilirsiniz."
|
||||
excerpt: "JavaScript'ten TypeScript'e geçiş, özellikle React projelerinde kod kalitesini gözle görülür şekilde artırıyor..."
|
||||
coverImage: "https://miro.medium.com/v2/resize:fit:1400/format:webp/0*yRK5eL_pqabAhrn7"
|
||||
---
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ category: "UX"
|
||||
date: "2026-02-05"
|
||||
readTime: "6 min read"
|
||||
author: "Poyraz Avsever"
|
||||
excerpt: "Bu yazida temel kavramlari, pratik ornekleri ve uygulayabileceginiz ipuclarini sade bir dille bulabilirsiniz."
|
||||
excerpt: "Tasarım dünyasında, ürünlerimizin kullanıcılarımızın ihtiyaçlarını en iyi şekilde karşılamasını istemek..."
|
||||
coverImage: "https://miro.medium.com/v2/resize:fit:1400/format:webp/0*BEVhh2Et54wytkaA.jpg"
|
||||
---
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ category: "Frontend"
|
||||
date: "2026-02-14"
|
||||
readTime: "11 min read"
|
||||
author: "Poyraz Avsever"
|
||||
excerpt: "Bu yazida temel kavramlari, pratik ornekleri ve uygulayabileceginiz ipuclarini sade bir dille bulabilirsiniz."
|
||||
excerpt: "Frontend dünyasında React, Vue ve Angular gibi güçlü seçenekler var. Son yıllarda bu listeye güçlü bir alternatif..."
|
||||
coverImage: "https://miro.medium.com/v2/resize:fit:1400/format:webp/0*Dx04pr9plejiCcWI.png"
|
||||
---
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ category: "Frontend"
|
||||
date: "2026-02-10"
|
||||
readTime: "10 min read"
|
||||
author: "Poyraz Avsever"
|
||||
excerpt: "Bu yazida temel kavramlari, pratik ornekleri ve uygulayabileceginiz ipuclarini sade bir dille bulabilirsiniz."
|
||||
excerpt: "Tailwind CSS, son dönemde front-end geliştiriciler arasında çok popüler hale geldi. Klasik CSS..."
|
||||
coverImage: "/news/performance.svg"
|
||||
---
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ category: "UX"
|
||||
date: "2026-02-26"
|
||||
readTime: "12 min read"
|
||||
author: "Poyraz Avsever"
|
||||
excerpt: "Bu yazida temel kavramlari, pratik ornekleri ve uygulayabileceginiz ipuclarini sade bir dille bulabilirsiniz."
|
||||
excerpt: "UX (Kullanıcı Deneyimi) tasarımı, teknolojiyle etkileşime geçen herkesin deneyimini iyileştirmeye..."
|
||||
coverImage: "https://miro.medium.com/v2/resize:fit:1400/format:webp/0*5OUFz00g3w5ee2lV.jpg"
|
||||
---
|
||||
|
||||
|
||||
+26
-7
@@ -44,6 +44,7 @@ export type BlogPageData = {
|
||||
news: BlogNewsItem[];
|
||||
articles: BlogArticleItem[];
|
||||
categories: string[];
|
||||
selectedCategory: string;
|
||||
podcastGroups: BlogPodcastGroup[];
|
||||
totalPages: number;
|
||||
currentPage: number;
|
||||
@@ -74,6 +75,10 @@ function sortByDateDesc<T extends { date: string; id: string }>(items: T[]) {
|
||||
});
|
||||
}
|
||||
|
||||
function normalizeCategory(value: string) {
|
||||
return value.trim().toLocaleLowerCase();
|
||||
}
|
||||
|
||||
function mapEpisodeToPodcastItem(episode: PodcastEpisode): BlogPodcastItem {
|
||||
return {
|
||||
id: `${episode.podcast}-${episode.slug}`,
|
||||
@@ -115,13 +120,12 @@ export async function getHomeBlogNews(limit = 3): Promise<BlogNewsItem[]> {
|
||||
}));
|
||||
}
|
||||
|
||||
export async function getBlogPageData(page = 1, pageSize = 12): Promise<BlogPageData> {
|
||||
export async function getBlogPageData(
|
||||
page = 1,
|
||||
pageSize = 12,
|
||||
selectedCategoryParam?: string,
|
||||
): Promise<BlogPageData> {
|
||||
const articles = await getAllBlogArticles();
|
||||
const totalPages = Math.max(1, Math.ceil(Math.max(articles.length, 1) / pageSize));
|
||||
const currentPage = Math.min(Math.max(1, page), totalPages);
|
||||
const start = (currentPage - 1) * pageSize;
|
||||
const paginated = articles.slice(start, start + pageSize);
|
||||
|
||||
const categories = [
|
||||
"All",
|
||||
...new Set(
|
||||
@@ -130,11 +134,25 @@ export async function getBlogPageData(page = 1, pageSize = 12): Promise<BlogPage
|
||||
.filter(Boolean),
|
||||
),
|
||||
];
|
||||
const categoryByNormalized = new Map(
|
||||
categories.map((category) => [normalizeCategory(category), category]),
|
||||
);
|
||||
const requestedCategory = selectedCategoryParam?.trim();
|
||||
const selectedCategory =
|
||||
(requestedCategory && categoryByNormalized.get(normalizeCategory(requestedCategory))) || "All";
|
||||
const filteredArticles =
|
||||
selectedCategory === "All"
|
||||
? articles
|
||||
: articles.filter((item) => normalizeCategory(item.category) === normalizeCategory(selectedCategory));
|
||||
const totalPages = Math.max(1, Math.ceil(Math.max(filteredArticles.length, 1) / pageSize));
|
||||
const currentPage = Math.min(Math.max(1, page), totalPages);
|
||||
const start = (currentPage - 1) * pageSize;
|
||||
const paginated = filteredArticles.slice(start, start + pageSize);
|
||||
|
||||
const podcastCollections = await getPodcastCollections();
|
||||
|
||||
return {
|
||||
news: articles.slice(0, 4).map((item) => ({
|
||||
news: filteredArticles.slice(0, 4).map((item) => ({
|
||||
id: `blog-news-${item.slug}`,
|
||||
title: item.title,
|
||||
category: item.category,
|
||||
@@ -144,6 +162,7 @@ export async function getBlogPageData(page = 1, pageSize = 12): Promise<BlogPage
|
||||
})),
|
||||
articles: paginated,
|
||||
categories,
|
||||
selectedCategory,
|
||||
totalPages,
|
||||
currentPage,
|
||||
podcastGroups: [
|
||||
|
||||
Reference in New Issue
Block a user