switched to approuter

This commit is contained in:
2025-08-18 13:10:47 -05:00
parent c2b0d905e1
commit 6cd941295c
82 changed files with 5154 additions and 9772 deletions
+77
View File
@@ -0,0 +1,77 @@
'use client';
import React, { useState, useEffect } from 'react';
import { useSearchParams } from 'next/navigation';
import PostCard from '@/components/PostCard';
import SearchBar from '@/components/SearchBar';
import { PostMetadata } from '@/types';
interface SearchClientProps {
allPosts: PostMetadata[];
}
export default function SearchClient({ allPosts }: SearchClientProps) {
const searchParams = useSearchParams();
const query = searchParams.get('q') || '';
const [searchResults, setSearchResults] = useState<PostMetadata[]>([]);
useEffect(() => {
if (!query.trim()) {
setSearchResults([]);
return;
}
const searchTerms = query.toLowerCase().trim().split(/\s+/);
const filteredPosts = allPosts.filter(post => {
const titleMatch = searchTerms.some(term =>
post.title.toLowerCase().includes(term)
);
const excerptMatch = searchTerms.some(term =>
post.excerpt.toLowerCase().includes(term)
);
const tagMatch = post.tags.some(tag =>
searchTerms.some(term => tag.toLowerCase().includes(term))
);
return titleMatch || excerptMatch || tagMatch;
});
setSearchResults(filteredPosts);
}, [query, allPosts]);
return (
<>
<div className="mb-8">
<SearchBar />
</div>
{query.trim() ? (
<>
<p className="mb-8 text-primary-600">
{searchResults.length} {searchResults.length === 1 ? 'result' : 'results'} for "{query}"
</p>
{searchResults.length > 0 ? (
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{searchResults.map(post => (
<PostCard key={post.id} post={post} />
))}
</div>
) : (
<div className="bg-white rounded-lg shadow-sm p-8 border border-primary-200 text-center">
<p className="text-xl text-primary-600 mb-4">No results found for "{query}"</p>
<p className="text-primary-500">Try using different keywords or browse all posts.</p>
</div>
)}
</>
) : (
<div className="bg-white rounded-lg shadow-sm p-8 border border-primary-200">
<p className="text-xl text-primary-600 mb-4 text-center">Enter a search term to find posts</p>
</div>
)}
</>
);
}
+30
View File
@@ -0,0 +1,30 @@
import React from 'react';
import { getSortedPostsData } from '@/lib/markdown';
import { PostMetadata } from '@/types';
import { generateMetadata as createMetadata } from '@/components/Metadata';
import type { Metadata } from 'next';
import SearchClient from './SearchClient';
export async function generateMetadata(): Promise<Metadata> {
return createMetadata({
title: 'Search Posts',
description: 'Search through all posts on Confessions of Grace by title, content, or tags.',
url: 'https://confessionsofgrace.com/search',
type: 'website'
});
}
async function getAllPosts(): Promise<PostMetadata[]> {
return getSortedPostsData();
}
export default async function SearchPage() {
const allPosts = await getAllPosts();
return (
<div className="max-w-4xl mx-auto">
<h1 className="text-3xl md:text-4xl font-bold mb-6">Search Results</h1>
<SearchClient allPosts={allPosts} />
</div>
);
}