initial: bootstrap from BukidBountyApp base
This commit is contained in:
218
resources/js/stores/product.js
Normal file
218
resources/js/stores/product.js
Normal file
@@ -0,0 +1,218 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user