auto-claude: subtask-1-4 - Add URL state management using searchParams and router.push

This commit is contained in:
2026-01-25 04:03:05 +01:00
parent d130972cd7
commit b89031576d
2 changed files with 37 additions and 5 deletions
+9 -1
View File
@@ -7,6 +7,7 @@ import { BlogList } from '@/components/blog/BlogList';
type Props = { type Props = {
params: Promise<{ locale: string }>; params: Promise<{ locale: string }>;
searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
}; };
// Legacy blog posts with translations (these have manual translations) // Legacy blog posts with translations (these have manual translations)
@@ -304,8 +305,9 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {
} }
export default async function BlogPage({ params }: Props) { export default async function BlogPage({ params, searchParams }: Props) {
const { locale } = await params; const { locale } = await params;
const resolvedSearchParams = await searchParams;
setRequestLocale(locale); setRequestLocale(locale);
const t = await getTranslations('blog'); const t = await getTranslations('blog');
@@ -323,6 +325,10 @@ export default async function BlogPage({ params }: Props) {
...legacyPosts, ...legacyPosts,
].sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()); ].sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
// Extract search and category from URL params
const initialSearch = typeof resolvedSearchParams.search === 'string' ? resolvedSearchParams.search : '';
const initialCategory = typeof resolvedSearchParams.category === 'string' ? resolvedSearchParams.category : null;
return ( return (
<main className="min-h-screen"> <main className="min-h-screen">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16 sm:py-20 lg:py-24"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16 sm:py-20 lg:py-24">
@@ -344,6 +350,8 @@ export default async function BlogPage({ params }: Props) {
<BlogList <BlogList
posts={allPosts} posts={allPosts}
locale={locale} locale={locale}
initialSearch={initialSearch}
initialCategory={initialCategory}
translations={{ translations={{
searchPlaceholder: t('ui.search.placeholder'), searchPlaceholder: t('ui.search.placeholder'),
showingText: (start: number, end: number, total: number) => showingText: (start: number, end: number, total: number) =>
+28 -4
View File
@@ -1,9 +1,10 @@
'use client'; 'use client';
import { useState, useMemo } from 'react'; import { useState, useMemo, useEffect } from 'react';
import { Calendar, Tag, ExternalLink, ChevronLeft, ChevronRight } from 'lucide-react'; import { Calendar, Tag, ExternalLink, ChevronLeft, ChevronRight } from 'lucide-react';
import Link from 'next/link'; import Link from 'next/link';
import Image from 'next/image'; import Image from 'next/image';
import { useRouter, usePathname } from 'next/navigation';
import { BlogPost } from '@/lib/blog'; import { BlogPost } from '@/lib/blog';
import { SearchBar } from './SearchBar'; import { SearchBar } from './SearchBar';
import { CategoryFilter } from './CategoryFilter'; import { CategoryFilter } from './CategoryFilter';
@@ -281,6 +282,8 @@ function Pagination({
interface BlogListProps { interface BlogListProps {
posts: BlogPost[]; posts: BlogPost[];
locale: string; locale: string;
initialSearch?: string;
initialCategory?: string | null;
translations: { translations: {
searchPlaceholder: string; searchPlaceholder: string;
showingText: (start: number, end: number, total: number) => string; showingText: (start: number, end: number, total: number) => string;
@@ -290,11 +293,32 @@ interface BlogListProps {
}; };
} }
export function BlogList({ posts, locale, translations }: BlogListProps) { export function BlogList({ posts, locale, initialSearch = '', initialCategory = null, translations }: BlogListProps) {
const [searchQuery, setSearchQuery] = useState(''); const router = useRouter();
const [selectedCategory, setSelectedCategory] = useState<string | null>(null); const pathname = usePathname();
const [searchQuery, setSearchQuery] = useState(initialSearch);
const [selectedCategory, setSelectedCategory] = useState<string | null>(initialCategory);
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
// Update URL when filters change
useEffect(() => {
const params = new URLSearchParams();
if (searchQuery.trim()) {
params.set('search', searchQuery.trim());
}
if (selectedCategory) {
params.set('category', selectedCategory);
}
const queryString = params.toString();
const newUrl = queryString ? `${pathname}?${queryString}` : pathname;
router.push(newUrl, { scroll: false });
}, [searchQuery, selectedCategory, pathname, router]);
// Extract unique categories from all posts // Extract unique categories from all posts
const allCategories = useMemo(() => { const allCategories = useMemo(() => {
const categories = new Set(posts.map(post => post.category).filter(Boolean)); const categories = new Set(posts.map(post => post.category).filter(Boolean));