The SansiStore product catalog is the primary storefront, available atDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/ProcesosAgilesUMSS/sansistore/llms.txt
Use this file to discover all available pages before exploring further.
/productos. It loads all active products from the products Firestore collection and merges each product’s live inventory data from the inventory collection in a single parallel fetch. Buyers can filter by category, toggle an offers-only view, sort results, run full-text search with history, and navigate directly from a product card to the full detail page at /productos/[slug].
Buyer Journey
Browse the catalog
Visit
/productos. The <FeaturedProducts> component fetches active products via fetchCatalogProducts(), which queries products (where active == true, ordered by createdAt desc) and joins each record with its inventory doc.Filter and sort
Use the
<CategoryFilter> dropdown to narrow by category. Toggle Ofertas to show only discounted items. Use the sort dropdown (Popular · Recientes · A-Z · Z-A) to reorder results. All filter state is reflected in URL query params (?category=, ?offers=true, ?sort=, ?page=).Search
Type in the search bar. Up to five matching product suggestions appear in a live dropdown alongside up to five recent search history entries (stored in
localStorage under sansistore-search-history). Press Enter or click a suggestion to apply the search; matching text is highlighted inline.View product detail
Click any product card to open
/productos/[slug]. The detail page shows the full product image, price (or offer price), stock status, add-to-cart, add-to-favorites, breadcrumb navigation, and a reviews section.The <FeaturedProducts> Component
FeaturedProducts (src/components/FeaturedProducts.tsx) is a client-side React 19 component wrapped in a <CartProvider>. It accepts the following props, all of which can be seeded from Astro’s URL search-params at the page level:
/productos Astro page seeds these props from Astro.url.searchParams:
| Value | Label |
|---|---|
best-sellers | Popular |
recent | Recientes |
name-asc | A-Z |
name-desc | Z-A |
Category Filtering
<CategoryFilter> (src/components/CategoryFilter.tsx) is a self-contained dropdown that queries the categories Firestore collection ordered by name asc and filters out any category where active === false. Selecting a category sets the ?category=<id> URL param and notifies the parent via onCategoryChange.
The catalog validates the
?category= param on mount by checking whether the Firestore document exists and has active !== false. Invalid category IDs are silently removed from the URL.Product Cards
Each<ProductCard> (src/features/catalog/components/ProductCard.tsx) renders one product from the merged catalog + inventory result. The card shows:
Name & Price
Product name (up to two lines, truncated), current price formatted as
Bs X.XX. When hasOffer is true, the offer price is shown prominently and the original price appears with a strikethrough.Badges
Offer/discount badges appear in red (
bg-red-600). Custom badge text appears in the brand primary color. A separate Popular amber badge is applied when soldCount meets the popularity threshold from isPopularProduct().Stock Status
Effective stock =
stockAvailable − stockReserved. When effectiveStock <= 0, an Agotado badge overlays the image and the add-to-cart button is disabled. When enabled === false on the inventory doc, a No disponible badge is shown instead.Favorite Toggle
The
<FavoriteButton> sits in the top-right corner of the image. It reads state from useFavorites() and calls toggleFavorite(productId) on click, updating both localStorage and Firestore for authenticated users./productos/[slug] via an invisible full-card <a> overlay.
Product Detail Page (/productos/[slug])
The detail page is powered by the <ProductDetail> component (src/components/ProductDetail/index.tsx), which wraps a <CartProvider> around <ProductDetailInner>.
Sub-components
| Component | Responsibility |
|---|---|
BreadcrumbNav | Renders an aria-label="Ruta de navegación" nav with links to Inicio → Productos → Detalle |
ProductImageSection | Displays the full product image with fallback to /product-placeholder.svg |
ProductInfoSection | Name, description, price / offer price, stock count, add-to-cart button, add-to-favorites button |
ReviewSection | Loads and displays all reviews; shows the ReviewForm for authenticated users |
ReviewCard | Single review with star rating, comment text, reviewer name, and date |
StockAlertButton | Rendered when effectiveStock === 0; lets buyers register a stock-back alert |
Offer Price Display
WhenhasOffer is true and offerPrice is a positive number, the detail page shows:
Stock States
- In Stock
- Out of Stock
The Agregar al carrito button is enabled. The stock count is shown as
Stock: N disponibles.Reviews
Authenticated buyers can post a star rating (1–5) and a comment viaReviewForm. All reviews are shown in ReviewSection with an aggregate average score. A product with no reviews displays Sin calificaciones and the message Este producto aún no tiene comentarios.
Reviews are stored in the top-level
reviews Firestore collection, not as a subcollection of the product document. Each review document contains a productId field that links it to the corresponding product. The detail page shows 4.5 de 5 aggregate score and individual half-star indicators for each review.Firestore Data Model
products collection
| Field | Type | Description |
|---|---|---|
id | string | Firestore document ID |
slug | string | URL-safe identifier used in /productos/[slug] |
name | string | Display name |
description | string | Full product description |
price | number | Base price in Bolivianos |
imageUrl | string? | Product image URL; falls back to /product-placeholder.svg |
active | boolean | Only active === true products appear in the catalog |
hasOffer | boolean | Whether a discounted offer price is active |
offerPrice | number? | Discounted price shown when hasOffer is true |
badge | string? | Custom badge label (e.g. “Nuevo”) |
soldCount | number | Total units sold; used for “Popular” ranking |
categoryId | string? | Reference to the categories collection |
createdAt | Timestamp | Used for recent sort order |
inventory collection
| Field | Type | Description |
|---|---|---|
productId | string | Matches the products document ID |
stockAvailable | number | Current available stock |
stockReserved | number | Units reserved by pending orders |
stockTotal | number | Total stock count |
enabled | boolean | false marks the product as unavailable regardless of stock |
End-to-End Tests
The catalog is covered by Playwright tests intests/products/: