87 lines
2.9 KiB
TypeScript
87 lines
2.9 KiB
TypeScript
// Ported from legacy henza_admin/src/store/invoiceCart/invoiceCart.js
|
|
//
|
|
// The basket behind the branch-allocation ("فاکتور") screen. Structurally a copy
|
|
// of the order cart, with two deliberate differences:
|
|
//
|
|
// 1. STORAGE KEY — legacy wrote BOTH carts to 'admin_cart_items', so building an
|
|
// allocation clobbered a half-finished order and vice versa. Verified in
|
|
// legacy: store/cart/cart.js:27 and store/invoiceCart/invoiceCart.js:27 use
|
|
// the same key. This cart gets its own key instead; reproducing silent data
|
|
// loss would be worse than the deviation. Recorded in docs/ADMIN-PORT-PLAN.md.
|
|
//
|
|
// 2. No re-hydrate fetch — the allocation screen only needs product ids, so
|
|
// there is no variant/stock refresh to perform.
|
|
import { defineStore } from 'pinia';
|
|
import { isBranch } from '../utils';
|
|
|
|
const cartKey = isBranch() ? 'branch_invoice_items' : 'admin_invoice_items';
|
|
|
|
export interface InvoiceCartItem {
|
|
pid: string;
|
|
vid?: string;
|
|
qty: number;
|
|
product: Record<string, unknown>;
|
|
}
|
|
|
|
export const useInvoiceCartStore = defineStore('invoiceCart', {
|
|
state: () => ({
|
|
items: [] as InvoiceCartItem[],
|
|
}),
|
|
actions: {
|
|
/** legacy mutation INIT — also persists */
|
|
setItems(res: InvoiceCartItem[]) {
|
|
this.items = res;
|
|
localStorage.setItem(cartKey, JSON.stringify(res));
|
|
},
|
|
|
|
/** legacy mutation ADD_TO_CART, including its out-of-stock guard */
|
|
add(data: InvoiceCartItem) {
|
|
const index = this.items.findIndex((i) => i.pid == data.pid && i.vid == data.vid);
|
|
const variants = (data.product?.variants_all ?? []) as {
|
|
id: string;
|
|
qty?: number;
|
|
is_pre_order?: boolean;
|
|
}[];
|
|
const variant = variants.filter((x) => x.id === data.vid)[0];
|
|
|
|
// legacy: when a variant was named, it must be in stock or a pre-order.
|
|
// The allocation screen adds whole products (no vid), which legacy let
|
|
// through only because `variant` was undefined — preserved.
|
|
if (data.vid && variant && !variant.is_pre_order && variant.qty === 0) return;
|
|
|
|
if (index == -1) {
|
|
this.items.push(data);
|
|
} else {
|
|
this.items[index].product = data.product;
|
|
this.items[index].qty = data.qty;
|
|
}
|
|
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);
|
|
},
|
|
|
|
/** Rehydrate from localStorage on mount. */
|
|
init() {
|
|
try {
|
|
this.items = JSON.parse(localStorage.getItem(cartKey) ?? '[]') || [];
|
|
} catch {
|
|
this.items = [];
|
|
}
|
|
},
|
|
},
|
|
});
|