UNPKG

@salla.sa/twilight-components

Version:
198 lines (197 loc) 8.73 kB
/*! * Crafted with ❤ by Salla */ import { h, Host } from "@stencil/core"; import { getOrderEditProductMaxQuantity } from "./helpers"; /** * @salla/ui-components * The `salla-order-edit-item` component renders a single editable order item card * with quantity controls, editable product options, and a remove button. */ export class SallaOrderEditItem { constructor() { this.quantityInput = null; this.productOptions = null; this.handleQuantityChange = (event) => { const detail = event.detail; const newQuantity = detail?.quantity ?? parseInt(event.target.value, 10); if (isNaN(newQuantity) || newQuantity < 1) return; if (newQuantity === this.quantity) return; this.quantity = newQuantity; this.emitUpdate(newQuantity); }; this.handleOptionsChange = () => { this.emitUpdate(this.quantity); }; } componentWillLoad() { this.quantity = this.item?.quantity || 1; } handleItemChange(newItem) { const newQuantity = newItem?.quantity || 1; if (newQuantity === this.quantity) return; this.quantity = newQuantity; this.quantityInput?.setValue?.(newQuantity, false); } get hasOptions() { return (this.item.product?.options?.length || 0) > 0; } async getSelectedOptions() { return (await this.productOptions?.getSelectedOptionsData?.()) || {}; } async getOptionsData() { return (await this.productOptions?.getOptionsData?.()) || this.item.product?.options || []; } async emitUpdate(quantity) { const itemId = this.item?.id; if (itemId == null) return; const detail = { itemId, quantity }; if (this.hasOptions) { detail.options = await this.getSelectedOptions(); detail.optionDefinitions = await this.getOptionsData(); } this.orderItemUpdated.emit(detail); } removeItem() { const itemId = this.item?.id; if (itemId == null) return; this.orderItemRemoved.emit({ itemId }); } render() { if (!this.item) return null; const product = this.item.product; const productName = this.item.name || product?.name || ''; const imageUrl = product?.image?.url || ''; const imageAlt = product?.image?.alt || productName; const productUrl = product?.url || '#'; const price = product?.price; const maxQuantity = getOrderEditProductMaxQuantity(product); const weightLabel = product?.weight_label; const options = this.item.product?.options; const optionsInstanceKey = `order-edit-item-${this.item.id}-${product?.id}`; const quantityAttrs = { value: this.quantity }; if (maxQuantity) { quantityAttrs.max = maxQuantity; } return (h(Host, null, h("div", null, h("div", { class: "s-order-edit-item-header" }, h("div", { class: "s-order-edit-item-media" }, imageUrl && (h("a", { href: productUrl }, h("img", { src: imageUrl, alt: imageAlt, class: "s-order-edit-item-image" }))), h("div", { class: "s-order-edit-item-details" }, h("h2", { class: "s-order-edit-item-name" }, h("a", { href: productUrl, class: "s-order-edit-item-link" }, productName)), price != null && (h("span", { class: "s-order-edit-item-price", innerHTML: salla.money(price) })), weightLabel && (h("p", { class: "s-order-edit-item-weight" }, salla.lang.getWithDefault('pages.products.weight', 'الوزن'), " ", weightLabel)))), h("salla-button", { type: "button", shape: "icon", size: "small", color: "danger", "aria-label": salla.lang.getWithDefault('common.elements.delete', 'حذف'), onClick: () => this.removeItem() }, h("i", { class: "sicon-cancel" }))), h("div", { class: "s-order-edit-item-quantity" }, h("h3", { class: "s-order-edit-item-quantity-label" }, salla.lang.getWithDefault('common.elements.quantity', 'الكمية')), h("div", { class: "s-order-edit-item-quantity-input" }, h("salla-quantity-input", { ref: el => (this.quantityInput = el), ...quantityAttrs, onChange: this.handleQuantityChange }))), this.hasOptions && (h("form", { class: "s-order-edit-item-options", onSubmit: e => e.preventDefault() }, h("salla-product-options", { ref: el => (this.productOptions = el), onChange: this.handleOptionsChange, "product-id": product.id, "unique-key": optionsInstanceKey, options: JSON.stringify(options), key: `${optionsInstanceKey}-options` })))))); } static get is() { return "salla-order-edit-item"; } static get originalStyleUrls() { return { "$": ["salla-order-edit-item.scss"] }; } static get styleUrls() { return { "$": ["salla-order-edit-item.css"] }; } static get properties() { return { "item": { "type": "unknown", "attribute": "item", "mutable": false, "complexType": { "original": "OrderEditItem", "resolved": "OrderEditItem", "references": { "OrderEditItem": { "location": "import", "path": "./interfaces", "id": "src/components/salla-order-edit/interfaces.ts::OrderEditItem" } } }, "required": false, "optional": false, "docs": { "tags": [], "text": "Item data object" }, "getter": false, "setter": false }, "orderId": { "type": "any", "attribute": "order-id", "mutable": false, "complexType": { "original": "string | number", "resolved": "number | string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Parent order ID (for API calls)" }, "getter": false, "setter": false, "reflect": false } }; } static get states() { return { "quantity": {} }; } static get events() { return [{ "method": "orderItemUpdated", "name": "orderItemUpdated", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "Emitted when an item quantity or options are updated" }, "complexType": { "original": "{\n itemId: string | number;\n quantity: number;\n options?: OrderEditSelectedOptions;\n optionDefinitions?: OrderEditProductOption[];\n }", "resolved": "{ itemId: string | number; quantity: number; options?: OrderEditSelectedOptions; optionDefinitions?: Option[]; }", "references": { "OrderEditSelectedOptions": { "location": "import", "path": "./interfaces", "id": "src/components/salla-order-edit/interfaces.ts::OrderEditSelectedOptions" }, "OrderEditProductOption": { "location": "import", "path": "./interfaces", "id": "src/components/salla-order-edit/interfaces.ts::OrderEditProductOption" } } } }, { "method": "orderItemRemoved", "name": "orderItemRemoved", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "Emitted when an item is successfully removed" }, "complexType": { "original": "{\n itemId: string | number;\n }", "resolved": "{ itemId: string | number; }", "references": {} } }]; } static get watchers() { return [{ "propName": "item", "methodName": "handleItemChange" }]; } }