Files
tehran_tala/apps/admin-panel/src/stores/invoiceCart.ts
T

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 = [];
}
},
},
});