feat: Add cart store for catalog quantity sync

- Create Pinia cart store to manage cart state globally
- Sync quantity changes between catalog cards and cart sidebar
- Improve product card design with borders and hover effects
- Fix cart sync when updating quantity via minus button or input field
This commit is contained in:
2026-03-14 16:59:45 -05:00
parent 1d37ce42dc
commit 78923ddb6e
3 changed files with 93 additions and 57 deletions

View File

@@ -186,17 +186,17 @@
clients: [], clients: [],
products: [], products: [],
}; };
}, },
created() { created() {
this.fetchClients(); this.fetchClients();
this.fetchProducts(); this.fetchProducts();
this.fetchPaymentMethods(); this.fetchPaymentMethods();
},
watch: {
group () {
this.drawer = false
}, },
}, watch: {
group () {
this.drawer = false
},
},
beforeMount() { beforeMount() {
window.addEventListener('beforeunload', this.confirmLeave); window.addEventListener('beforeunload', this.confirmLeave);
}, },
@@ -228,8 +228,8 @@
}); });
}, },
}, },
methods: { methods: {
openModal() { openModal() {
this.$refs.customerModal.openModal(); this.$refs.customerModal.openModal();
}, },
onFormChange() { onFormChange() {
@@ -307,25 +307,25 @@
calculateSubtotal(line) { calculateSubtotal(line) {
return line.unit_price * line.quantity; return line.unit_price * line.quantity;
}, },
async submit() { async submit() {
this.$refs.purchase.validate(); this.$refs.purchase.validate();
if (this.valid) { if (this.valid) {
this.api.createPurchase(this.purchase) this.api.createPurchase(this.purchase)
.then(data => { .then(data => {
console.log('Compra enviada:', data); console.log('Compra enviada:', data);
this.$router.push({ this.$router.push({
path: "/summary_purchase", path: "/summary_purchase",
query : {id: parseInt(data.id)} query : {id: parseInt(data.id)}
}); });
}) })
.catch(error => console.error('Error al enviarl la compra:', error)); .catch(error => console.error('Error al enviarl la compra:', error));
} else { } else {
this.show_alert_purchase = true; this.show_alert_purchase = true;
setTimeout(() => { setTimeout(() => {
this.show_alert_purchase = false; this.show_alert_purchase = false;
}, 4000); }, 4000);
} }
}, },
navigate(route) { navigate(route) {
this.$router.push(route); this.$router.push(route);
}, },

View File

@@ -35,21 +35,32 @@ export default {
Card, Card,
Cart Cart
}, },
setup() {
const cartStore = useCartStore();
return { cartStore };
},
data() { data() {
return { return {
api: inject('api'), api: inject('api'),
cartItems: [],
items: [], items: [],
}; };
}, },
computed: {
cartItems: {
get() {
return this.cartStore.items;
},
set(value) {
this.cartStore.items = value;
}
},
cartCount() {
return this.cartStore.cartCount;
}
},
created() { created() {
this.fetchProducts(); this.fetchProducts();
}, },
computed: {
cartCount() {
return this.cartItems.reduce((sum, item) => sum + item.quantity, 0);
}
},
methods: { methods: {
fetchProducts() { fetchProducts() {
this.api.getProducts() this.api.getProducts()
@@ -85,35 +96,17 @@ export default {
}, },
addToCart(item) { addToCart(item) {
if (item.quantity <= 0) return; if (item.quantity <= 0) return;
this.cartStore.addItem(item);
const existingItem = this.cartItems.find(i => i.id === item.id);
if (existingItem) {
existingItem.quantity = item.quantity;
} else {
this.cartItems.push({
id: item.id,
name: item.name,
img: item.img,
price: item.price,
quantity: item.quantity
});
}
}, },
removeFromCart(itemId) { removeFromCart(itemId) {
const index = this.cartItems.findIndex(i => i.id === itemId); this.cartStore.removeItem(itemId);
if (index > -1) {
this.cartItems.splice(index, 1);
}
const item = this.items.find(i => i.id === itemId); const item = this.items.find(i => i.id === itemId);
if (item) { if (item) {
item.quantity = 0; item.quantity = 0;
} }
}, },
updateCartQuantity({ itemId, quantity }) { updateCartQuantity({ itemId, quantity }) {
const cartItem = this.cartItems.find(i => i.id === itemId); this.cartStore.updateQuantity({ itemId, quantity });
if (cartItem) {
cartItem.quantity = quantity;
}
const productItem = this.items.find(i => i.id === itemId); const productItem = this.items.find(i => i.id === itemId);
if (productItem) { if (productItem) {
productItem.quantity = quantity; productItem.quantity = quantity;

43
src/stores/cart.js Normal file
View File

@@ -0,0 +1,43 @@
import { defineStore } from 'pinia'
export const useCartStore = defineStore('cart', {
state: () => ({
items: []
}),
getters: {
cartCount: (state) => state.items.reduce((sum, item) => sum + item.quantity, 0),
cartTotal: (state) => state.items.reduce((sum, item) => sum + (item.price * item.quantity), 0)
},
actions: {
addItem(product) {
const existing = this.items.find(i => i.id === product.id)
if (existing) {
existing.quantity = product.quantity
} else {
this.items.push({
id: product.id,
name: product.name,
img: product.img,
price: product.price,
quantity: product.quantity,
measuring_unit: product.measuring_unit || 'Unidad'
})
}
},
removeItem(itemId) {
const index = this.items.findIndex(i => i.id === itemId)
if (index > -1) {
this.items.splice(index, 1)
}
},
updateQuantity({ itemId, quantity }) {
const item = this.items.find(i => i.id === itemId)
if (item) {
item.quantity = quantity
}
},
clearCart() {
this.items = []
}
}
})