Update src/app/collections/[category]/page.tsx

This commit is contained in:
2026-06-10 19:56:37 +00:00
parent e2c09ea896
commit 9f9d28b37a

View File

@@ -1,216 +1,115 @@
"use client"; 'use client';
import { ThemeProvider } from '@/providers/themeProvider/ThemeProvider';
import NavbarStyleCentered from '@/components/navbar/NavbarStyleCentered/NavbarStyleCentered';
import ProductCardTwo from '@/components/sections/product/ProductCardTwo';
import ButtonTextShift from '@/components/button/ButtonTextShift/ButtonTextShift';
import FooterBaseReveal from '@/components/sections/footer/FooterBaseReveal';
import { useState, useMemo } from 'react'; import { usePathname } from 'next/navigation';
import NavbarStyleFullscreen from '@/components/navbar/NavbarStyleFullscreen/NavbarStyleFullscreen';
import ProductCardThree from '@/components/sections/product/ProductCardThree';
import Input from '@/components/form/Input';
import ButtonExpandHover from '@/components/button/ButtonExpandHover';
import { useRouter } from 'next/navigation';
import { ChevronLeft, ChevronRight, Filter, Search, SlidersHorizontal } from 'lucide-react';
// Dummy data for books export default function CollectionPage() {
const allBooks = [ const pathname = usePathname();
{ id: '1', name: 'The Art of Programming', price: '$29.99', imageSrc: '/book-programming.jpg', imageAlt: 'Book cover for The Art of Programming', category: 'technology' }, const category = pathname.split('/').pop()?.replace(/-/g, ' ') || 'All Products';
{ id: '2', name: 'Science Fiction Masterpiece', price: '$19.99', imageSrc: '/book-scifi.jpg', imageAlt: 'Book cover for Science Fiction Masterpiece', category: 'fiction' },
{ id: '3', name: 'A Culinary Journey', price: '$24.99', imageSrc: '/book-cooking.jpg', imageAlt: 'Book cover for A Culinary Journey', category: 'cooking' },
{ id: '4', name: 'History of the World', price: '$35.00', imageSrc: '/book-history.jpg', imageAlt: 'Book cover for History of the World', category: 'history' },
{ id: '5', name: 'Developing Modern Web Apps', price: '$39.99', imageSrc: '/book-webdev.jpg', imageAlt: 'Book cover for Developing Modern Web Apps', category: 'technology' },
{ id: '6', name: 'Fantasy Realms Saga', price: '$22.50', imageSrc: '/book-fantasy.jpg', imageAlt: 'Book cover for Fantasy Realms Saga', category: 'fiction' },
{ id: '7', name: 'Gourmet Baking Guide', price: '$28.00', imageSrc: '/book-baking.jpg', imageAlt: 'Book cover for Gourmet Baking Guide', category: 'cooking' },
{ id: '8', name: 'Ancient Civilizations', price: '$32.00', imageSrc: '/book-ancient.jpg', imageAlt: 'Book cover for Ancient Civilizations', category: 'history' },
{ id: '9', name: 'The Digital Frontier', price: '$31.99', imageSrc: '/book-digital.jpg', imageAlt: 'Book cover for The Digital Frontier', category: 'technology' },
{ id: '10', name: 'Mythical Beasts', price: '$18.75', imageSrc: '/book-myth.jpg', imageAlt: 'Book cover for Mythical Beasts', category: 'fiction' }
];
const ITEMS_PER_PAGE = 6;
export default function BookCollectionPage({ params }: { params: { category: string } }) {
const router = useRouter();
const { category } = params;
const [searchTerm, setSearchTerm] = useState('');
const [sortOrder, setSortOrder] = useState<'asc' | 'desc' | 'none'>('none');
const [currentPage, setCurrentPage] = useState(1);
const navItems = [ const navItems = [
{ name: "Home", id: "/" }, { name: "Home", id: "/" },
{ name: "About", id: "#about" }, { name: "Cart", id: "/cart" },
{ name: "Features", id: "#features" }, { name: "Checkout", id: "/checkout" },
{ name: "Pricing", id: "#pricing" }, { name: "Order Conf", id: "/order-confirmation" },
{ name: "Books", id: "/collections/all" } { name: "Products", id: "/products/1" },
{ name: "Collections", id: "/collections/all" }
]; ];
const filteredAndSortedBooks = useMemo(() => { // Dummy product data for the collection page
let books = allBooks; const products = [
{
// Category filtering id: "prod1", brand: "BrandA", name: "Stylish Shirt", price: "$29.99", rating: 4.5,
if (category !== 'all') { reviewCount: "120", imageSrc: "https://via.placeholder.com/300x400?text=Product+1", imageAlt: "Stylish Shirt"
books = books.filter(book => book.category === category); },
{
id: "prod2", brand: "BrandB", name: "Comfy Jeans", price: "$49.99", rating: 4.2,
reviewCount: "85", imageSrc: "https://via.placeholder.com/300x400?text=Product+2", imageAlt: "Comfy Jeans"
},
{
id: "prod3", brand: "BrandC", name: "Running Shoes", price: "$79.99", rating: 4.8,
reviewCount: "200", imageSrc: "https://via.placeholder.com/300x400?text=Product+3", imageAlt: "Running Shoes"
},
{
id: "prod4", brand: "BrandD", name: "Elegant Dress", price: "$89.99", rating: 4.7,
reviewCount: "150", imageSrc: "https://via.placeholder.com/300x400?text=Product+4", imageAlt: "Elegant Dress"
},
{
id: "prod5", brand: "BrandE", name: "Smart Watch", price: "$199.99", rating: 4.6,
reviewCount: "230", imageSrc: "https://via.placeholder.com/300x400?text=Product+5", imageAlt: "Smart Watch"
} }
];
// Search term filtering
if (searchTerm) {
books = books.filter(book =>
book.name.toLowerCase().includes(searchTerm.toLowerCase())
);
}
// Sorting
if (sortOrder === 'asc') {
books = [...books].sort((a, b) => a.name.localeCompare(b.name));
} else if (sortOrder === 'desc') {
books = [...books].sort((a, b) => b.name.localeCompare(a.name));
}
return books;
}, [category, searchTerm, sortOrder]);
const totalPages = Math.ceil(filteredAndSortedBooks.length / ITEMS_PER_PAGE);
const paginatedBooks = useMemo(() => {
const startIndex = (currentPage - 1) * ITEMS_PER_PAGE;
const endIndex = startIndex + ITEMS_PER_PAGE;
return filteredAndSortedBooks.slice(startIndex, endIndex);
}, [filteredAndSortedBooks, currentPage]);
const handleCategoryChange = (newCategory: string) => {
router.push(`/collections/${newCategory}`);
setCurrentPage(1); // Reset page on category change
};
const handlePageChange = (page: number) => {
if (page >= 1 && page <= totalPages) {
setCurrentPage(page);
}
};
const uniqueCategories = useMemo(() => {
const categories = new Set(allBooks.map(book => book.category));
return ['all', ...Array.from(categories)];
}, []);
return ( return (
<main className="min-h-screen bg-background text-foreground"> <ThemeProvider
<NavbarStyleFullscreen defaultButtonVariant="hover-magnetic"
navItems={navItems} defaultTextAnimation="entrance-slide"
brandName="BookShelf" borderRadius="rounded"
logoSrc="/placeholder-logo.svg" contentWidth="medium"
logoAlt="BookShelf Logo" sizing="medium"
button={{ text: "Sign Up", href: "#" }} background="none"
/> cardStyle="solid"
primaryButtonStyle="gradient"
<div className="container mx-auto p-8"> secondaryButtonStyle="glass"
<h1 className="text-4xl font-bold text-center mb-8 capitalize"> headingFontWeight="bold"
{category === 'all' ? 'All Books' : `${category} Books`} >
</h1> <div id="nav" data-section="nav">
<NavbarStyleCentered navItems={navItems} brandName="Webild" logoSrc="https://via.placeholder.com/40" />
<div className="flex flex-wrap items-center justify-between gap-4 mb-8"> </div>
{/* Category Filter */} <main className="flex min-h-screen flex-col items-center justify-between p-24">
<div className="flex items-center gap-2"> <div id="product-collection" data-section="product-collection">
<Filter className="w-5 h-5" /> <ProductCardTwo
<label htmlFor="category-filter" className="sr-only">Filter by Category</label>
<select
id="category-filter"
value={category}
onChange={(e) => handleCategoryChange(e.target.value)}
className="px-4 py-2 rounded-lg border border-border bg-card text-foreground focus:ring-2 focus:ring-primary-cta focus:outline-none"
>
{uniqueCategories.map(cat => (
<option key={cat} value={cat} className="capitalize">
{cat === 'all' ? 'All Categories' : cat}
</option>
))}
</select>
</div>
{/* Search Input */}
<div className="relative flex-grow max-w-sm">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-foreground/60" />
<Input
value={searchTerm}
onChange={setSearchTerm}
placeholder="Search books..."
className="w-full pl-10 pr-4 py-2 rounded-lg border border-border bg-card text-foreground focus:ring-2 focus:ring-primary-cta focus:outline-none"
ariaLabel="Search books"
/>
</div>
{/* Sort Order */}
<div className="flex items-center gap-2">
<SlidersHorizontal className="w-5 h-5" />
<label htmlFor="sort-order" className="sr-only">Sort Order</label>
<select
id="sort-order"
value={sortOrder}
onChange={(e) => setSortOrder(e.target.value as 'asc' | 'desc' | 'none')}
className="px-4 py-2 rounded-lg border border-border bg-card text-foreground focus:ring-2 focus:ring-primary-cta focus:outline-none"
>
<option value="none">Sort By</option>
<option value="asc">Name (A-Z)</option>
<option value="desc">Name (Z-A)</option>
</select>
</div>
</div>
{paginatedBooks.length > 0 ? (
<ProductCardThree
animationType="slide-up" animationType="slide-up"
gridVariant="three-columns-all-equal-width" gridVariant="three-columns-all-equal-width"
title="" // No title for the section itself, as the page title handles it title={`Collection: ${category}`}
description="" description="Explore our curated selection of products."
products={paginatedBooks.map(book => ({ products={products}
id: book.id, className="my-10"
name: book.name, textboxLayout="default"
price: book.price, useInvertedBackground={false}
imageSrc: book.imageSrc,
imageAlt: book.imageAlt
// Add other necessary product props, e.g., onFavorite, onProductClick
}))}
className="mb-8"
/> />
) : ( <div className="flex justify-center mt-8 space-x-4">
<div className="text-center text-foreground/80 text-xl py-16"> <ButtonTextShift
No books found for this category or search term. text="View More"
onClick={() => alert("Loading more products...")}
disabled={false}
ariaLabel="View more products"
className="px-6 py-3"
textClassName="font-semibold"
/>
<ButtonTextShift
text="Filter"
onClick={() => alert("Opening filter options...")}
disabled={false}
ariaLabel="Filter products"
className="px-6 py-3"
textClassName="font-semibold"
/>
</div> </div>
)} </div>
</main>
{/* Pagination */} <FooterBaseReveal
{totalPages > 1 && ( logoText="Webild"
<div className="flex justify-center items-center gap-4 mt-8"> columns={[
<ButtonExpandHover {
text="" title: "Company", items: [
onClick={() => handlePageChange(currentPage - 1)} { label: "About Us", href: "/" },
disabled={currentPage === 1} { label: "Contact", href: "/" }
ariaLabel="Previous page" ]
className="w-10 h-10 p-0 flex items-center justify-center bg-secondary-cta hover:bg-secondary-cta/80 disabled:opacity-50 disabled:cursor-not-allowed" },
textClassName="sr-only" {
> title: "Legal", items: [
<ChevronLeft className="w-5 h-5" /> { label: "Privacy Policy", href: "/" },
</ButtonExpandHover> { label: "Terms of Service", href: "/" }
{Array.from({ length: totalPages }, (_, i) => i + 1).map(page => ( ]
<button }
key={page} ]}
onClick={() => handlePageChange(page)} copyrightText="© 2023 Webild. All rights reserved."
className={`w-10 h-10 rounded-lg flex items-center justify-center text-lg font-medium />
${currentPage === page </ThemeProvider>
? 'bg-primary-cta text-primary-cta-foreground'
: 'bg-card text-foreground hover:bg-card/80'
}`}
>
{page}
</button>
))}
<ButtonExpandHover
text=""
onClick={() => handlePageChange(currentPage + 1)}
disabled={currentPage === totalPages}
ariaLabel="Next page"
className="w-10 h-10 p-0 flex items-center justify-center bg-secondary-cta hover:bg-secondary-cta/80 disabled:opacity-50 disabled:cursor-not-allowed"
textClassName="sr-only"
>
<ChevronRight className="w-5 h-5" />
</ButtonExpandHover>
</div>
)}
</div>
</main>
); );
} }