commerce/app/search/page.tsx

130 lines
5.7 KiB
TypeScript

// app/search/page.tsx
'use client'; // Required for using client-side features like useState
import { useState, useEffect } from 'react';
import { useSearchParams } from 'next/navigation'; // To get query from URL
// Simulate fetching search results
async function getSearchResults(query: string | null) {
// Simulate network delay
await new Promise(resolve => setTimeout(resolve, 50));
if (!query) return [];
const mockResults: { [key: string]: any[] } = {
'shirt': [
{ id: 'sr1', name: 'Search Result Shirt 1', price: { amount: '29.99', currencyCode: 'USD' }, image: { src: '/placeholder-shirt1.jpg', alt: 'Shirt 1' } },
{ id: 'sr2', name: 'Search Result Shirt 2', price: { amount: '35.50', currencyCode: 'USD' }, image: { src: '/placeholder-shirt2.jpg', alt: 'Shirt 2' } },
],
'accessory': [
{ id: 'sa1', name: 'Search Result Accessory', price: { amount: '12.00', currencyCode: 'USD' }, image: { src: '/placeholder-accessory.jpg', alt: 'Accessory' } },
],
'generic': [ // Added a generic list for queries that don't match specific terms
{ id: 'g1', name: 'Generic Product A', price: { amount: '10.00', currencyCode: 'USD' }, image: { src: '/placeholder-generic1.jpg', alt: 'Generic A' } },
{ id: 'g2', name: 'Generic Product B', price: { amount: '15.00', currencyCode: 'USD' }, image: { src: '/placeholder-generic2.jpg', alt: 'Generic B' } },
]
};
return mockResults[query.toLowerCase()] || mockResults['generic']; // Fallback to generic results
}
export default function SearchPage() {
const searchParams = useSearchParams();
const initialQuery = searchParams.get('q');
const [query, setQuery] = useState(initialQuery || '');
const [results, setResults] = useState<any[]>([]);
const [loading, setLoading] = useState(false);
const handleSearch = async (currentQuery: string) => {
if (!currentQuery.trim()) { // Trim query to avoid searching for empty spaces
setResults([]);
return;
}
setLoading(true);
const fetchedResults = await getSearchResults(currentQuery);
setResults(fetchedResults);
setLoading(false);
};
// Perform search when initialQuery (from URL) changes or when component mounts with an initialQuery
useEffect(() => {
if (initialQuery) {
setQuery(initialQuery); // Ensure input field is updated if query comes from URL
handleSearch(initialQuery);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
// Disabled exhaustive-deps because handleSearch reference might change but we only care about initialQuery
}, [initialQuery]);
return (
<div style={{ padding: '20px', fontFamily: 'Arial, sans-serif', maxWidth: '900px', margin: '0 auto' }}>
<h1 style={{ textAlign: 'center', marginBottom: '20px' }}>Search Products</h1>
<form
onSubmit={(e) => {
e.preventDefault();
// Update URL with the new search query
window.history.pushState(null, '', `?q=${encodeURIComponent(query)}`);
handleSearch(query);
}}
style={{ display: 'flex', justifyContent: 'center', marginBottom: '20px' }}
>
<input
type="search"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search for products..."
style={{ padding: '10px', fontSize: '1em', width: '300px', marginRight: '10px' }}
/>
<button type="submit" style={{ padding: '10px 15px', fontSize: '1em' }}>Search</button>
</form>
<p style={{ textAlign: 'center', fontStyle: 'italic', marginBottom: '20px', color: '#555' }}>
Personalization by Relewise will be implemented here.
</p>
{loading && <p style={{ textAlign: 'center' }}>Loading...</p>}
{!loading && results.length > 0 && (
<div>
<h2 style={{ marginBottom: '15px' }}>Results for "{query}"</h2>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(200px, 1fr))', gap: '20px' }}>
{results.map((product) => (
<div key={product.id} style={{ border: '1px solid #ccc', padding: '16px', borderRadius: '5px', textAlign: 'center' }}>
<img src={product.image.src} alt={product.image.alt} style={{ width: '100%', height: '180px', objectFit: 'cover', marginBottom: '10px', borderBottom: '1px solid #eee', paddingBottom: '10px' }} />
<h3 style={{ fontSize: '1.1em', margin: '0 0 10px 0', minHeight: '44px' }}>{product.name}</h3>
<p style={{ fontSize: '1em', fontWeight: 'bold', margin: '0 0 10px 0' }}>
{product.price.amount} {product.price.currencyCode}
</p>
<a
href={`/product/${product.id}`} // Assuming product.id can be a handle
style={{
display: 'inline-block',
padding: '8px 15px',
backgroundColor: '#007bff',
color: 'white',
textDecoration: 'none',
borderRadius: '3px'
}}
>
View Details
</a>
</div>
))}
</div>
</div>
)}
{!loading && results.length === 0 && query && (
<div style={{ textAlign: 'center', marginTop: '30px' }}>
<p>No specific results found for "{query}".</p>
<p style={{ color: '#777' }}>Did you mean: t-shirt, accessory, cap, generic?</p> {/* Placeholder suggestions */}
</div>
)}
{!loading && results.length === 0 && !query && (
<p style={{ textAlign: 'center', marginTop: '30px', color: '#777' }}>
Enter a search term above to find products.
</p>
)}
</div>
);
}