81 lines
2.3 KiB
TypeScript
81 lines
2.3 KiB
TypeScript
import {
|
||
calculateSweetsWeightTotal,
|
||
formatSweetWeightLabel,
|
||
} from '../sweets/pricing';
|
||
|
||
/** Shared order-line model used by cart, pre-order, and table orders. */
|
||
|
||
export type OrderPricingMode = 'standard' | 'weight';
|
||
|
||
export interface OrderLine {
|
||
id: string;
|
||
name: string;
|
||
price: number;
|
||
quantity: number;
|
||
image?: string;
|
||
pricingMode?: OrderPricingMode;
|
||
pricePerKg?: number;
|
||
pricePerHalfKg?: number;
|
||
}
|
||
|
||
export type NewOrderLine = Omit<OrderLine, 'quantity'>;
|
||
|
||
export function addOrderLine(lines: OrderLine[], item: NewOrderLine): OrderLine[] {
|
||
const existing = lines.find((line) => line.id === item.id);
|
||
if (existing) {
|
||
return lines.map((line) =>
|
||
line.id === item.id ? { ...line, quantity: line.quantity + 1 } : line
|
||
);
|
||
}
|
||
return [...lines, { ...item, quantity: 1 }];
|
||
}
|
||
|
||
export function updateOrderLineQuantity(
|
||
lines: OrderLine[],
|
||
id: string,
|
||
quantity: number
|
||
): OrderLine[] {
|
||
if (quantity <= 0) {
|
||
return lines.filter((line) => line.id !== id);
|
||
}
|
||
return lines.map((line) => (line.id === id ? { ...line, quantity } : line));
|
||
}
|
||
|
||
export function removeOrderLine(lines: OrderLine[], id: string): OrderLine[] {
|
||
return lines.filter((line) => line.id !== id);
|
||
}
|
||
|
||
export function calculateLineTotal(line: OrderLine): number {
|
||
if (line.pricingMode === 'weight') {
|
||
return calculateSweetsWeightTotal(line.quantity);
|
||
}
|
||
return line.price * line.quantity;
|
||
}
|
||
|
||
export function calculateOrderTotal(lines: OrderLine[]): number {
|
||
return lines.reduce((sum, line) => sum + calculateLineTotal(line), 0);
|
||
}
|
||
|
||
export function calculateOrderItemCount(lines: OrderLine[]): number {
|
||
return lines.reduce((sum, line) => sum + line.quantity, 0);
|
||
}
|
||
|
||
export function formatOrderLinesForMessage(lines: OrderLine[]): string {
|
||
return lines
|
||
.map((line) => {
|
||
const total = calculateLineTotal(line);
|
||
if (line.pricingMode === 'weight') {
|
||
const weight = formatSweetWeightLabel(line.quantity);
|
||
return `${line.name} (${weight}) — ${total} kr`;
|
||
}
|
||
return `${line.quantity} × ${line.name} — ${total} kr`;
|
||
})
|
||
.join('\n');
|
||
}
|
||
|
||
export function formatLineQuantityLabel(line: OrderLine): string {
|
||
if (line.pricingMode === 'weight') {
|
||
return formatSweetWeightLabel(line.quantity);
|
||
}
|
||
return String(line.quantity);
|
||
} |