Skip to main content

CategoryContext

Description​

Provides category page data to child components. Used only on category pages to access category information, products, filters, and price ranges.

Import​

import { CategoryProvider, useCategory } from '@components/frontStore/catalog/CategoryContext';

Usage​

Setup Provider​

import { CategoryProvider } from '@components/frontStore/catalog/CategoryContext';

function CategoryPage({ category }) {
return (
<CategoryProvider category={category}>
{/* Category page components */}
</CategoryProvider>
);
}

Access Category Data​

import { useCategory } from '@components/frontStore/catalog/CategoryContext';

function CategoryHeader() {
const category = useCategory();

return (
<div>
<h1>{category.name}</h1>
{category.description && <div>{category.description}</div>}
{category.image && <img src={category.image.url} alt={category.image.alt} />}
</div>
);
}

API​

CategoryProvider Props​

NameTypeRequiredDescription
categoryCategoryDataYesCategory data object
childrenReactNodeYesChild components

useCategory Hook​

Returns the complete CategoryData object. Throws error if used outside CategoryProvider.

CategoryData Interface​

FieldTypeDescription
categoryIdnumberCategory ID
uuidstringCategory UUID
namestringCategory name
descriptionArray<Row>Rich text description
urlstringCategory URL
imageobjectCategory image (url, alt)
showProductsbooleanWhether to display products
productsCategoryProductsProduct listing data
availableAttributesFilterableAttribute[]Filterable attributes
childrenCategoryFilter[]Child categories
priceRangeobjectPrice range (min, max)

CategoryProducts Interface​

interface CategoryProducts {
items: ProductData[]; // Array of products
currentFilters: FilterInput[]; // Active filters
total: number; // Total product count
}

Price Range Object​

interface PriceRange {
min: number; // Minimum price value
minText: string; // Formatted min price
max: number; // Maximum price value
maxText: string; // Formatted max price
}

Examples​

Display Category Info​

import { useCategory } from '@components/frontStore/catalog/CategoryContext';

function CategoryInfo() {
const { name, description, image, products } = useCategory();

return (
<div className="category-info">
{image && (
<img src={image.url} alt={image.alt} className="category-banner" />
)}
<h1>{name}</h1>
{description && <div className="description">{description}</div>}
<p>{products.total} products</p>
</div>
);
}

Product Listing​

import { useCategory } from '@components/frontStore/catalog/CategoryContext';

function ProductList() {
const { products, showProducts } = useCategory();

if (!showProducts) {
return null;
}

return (
<div className="product-grid">
{products.items.map(product => (
<div key={product.productId}>
<h3>{product.name}</h3>
<p>{product.price.text}</p>
</div>
))}
</div>
);
}

Price Filter​

import { useCategory } from '@components/frontStore/catalog/CategoryContext';

function PriceFilter() {
const { priceRange } = useCategory();

return (
<div className="price-filter">
<h3>Price Range</h3>
<p>From {priceRange.minText} to {priceRange.maxText}</p>
<input
type="range"
min={priceRange.min}
max={priceRange.max}
/>
</div>
);
}

Subcategories​

import { useCategory } from '@components/frontStore/catalog/CategoryContext';

function Subcategories() {
const { children } = useCategory();

if (!children || children.length === 0) {
return null;
}

return (
<div className="subcategories">
<h3>Shop by Category</h3>
<ul>
{children.map(child => (
<li key={child.categoryId}>
<a href={child.url}>{child.name}</a>
</li>
))}
</ul>
</div>
);
}

Active Filters Display​

import { useCategory } from '@components/frontStore/catalog/CategoryContext';

function ActiveFilters() {
const { products } = useCategory();

if (products.currentFilters.length === 0) {
return null;
}

return (
<div className="active-filters">
<h4>Active Filters:</h4>
{products.currentFilters.map((filter, index) => (
<span key={index} className="filter-tag">
{filter.key}: {filter.value}
</span>
))}
</div>
);
}

Complete Category Page​

import { CategoryProvider, useCategory } from '@components/frontStore/catalog/CategoryContext';
import { Image } from '@components/common/Image';

function CategoryPageContent() {
const category = useCategory();
const { name, description, image, products, priceRange, children } = category;

return (
<div className="category-page">
{/* Category Header */}
<div className="category-header">
{image && <Image src={image.url} alt={image.alt} width={1200} height={400} />}
<h1>{name}</h1>
{description && <div className="description">{description}</div>}
</div>

{/* Subcategories */}
{children.length > 0 && (
<div className="subcategories">
<h3>Categories</h3>
<div className="category-grid">
{children.map(child => (
<a key={child.categoryId} href={child.url}>
{child.name}
</a>
))}
</div>
</div>
)}

{/* Products Section */}
{category.showProducts && (
<>
<div className="results-bar">
<p>{products.total} products found</p>
{products.currentFilters.length > 0 && (
<div className="active-filters">
{products.currentFilters.map((filter, i) => (
<span key={i}>{filter.key}: {filter.value}</span>
))}
</div>
)}
</div>

<div className="product-listing">
{products.items.map(product => (
<div key={product.productId} className="product-card">
<h3>{product.name}</h3>
<p>{product.price.text}</p>
</div>
))}
</div>
</>
)}
</div>
);
}

export default function CategoryPage({ categoryData }) {
return (
<CategoryProvider category={categoryData}>
<CategoryPageContent />
</CategoryProvider>
);
}

Features​

  • Category Metadata: Name, description, image, URL
  • Product Listing: Filtered products with pagination
  • Filter Support: Current filters and available attributes
  • Price Range: Min/max prices for filtering
  • Subcategories: Child category navigation
  • Extended Fields: Support for custom fields
  • Type Safe: Full TypeScript support
  • Error Handling: Throws error if used outside provider

Usage Notes​

  • Only available on category pages
  • Must wrap components in CategoryProvider
  • The useCategory hook throws error if used outside provider
  • Description is rich text (array of Row objects)
  • Extended fields allow custom category data