126 lines
3.8 KiB
TypeScript
126 lines
3.8 KiB
TypeScript
// Ported from legacy henza_admin/src/store/cart/cart.js
|
|
//
|
|
// The admin-side order builder's basket. Behaviour is preserved exactly,
|
|
// including the two guards legacy applied:
|
|
// - ADD_TO_CART refuses an out-of-stock variant that is not a pre-order
|
|
// (`!variant.is_pre_order && variant.qty === 0`)
|
|
// - init() re-fetches every cart product and drops any that became
|
|
// out-of-stock while the basket sat in localStorage
|
|
//
|
|
// Storage key differs per mode ('admin_cart_items' vs 'branch_cart_items'),
|
|
// as in legacy.
|
|
import { defineStore } from 'pinia';
|
|
import api from '../api/client';
|
|
import { isBranch } from '../utils';
|
|
|
|
const cartKey = isBranch() ? 'branch_cart_items' : 'admin_cart_items';
|
|
|
|
export interface CartVariant {
|
|
id: string;
|
|
is_pre_order?: boolean;
|
|
qty?: number;
|
|
price?: number;
|
|
price_with_discount?: number;
|
|
grams?: number;
|
|
title?: string;
|
|
}
|
|
|
|
export interface CartProduct {
|
|
id: string;
|
|
variants_all: CartVariant[];
|
|
promotion?: { id: string } | null;
|
|
[k: string]: unknown;
|
|
}
|
|
|
|
export interface CartItem {
|
|
vid: string;
|
|
pid: string;
|
|
product: CartProduct;
|
|
qty: number;
|
|
promotion_id?: string | null;
|
|
}
|
|
|
|
export const useCartStore = defineStore('cart', {
|
|
state: () => ({
|
|
items: [] as CartItem[],
|
|
}),
|
|
actions: {
|
|
/** legacy mutation ADD_TO_CART */
|
|
addToCart(data: CartItem) {
|
|
const index = this.items.findIndex((item) => item.pid == data.pid && item.vid == data.vid);
|
|
const variant = data.product.variants_all.filter((x) => x.id === data.vid)[0];
|
|
// legacy guard: reject an out-of-stock, non-pre-order variant
|
|
if (variant && !(!variant.is_pre_order && variant.qty === 0)) {
|
|
if (index == -1) {
|
|
this.items.push(data);
|
|
} else {
|
|
this.items[index].product = data.product;
|
|
this.items[index].qty = data.qty;
|
|
}
|
|
}
|
|
},
|
|
|
|
/** legacy mutation INIT — also persists to localStorage */
|
|
setItems(res: CartItem[]) {
|
|
this.items = res;
|
|
localStorage.setItem(cartKey, JSON.stringify(res));
|
|
},
|
|
|
|
add(data: CartItem) {
|
|
this.addToCart(data);
|
|
this.setItems(this.items);
|
|
},
|
|
|
|
remove(item: { pid: string; vid: string }) {
|
|
const index = this.items.findIndex((v) => v.pid == item.pid && v.vid == item.vid);
|
|
if (index > -1) this.items.splice(index, 1);
|
|
this.setItems(this.items);
|
|
},
|
|
|
|
updateItemQuantity(payload: { index: number; quantity: number }) {
|
|
this.items[payload.index].qty = payload.quantity;
|
|
this.setItems(this.items);
|
|
},
|
|
|
|
clear() {
|
|
this.items = [];
|
|
this.setItems(this.items);
|
|
},
|
|
|
|
/**
|
|
* legacy init(): rehydrate from localStorage, then re-fetch each product so
|
|
* prices and stock are current, dropping anything now out of stock.
|
|
*/
|
|
async init() {
|
|
try {
|
|
const items: CartItem[] = JSON.parse(localStorage.getItem(cartKey) ?? '[]') || [];
|
|
const ids = items.map((item) => item.product.id);
|
|
if (ids.length === 0) {
|
|
this.setItems([]);
|
|
return;
|
|
}
|
|
const { data } = await api.post('product/variant', { products_id: ids });
|
|
if (data) {
|
|
const exp: CartItem[] = [];
|
|
for (const cartItem of items) {
|
|
const product = (data as CartProduct[]).find((item) => item.id == cartItem.product.id);
|
|
if (!product) continue;
|
|
if (!(!product.variants_all[0].is_pre_order && product.variants_all[0].qty === 0)) {
|
|
exp.push({
|
|
vid: cartItem.vid,
|
|
pid: product.id,
|
|
product,
|
|
qty: cartItem.qty,
|
|
promotion_id: product.promotion && product.promotion.id ? product.promotion.id : null,
|
|
});
|
|
}
|
|
}
|
|
this.setItems(exp);
|
|
}
|
|
} catch (e) {
|
|
console.log('error in cart', e);
|
|
}
|
|
},
|
|
},
|
|
});
|