From ae6dcaf50a6db703c50a686a1fd2d29823336305 Mon Sep 17 00:00:00 2001 From: khirvy019 Date: Mon, 29 Apr 2024 12:27:52 +0800 Subject: [PATCH 1/6] fix marketplace app not initializing properly --- src/layouts/MarketplaceLayout.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/layouts/MarketplaceLayout.vue b/src/layouts/MarketplaceLayout.vue index a1caa59f..bf1b9470 100644 --- a/src/layouts/MarketplaceLayout.vue +++ b/src/layouts/MarketplaceLayout.vue @@ -47,7 +47,7 @@ export default defineComponent({ onMounted(() => loadApp()) async function loadApp() { - if (marketplaceStore.appRefreshScopePromise) { + if (marketplaceStore.appRefreshScopePromise instanceof Promise) { return marketplaceStore.appRefreshScopePromise } marketplaceStore.appRefreshScopePromise = _loadApp() From db06408c5446b46ad0b8d0f51279bd2607882061 Mon Sep 17 00:00:00 2001 From: khirvy019 Date: Mon, 29 Apr 2024 12:30:19 +0800 Subject: [PATCH 2/6] add addon options form in add & edit product page --- .../cartoptions/AddonsFormDialog.vue | 521 ++++++++++++++++++ .../cartoptions/AddonsInfoDialog.vue | 53 ++ .../cartoptions/AddonsInfoPanel.vue | 60 ++ src/marketplace/objects.js | 108 ++++ src/marketplace/product-addons.js | 46 ++ src/pages/marketplace/products/AddProduct.vue | 55 ++ .../marketplace/products/UpdateProduct.vue | 62 +++ 7 files changed, 905 insertions(+) create mode 100644 src/components/marketplace/cartoptions/AddonsFormDialog.vue create mode 100644 src/components/marketplace/cartoptions/AddonsInfoDialog.vue create mode 100644 src/components/marketplace/cartoptions/AddonsInfoPanel.vue create mode 100644 src/marketplace/product-addons.js diff --git a/src/components/marketplace/cartoptions/AddonsFormDialog.vue b/src/components/marketplace/cartoptions/AddonsFormDialog.vue new file mode 100644 index 00000000..ed21dfbb --- /dev/null +++ b/src/components/marketplace/cartoptions/AddonsFormDialog.vue @@ -0,0 +1,521 @@ + + + + diff --git a/src/components/marketplace/cartoptions/AddonsInfoDialog.vue b/src/components/marketplace/cartoptions/AddonsInfoDialog.vue new file mode 100644 index 00000000..66941099 --- /dev/null +++ b/src/components/marketplace/cartoptions/AddonsInfoDialog.vue @@ -0,0 +1,53 @@ + + diff --git a/src/components/marketplace/cartoptions/AddonsInfoPanel.vue b/src/components/marketplace/cartoptions/AddonsInfoPanel.vue new file mode 100644 index 00000000..aaa2f00f --- /dev/null +++ b/src/components/marketplace/cartoptions/AddonsInfoPanel.vue @@ -0,0 +1,60 @@ + + + diff --git a/src/marketplace/objects.js b/src/marketplace/objects.js index 82ab3d25..a356f4b1 100644 --- a/src/marketplace/objects.js +++ b/src/marketplace/objects.js @@ -387,6 +387,7 @@ export class Product { fetchingStocks: false, fetchingShops: false, updatingCartOptions: false, + updatingAddons: false, } } @@ -400,6 +401,8 @@ export class Product { * @param {String} [data.code] * @param {String[]} data.categories * @param {Object[]} [data.cart_options] + * @param {Object[]} [data.addons] + * @param {Number} [data.addons_count] * @param {Boolean} data.has_cart_options * @param {String} data.image_url * @param {String} [data.variant_image_url] @@ -422,6 +425,8 @@ export class Product { this.code = data?.code if (Array.isArray(data?.categories)) this.categories = [...data.categories] if (Array.isArray(data?.cart_options)) this.cartOptions = [...data.cart_options] + if (Array.isArray(data?.addons)) this.addons = data.addons.map(Addon.parse) + this.addonsCount = data?.addons?.length ?? data?.addons_count this.hasCartOptions = data?.has_cart_options this.imageUrl = data?.image_url this.variantImageUrl = data?.variant_image_url @@ -533,6 +538,27 @@ export class Product { }) } + + async fetchAddons() { + if (!this.id) return Promise.resolve() + + this.$state.updatingAddons = true + const params = { ids: this.id } + return backend.get(`products/addons/`, { params }) + .then(response => { + const obj = response?.data?.results?.find(product => product?.id == this?.id) + console.log('obj', obj) + if (obj) { + this.addons = obj?.addons.map?.(Addon.parse) + if (this.$raw) this.$raw.cartOptions = obj?.addons + } + return response + }) + .finally(() => { + this.$state.updatingAddons = false + }) + } + async refetch(params={}) { if (!this.id) return this.$state.updating = true @@ -576,6 +602,86 @@ export class Product { } +export class Addon { + static parse(data) { + return new Addon(data) + } + + constructor(data) { + this.raw = data + } + + get raw() { + return this.$raw + } + + /** + * @param {Object} data + * @param {Number} data.id + * @param {String} data.label + * @param {Number} data.min_opts + * @param {Number} data.max_opts + * @param {{ id: Number, label: String, price: Number, markup_price: Number, require_input: Boolean }[]} data.options + */ + set raw(data) { + Object.defineProperty(this, '$raw', { enumerable: false, configurable: true, value: data }) + this.id = data?.id + this.label = data?.label + this.minOpts = data?.min_opts + this.maxOpts = data?.max_opts + this.options = (Array.isArray(data?.options) ? data.options : []).map(option => { + return { + id: option?.id, + label: option?.label, + price: option?.price, + markupPrice: option?.markup_price, + requireInput: option?.require_input, + } + }) + } + + get hasOptions() { + return this.options?.length > 1 + } + + get option() { + if (!this.hasOptions) return + return this.option[0] + } +} + +export class LineItemAddon { + static parse(data) { + return new LineItemAddon(data) + } + + constructor(data) { + this.raw = data + } + + get raw() { + return this.$raw + } + + /** + * @param {Object} data + * @param {Number} data.addon_option_id + * @param {String} data.label + * @param {Number} data.price + * @param {Number} data.markup_price + * @param {String} data.input_value + */ + set raw(data) { + Object.defineProperty(this, '$raw', { enumerable: false, configurable: true, value: data }) + this.addonOptionId = data?.addon_option_id + this.label = data?.label + this.price = data?.price + this.markupPrice = data?.markup_price + this.inputValue = data?.input_value + } +} + + export class Shop { static parse(data) { return new Shop(data) @@ -1572,6 +1678,7 @@ export class OrderItem { * @param {Number} data.price * @param {Number} data.markup_price * @param {{ schema:Array, data:Object }} [data.properties] + * @param {Object[]} [data.addons] */ set raw(data) { Object.defineProperty(this, '$raw', { enumerable: false, configurable: true, value: data }) @@ -1582,6 +1689,7 @@ export class OrderItem { this.price = data?.price this.markupPrice = data?.markup_price this.properties = data?.properties + this.addons = (Array.isArray(data?.addons) ? data.addons: []).map(LineItemAddon.parse) } get propertiesText() { diff --git a/src/marketplace/product-addons.js b/src/marketplace/product-addons.js new file mode 100644 index 00000000..147704ae --- /dev/null +++ b/src/marketplace/product-addons.js @@ -0,0 +1,46 @@ +/** + * + * @typedef {Object} AddonOptionInfoAPI + * @property {String} label + * @property {Number} price + * @property {Number} markup_price + * @property {Boolean} require_input + * + * @typedef {Object} AddonOptionInfo + * @property {String} label + * @property {Number} price + * @property {Number} [markupPrice] + * @property {Boolean} requireInput + * + * @typedef {Object} AddonInfo + * @property {String} label + * @property {Number} minOpts + * @property {Number} maxOpts + * @property {AddonOptionInfo[]} options + * + * @typedef {Object} AddonInfoAPI + * @property {String} label + * @property {Number} min_opts + * @property {Number} max_opts + * @property {AddonOptionInfoAPI[]} options + */ + + +/** + * @param {AddonInfo | AddonInfoAPI} addon + */ +export function parseProductAddon(addon) { + return { + label: addon?.label, + minOpts: addon?.minOpts ?? addon?.min__opts, + maxOpts: addon?.maxOpts ?? addon?.max__opts, + options: (Array.isArray(addon?.options) ? addon.options : [])?.map?.(opt => { + return { + label: opt?.label, + price: opt?.price, + markupPrice: opt?.markupPrice || opt?.markup_price, + requireInput: opt?.requireInput ?? opt?.require_input, + } + }) + } +} diff --git a/src/pages/marketplace/products/AddProduct.vue b/src/pages/marketplace/products/AddProduct.vue index 2829a2ae..28e50b88 100644 --- a/src/pages/marketplace/products/AddProduct.vue +++ b/src/pages/marketplace/products/AddProduct.vue @@ -60,6 +60,10 @@ errorMessage: formErrors?.categories, }" /> + + + +
Cart options
@@ -119,6 +123,24 @@
+ +
+
Addon Options
+
+ +
@@ -263,6 +285,7 @@