ecom / client /src /pages /search-results.tsx
shashwatIDR's picture
Upload 147 files
b89a86e verified
import { useState, useEffect } from "react";
import { useLocation } from "wouter";
import { useQuery } from "@tanstack/react-query";
import { productsApi, categoriesApi } from "@/lib/api";
import Header from "@/components/layout/header";
import ProductCard from "@/components/product/product-card";
import { Button } from "@/components/ui/button";
import { Skeleton } from "@/components/ui/skeleton";
import { ArrowLeft } from "lucide-react";
import { LoadingSpinner } from "@/components/ui/spinner";
export default function SearchResults() {
const [, setLocation] = useLocation();
const [searchQuery, setSearchQuery] = useState("");
const [selectedCategory, setSelectedCategory] = useState<string>("");
// Get search parameters from URL
useEffect(() => {
const urlParams = new URLSearchParams(window.location.search);
const query = urlParams.get('q') || '';
const category = urlParams.get('category') || '';
setSearchQuery(query);
setSelectedCategory(category);
}, []);
// Update URL when search parameters change
useEffect(() => {
const params = new URLSearchParams();
if (searchQuery) params.set('q', searchQuery);
if (selectedCategory) params.set('category', selectedCategory);
const newUrl = `/search${params.toString() ? '?' + params.toString() : ''}`;
window.history.replaceState({}, '', newUrl);
}, [searchQuery, selectedCategory]);
const { data: categories = [], isLoading: categoriesLoading } = useQuery({
queryKey: ['/api/categories'],
queryFn: () => categoriesApi.getAll(),
});
const { data: searchResults = [], isLoading: searchLoading } = useQuery({
queryKey: ['/api/products', { search: searchQuery, category: selectedCategory }],
queryFn: () => productsApi.getAll({
...(searchQuery && { search: searchQuery }),
...(selectedCategory && { category: selectedCategory })
}),
enabled: !!(searchQuery || selectedCategory),
});
const getPageTitle = () => {
if (searchQuery && selectedCategory) {
const categoryName = categories.find((c: any) => c.id === selectedCategory)?.name || 'Category';
return `"${searchQuery}" in ${categoryName}`;
} else if (searchQuery) {
return `"${searchQuery}"`;
} else if (selectedCategory) {
const categoryName = categories.find((c: any) => c.id === selectedCategory)?.name || 'Category';
return categoryName;
}
return 'Search Results';
};
return (
<div className="min-h-screen page-gradient">
<Header searchQuery={searchQuery} setSearchQuery={setSearchQuery} />
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8" data-testid="search-results-page">
{/* Back Navigation */}
<Button
variant="ghost"
onClick={() => setLocation('/')}
className="mb-6"
data-testid="back-to-home"
>
<ArrowLeft className="mr-2 h-4 w-4" />
Back to Home
</Button>
{/* Search Header */}
<div className="mb-8">
<h1 className="text-3xl font-bold text-gray-900 mb-2" data-testid="search-title">
Search Results for {getPageTitle()}
</h1>
{!searchLoading && (
<p className="text-gray-600" data-testid="results-count">
{searchResults.length} {searchResults.length === 1 ? 'product' : 'products'} found
</p>
)}
</div>
{/* Search Results */}
<section data-testid="search-results-section">
{searchLoading ? (
<div className="flex flex-col items-center">
<LoadingSpinner text="Searching products..." />
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6 mt-6 w-full">
{[...Array(8)].map((_, i) => (
<div key={i} className="glass-card rounded-2xl p-4">
<Skeleton className="aspect-square w-full mb-4 rounded-xl" />
<Skeleton className="h-4 w-3/4 mb-2" />
<Skeleton className="h-4 w-1/2 mb-2" />
<Skeleton className="h-6 w-1/4" />
</div>
))}
</div>
</div>
) : searchResults.length > 0 ? (
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4 sm:gap-5 md:gap-6" data-testid="search-product-grid">
{searchResults.map((product: any) => (
<ProductCard key={product.id} product={product} />
))}
</div>
) : (searchQuery || selectedCategory) ? (
<div className="text-center py-12" data-testid="no-results">
<h3 className="text-xl font-semibold text-gray-900 mb-2">No products found</h3>
<p className="text-gray-600 mb-6">
Try adjusting your search terms or browse all products
</p>
<Button
onClick={() => {
setSearchQuery('');
setSelectedCategory('');
setLocation('/');
}}
data-testid="browse-all-products"
>
Browse All Products
</Button>
</div>
) : (
<div className="text-center py-12" data-testid="search-prompt">
<h3 className="text-xl font-semibold text-gray-900 mb-2">Search for products</h3>
<p className="text-gray-600">
Use the search bar above or select a category to find products
</p>
</div>
)}
</section>
</div>
</div>
);
}