import { defineStore } from 'pinia' import axios from 'axios' import { useOPFS } from '../composables/useOPFS' const opfs = useOPFS() const CACHE_KEY_PRODUCTS = 'cached_products.json' export const useProductStore = defineStore('product', { state: () => ({ products: [], currentProduct: null, categories: [], subcategories: [], loading: false, error: null, detailsCache: {} // Cache for full product details keyed by hashkey }), actions: { async fetchProducts(force = false) { if (!force && this.products.length > 0) { return; } this.loading = true this.error = null // Attempt to load from cache first for immediate UI update try { const cachedProducts = await opfs.loadJSON(CACHE_KEY_PRODUCTS) if (cachedProducts && Array.isArray(cachedProducts)) { this.products = cachedProducts } } catch (e) { console.warn('Failed to load products from cache:', e) } try { const response = await axios.post('/Market/Products/List') const newProducts = response.data || [] // Merge or replace this.products = newProducts // Save to cache await opfs.saveJSON(CACHE_KEY_PRODUCTS, this.products) } catch (error) { console.error('Failed to fetch products:', error) this.error = error.message } finally { this.loading = false } }, syncFromSSE(data) { // 1. Full Market List if (data.products_market && data.products_market.length > 0) { console.log('[ProductStore] Syncing full market list from SSE'); this.products = data.products_market; // Optionally cache to OPFS opfs.saveJSON(CACHE_KEY_PRODUCTS, this.products).catch(() => {}); } // 2. Deltas (Inventory/Price/Details) if (data.inventory_deltas && data.inventory_deltas.length > 0) { data.inventory_deltas.forEach(delta => { const index = this.products.findIndex(p => p.hashkey === delta.hashkey); if (index !== -1) { this.products[index] = { ...this.products[index], ...delta }; } else { // New product added this.products.unshift(delta); } // Also update currentProduct if it matches if (this.currentProduct && (this.currentProduct.hashkey === delta.hashkey)) { this.currentProduct = { ...this.currentProduct, ...delta }; } }); } // 3. New detailed product data from SSE (if added) if (data.product_details && typeof data.product_details === 'object') { Object.entries(data.product_details).forEach(([hash, details]) => { this.detailsCache[hash] = details; if (this.currentProduct && this.currentProduct.hashkey === hash) { this.currentProduct = { ...this.currentProduct, ...details }; } }); } }, async fetchProductById(hashkey, storeHash = null) { if (this.detailsCache[hashkey]) { this.currentProduct = this.detailsCache[hashkey]; // return early but still fetch in background if needed (optional) // for now just return it return; } this.loading = true this.error = null try { const response = await axios.post('/View/Product/Details/data', { target: hashkey, data: { store_hash: storeHash } }) if (response.data && response.data.success && response.data.data) { this.currentProduct = response.data.data this.detailsCache[hashkey] = this.currentProduct } } catch (error) { console.error('Failed to fetch product:', error) this.error = error.message } finally { this.loading = false } }, async fetchCategories() { try { const response = await axios.get('/api/categories') this.categories = response.data || [] } catch (error) { console.error('Failed to fetch categories:', error) } }, async fetchSubcategories(categoryId) { try { const response = await axios.get(`/api/subcategories?category_id=${categoryId}`) this.subcategories = response.data || [] } catch (error) { console.error('Failed to fetch subcategories:', error) } }, async createProduct(data) { this.loading = true this.error = null try { const response = await axios.post('/api/products', data) if (response.data && response.data.success) { this.products.push(response.data.product) } return response.data } catch (error) { console.error('Failed to create product:', error) this.error = error.message throw error } finally { this.loading = false } }, async updateProduct(id, data) { this.loading = true this.error = null try { const response = await axios.put(`/api/products/${id}`, data) if (response.data && response.data.success) { const index = this.products.findIndex(p => p.id === id) if (index !== -1) { this.products[index] = response.data.product } } return response.data } catch (error) { console.error('Failed to update product:', error) this.error = error.message throw error } finally { this.loading = false } }, async deleteProduct(id) { this.loading = true this.error = null try { const response = await axios.delete(`/api/products/${id}`) if (response.data && response.data.success) { this.products = this.products.filter(p => p.id !== id) } return response.data } catch (error) { console.error('Failed to delete product:', error) this.error = error.message throw error } finally { this.loading = false } }, async updateProductStatus(productId, status) { try { const response = await axios.post('/api/products/status', { product_id: productId, status: status }) return response.data } catch (error) { console.error('Failed to update product status:', error) throw error } }, resetCurrentProduct() { this.currentProduct = null } } })