259 lines
7.3 KiB
Plaintext
259 lines
7.3 KiB
Plaintext
import { defineStore } from "pinia";
|
|
import ProductService from "@/services/product";
|
|
|
|
export const useProductStore = defineStore("product", {
|
|
state: () => ({
|
|
products: [],
|
|
currentProduct: null,
|
|
loading: false,
|
|
isLoading: false,
|
|
error: null,
|
|
meta: {
|
|
current_page: 1,
|
|
last_page: 1,
|
|
per_page: 15,
|
|
total: 0,
|
|
from: 1,
|
|
to: 0,
|
|
},
|
|
}),
|
|
|
|
getters: {
|
|
lowStockProducts: (state) =>
|
|
state.products.filter((product) => product.is_low_stock),
|
|
expiringProducts: (state) =>
|
|
state.products.filter((product) =>
|
|
product.date_expiration &&
|
|
new Date(product.date_expiration) <= new Date(Date.now() + 30 * 24 * 60 * 60 * 1000)
|
|
),
|
|
categories: (state) => {
|
|
const categorySet = new Set(state.products.map(product => product.categorie).filter(Boolean));
|
|
return Array.from(categorySet).sort();
|
|
},
|
|
totalProducts: (state) => state.meta.total,
|
|
totalValue: (state) =>
|
|
state.products.reduce((total, product) =>
|
|
total + (product.stock_actuel * product.prix_unitaire), 0
|
|
),
|
|
},
|
|
|
|
actions: {
|
|
async fetchProducts(params = {}) {
|
|
this.loading = true;
|
|
this.error = null;
|
|
|
|
try {
|
|
const response = await ProductService.getAllProducts(params);
|
|
|
|
this.products = response.data;
|
|
this.meta = {
|
|
current_page: response.pagination.current_page,
|
|
last_page: response.pagination.last_page,
|
|
per_page: response.pagination.per_page,
|
|
total: response.pagination.total,
|
|
from: response.pagination.from,
|
|
to: response.pagination.to,
|
|
};
|
|
|
|
return response;
|
|
} catch (error: any) {
|
|
this.error = error?.message || "Erreur lors du chargement des produits";
|
|
throw error;
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
},
|
|
|
|
async createProduct(productData: any) {
|
|
this.isLoading = true;
|
|
this.error = null;
|
|
|
|
try {
|
|
const response = await ProductService.createProduct(productData);
|
|
const product = response.data;
|
|
|
|
// Add the new product to the beginning of the list
|
|
this.products.unshift(product);
|
|
this.meta.total += 1;
|
|
|
|
return product;
|
|
} catch (error: any) {
|
|
this.error = error?.message || "Erreur lors de la création du produit";
|
|
throw error;
|
|
} finally {
|
|
this.isLoading = false;
|
|
}
|
|
},
|
|
|
|
async updateProduct(id: number, productData: any) {
|
|
this.isLoading = true;
|
|
this.error = null;
|
|
|
|
try {
|
|
const response = await ProductService.updateProduct(id, productData);
|
|
const updatedProduct = response.data;
|
|
|
|
// Update the product in the list
|
|
const index = this.products.findIndex((p) => p.id === id);
|
|
if (index !== -1) {
|
|
this.products[index] = updatedProduct;
|
|
}
|
|
|
|
// Update current product if it matches
|
|
if (this.currentProduct?.id === id) {
|
|
this.currentProduct = updatedProduct;
|
|
}
|
|
|
|
return updatedProduct;
|
|
} catch (error: any) {
|
|
this.error = error?.message || "Erreur lors de la mise à jour du produit";
|
|
throw error;
|
|
} finally {
|
|
this.isLoading = false;
|
|
}
|
|
},
|
|
|
|
async deleteProduct(id: number) {
|
|
this.isLoading = true;
|
|
this.error = null;
|
|
|
|
try {
|
|
await ProductService.deleteProduct(id);
|
|
|
|
// Remove the product from the list
|
|
this.products = this.products.filter((p) => p.id !== id);
|
|
this.meta.total -= 1;
|
|
|
|
// Clear current product if it was deleted
|
|
if (this.currentProduct?.id === id) {
|
|
this.currentProduct = null;
|
|
}
|
|
|
|
return true;
|
|
} catch (error: any) {
|
|
this.error = error?.message || "Erreur lors de la suppression du produit";
|
|
throw error;
|
|
} finally {
|
|
this.isLoading = false;
|
|
}
|
|
},
|
|
|
|
async fetchProduct(id: number) {
|
|
this.loading = true;
|
|
this.error = null;
|
|
|
|
try {
|
|
const response = await ProductService.getProduct(id);
|
|
this.currentProduct = response.data;
|
|
return response.data;
|
|
} catch (error: any) {
|
|
this.error = error?.message || "Erreur lors du chargement du produit";
|
|
throw error;
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
},
|
|
|
|
async searchProducts(searchTerm: string, exact = false) {
|
|
this.loading = true;
|
|
this.error = null;
|
|
|
|
try {
|
|
const response = await ProductService.searchProducts(searchTerm, exact);
|
|
|
|
// Update current products list with search results
|
|
this.products = response.data;
|
|
|
|
return response.data;
|
|
} catch (error: any) {
|
|
this.error = error?.message || "Erreur lors de la recherche";
|
|
throw error;
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
},
|
|
|
|
async fetchLowStockProducts() {
|
|
this.loading = true;
|
|
this.error = null;
|
|
|
|
try {
|
|
const response = await ProductService.getLowStockProducts();
|
|
return response;
|
|
} catch (error: any) {
|
|
this.error = error?.message || "Erreur lors du chargement des produits à stock faible";
|
|
throw error;
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
},
|
|
|
|
async fetchProductsByCategory(category: string) {
|
|
this.loading = true;
|
|
this.error = null;
|
|
|
|
try {
|
|
const response = await ProductService.getProductsByCategory(category);
|
|
return response;
|
|
} catch (error: any) {
|
|
this.error = error?.message || "Erreur lors du chargement des produits par catégorie";
|
|
throw error;
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
},
|
|
|
|
async getProductStatistics() {
|
|
try {
|
|
const response = await ProductService.getProductStatistics();
|
|
return response.data;
|
|
} catch (error: any) {
|
|
this.error = error?.message || "Erreur lors du chargement des statistiques";
|
|
throw error;
|
|
}
|
|
},
|
|
|
|
async updateStock(productId: number, newStock: number) {
|
|
try {
|
|
const response = await ProductService.updateStock(productId, newStock);
|
|
|
|
// Update the product in the list
|
|
const index = this.products.findIndex((p) => p.id === productId);
|
|
if (index !== -1) {
|
|
this.products[index] = response.data;
|
|
}
|
|
|
|
return response.data;
|
|
} catch (error: any) {
|
|
this.error = error?.message || "Erreur lors de la mise à jour du stock";
|
|
throw error;
|
|
}
|
|
},
|
|
|
|
resetState() {
|
|
this.products = [];
|
|
this.currentProduct = null;
|
|
this.error = null;
|
|
this.loading = false;
|
|
this.isLoading = false;
|
|
},
|
|
|
|
// Local filtering functions
|
|
filterByCategory(category: string) {
|
|
if (!category) return this.products;
|
|
return this.products.filter((product: any) => product.categorie === category);
|
|
},
|
|
|
|
filterByLowStock() {
|
|
return this.products.filter((product: any) => product.is_low_stock);
|
|
},
|
|
|
|
filterByExpiration(days = 30) {
|
|
const cutoffDate = new Date(Date.now() + days * 24 * 60 * 60 * 1000);
|
|
return this.products.filter((product: any) =>
|
|
product.date_expiration &&
|
|
new Date(product.date_expiration) <= cutoffDate
|
|
);
|
|
},
|
|
},
|
|
}); |