useProductsStore
The useProductsStore Pinia store manages product catalog data including products, categories, and brands. It provides centralized data fetching, localization transformation, initialization management, and utility methods for product-related operations.
Features
- Product catalog management (products, categories, brands)
- Localization transformation based on current language
- Parallel data initialization with error handling
- Thumbnail generation for product media
Usage
import { useProductsStore } from '@/stores/products';
const productsStore = useProductsStore();
// Access reactive state
const { products, categories, brands, ready } = productsStore;
// Initialize store
await productsStore.init();
// Fetch specific data
const products = await productsStore.fetchProducts(['localizations', 'media']);
const categories = await productsStore.fetchCategories();
const brands = await productsStore.fetchBrands();Properties
products
A ref containing the transformed product list.
- Type:
Ref<Product[]> - Default: Empty array
- Features: Localized data, thumbnail URLs included
categories
A ref containing the transformed category list.
- Type:
Ref<Category[]> - Default: Empty array
- Features: Localized names and data
brands
A ref containing the transformed brand list.
- Type:
Ref<Brand[]> - Default: Empty array
- Features: Localized names and data
ready
A ref indicating whether all data has been successfully loaded.
- Type:
Ref<boolean> - Default:
false - Logic:
truewhen all parallel fetches succeed
initialized
A ref tracking whether the store has been initialized.
- Type:
Ref<boolean> - Default:
false - Usage: Prevents duplicate initialization calls
Methods
Data Fetching
fetchProducts
fetchProducts(fields?: ProductFieldsFilter[]): Promise<Product[]>Fetches and transforms products from the API.
- Parameters:
fields: Optional array of fields to include (default:['localizations', 'media', 'prices'])
- Returns: Promise resolving to transformed products array
- Features: Automatic localization and thumbnail generation
fetchCategories
fetchCategories(): Promise<Category[]>Fetches and transforms categories from the API.
- Returns: Promise resolving to localized categories array
fetchBrands
fetchBrands(): Promise<Brand[]>Fetches and transforms brands from the API.
- Returns: Promise resolving to localized brands array
init
init(): Promise<void>Initializes the store by fetching all data in parallel.
- Features:
- Parallel API calls for performance
- Error handling with logging
- Sets
readystate based on success - Prevents duplicate initialization
- Detailed error logging for failed calls
reset
reset(): voidResets all store state to initial values.
- Resets: products, categories, brands arrays and ready state
Utility Methods
getCategoryName
getCategoryName(id: string): stringGets category name by ID.
- Parameters:
id: Category ID to look up
- Returns: Category name or empty string if not found
getBrandName
getBrandName(id: string): stringGets brand name by ID.
- Parameters:
id: Brand ID to look up
- Returns: Brand name or empty string if not found
Transformation Methods
transformProducts
transformProducts(products: Product[]): Product[]Transforms products with localization and thumbnail generation.
- Features:
- Merges localized data for current language
- Adds thumbnail URL from first media item
- Handles missing data gracefully
transformCategories
transformCategories(categories: Category[]): Category[]Transforms categories with localization for current language.
transformBrands
transformBrands(brands: Brand[]): Brand[]Transforms brands with localization for current language.
Example
<script setup lang="ts">
const productsStore = useProductsStore();
const { products, categories, brands, ready } = productsStore;
// Initialize on mount
onMounted(async () => {
await productsStore.init();
if (ready.value) {
console.log(`Loaded ${products.value.length} products`);
}
});
// Get category name for a product
const getProductCategoryName = (product: Product) => {
return productsStore.getCategoryName(product.categoryId);
};
// Get brand name for a product
const getProductBrandName = (product: Product) => {
return productsStore.getBrandName(product.brandId);
};
// Refresh products with specific fields
const refreshProducts = async () => {
await productsStore.fetchProducts([
'localizations',
'media',
'prices',
'stock',
]);
};
</script>
<template>
<div v-if="ready" class="product-catalog">
<div v-for="product in products" :key="product._id" class="product-card">
<img :src="product.thumbnail" :alt="product.name" />
<h3>{{ product.name }}</h3>
<p>Category: {{ getProductCategoryName(product) }}</p>
<p>Brand: {{ getProductBrandName(product) }}</p>
</div>
</div>
<div v-else class="loading">Loading product catalog...</div>
</template>Type Definitions
function useProductsStore(): ProductsStoreReturnType;
interface ProductsStoreReturnType {
products: Ref<Product[]>;
categories: Ref<Category[]>;
brands: Ref<Brand[]>;
ready: Ref<boolean>;
fetchProducts: (fields?: ProductFieldsFilter[]) => Promise<Product[]>;
fetchCategories: () => Promise<Category[]>;
fetchBrands: () => Promise<Brand[]>;
init: () => Promise<void>;
reset: () => void;
getCategoryName: (id: string) => string;
getBrandName: (id: string) => string;
transformProducts: (products: Product[]) => Product[];
}
type ProductFieldsFilter =
| 'localizations'
| 'media'
| 'prices'
| 'stock'
| 'categories'
| 'brands';
interface Product {
_id: string;
name: string;
categoryId: string;
brandId: string;
thumbnail?: string;
localizations?: Record<string, any>;
media?: Media[];
prices?: Price[];
[key: string]: any;
}
interface Category {
_id: string;
name: string;
localizations: Record<string, any>;
[key: string]: any;
}
interface Brand {
_id: string;
name: string;
localizations: Record<string, any>;
[key: string]: any;
}
interface Media {
_id: string;
[key: string]: any;
}Dependencies
This store depends on:
- Pinia: For store management
- useGeinsRepository: To access product API endpoints
- useAccountStore: For current language context
- useGeinsImage: For thumbnail URL generation
- useGeinsLog: For error logging and debugging
- #shared/types: For TypeScript type definitions