@ikas/storefront 4.0.0-alpha.5 → 4.0.0-alpha.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +13 -13
- package/src/analytics/analytics.ts +2 -1
- package/src/analytics/googleUniversal.ts +12 -2
- package/src/analytics/head/index.tsx +1 -2
- package/src/analytics/ikas.ts +25 -7
- package/src/components/checkout/components/address-form/index.tsx +1 -1
- package/src/components/checkout/components/address-form/model.ts +1 -0
- package/src/components/checkout/components/button/style.module.scss +2 -2
- package/src/components/checkout/components/cart-summary/cart-item/index.tsx +16 -29
- package/src/components/checkout/components/cart-summary/cart-item/style.module.scss +60 -23
- package/src/components/checkout/components/cart-summary/index.tsx +58 -27
- package/src/components/checkout/components/cart-summary/style.module.scss +48 -3
- package/src/components/checkout/components/customer-addresses/index.tsx +7 -2
- package/src/components/checkout/components/customer-addresses/model.ts +16 -8
- package/src/components/checkout/components/error/index.tsx +1 -1
- package/src/components/checkout/components/error/unknown-error/index.tsx +4 -2
- package/src/components/checkout/components/form-item/index.tsx +9 -11
- package/src/components/checkout/components/master-pass/credit-card-form/index.tsx +2 -0
- package/src/components/checkout/components/offer-product/index.tsx +16 -19
- package/src/components/checkout/components/offer-product/style.module.scss +1 -3
- package/src/components/checkout/components/phone-number-input/get-countries.ts +37 -5
- package/src/components/checkout/components/phone-number-input/index.tsx +15 -10
- package/src/components/checkout/index.tsx +28 -19
- package/src/components/checkout/model.ts +214 -91
- package/src/components/checkout/modelMasterPass.ts +2 -2
- package/src/components/checkout/steps/step-info/index.tsx +9 -3
- package/src/components/checkout/steps/step-payment/billing-address/index.tsx +1 -1
- package/src/components/checkout/steps/step-payment/index.tsx +11 -2
- package/src/components/checkout/steps/step-payment/payment-gateways/index.tsx +12 -3
- package/src/components/checkout/steps/step-payment/payment-gateways/installments/index.tsx +5 -3
- package/src/components/checkout/steps/step-payment/style.module.scss +5 -0
- package/src/components/checkout/steps/step-shipping/index.tsx +9 -4
- package/src/components/checkout/steps/step-success/index.tsx +15 -7
- package/src/components/page/head.tsx +12 -0
- package/src/components/page/index.tsx +10 -9
- package/src/components/page-editor/ThemeComponentEditor.tsx +19 -8
- package/src/components/page-editor/model.ts +44 -107
- package/src/models/data/cart/campaign-offer/index.ts +13 -2
- package/src/models/data/cart/index.ts +1 -1
- package/src/models/data/category/path-item/index.ts +4 -0
- package/src/models/data/checkout/index.ts +36 -4
- package/src/models/data/checkout-settings/price/index.ts +2 -0
- package/src/models/data/country/index.ts +4 -0
- package/src/models/data/country/location-translations/index.ts +15 -0
- package/src/models/data/index.ts +3 -0
- package/src/models/data/merchant-settings/index.ts +9 -0
- package/src/models/data/order/index.ts +51 -32
- package/src/models/data/order/line-item/base-unit/index.ts +22 -0
- package/src/models/data/order/line-item/base-unit/unit-type/index.ts +14 -0
- package/src/models/data/order/line-item/index.ts +76 -18
- package/src/models/data/order/line-item/variant/index.ts +8 -0
- package/src/models/data/order/line-item/variant/price/index.ts +2 -0
- package/src/models/data/order/line-item/variant/unit/index.ts +17 -0
- package/src/models/data/order/line-item/variant/value/index.ts +1 -1
- package/src/models/data/order/transaction/index.ts +2 -5
- package/src/models/data/product/attribute-value/index.ts +40 -0
- package/src/models/data/product/base-unit/index.ts +32 -0
- package/src/models/data/product/filter/index.ts +4 -13
- package/src/models/data/product/index.ts +45 -7
- package/src/models/data/product/option-set/index.ts +8 -3
- package/src/models/data/product/option-set/option/index.ts +36 -13
- package/src/models/data/product/variant/index.ts +26 -1
- package/src/models/data/product/variant/price/index.ts +25 -9
- package/src/models/data/product/variant/unit/index.ts +17 -0
- package/src/models/data/product/variant-type/index.ts +2 -0
- package/src/models/data/raffle/index.ts +9 -7
- package/src/models/data/state/index.ts +6 -2
- package/src/models/data/storefront/index.ts +2 -0
- package/src/models/data/storefront/routing/index.tsx +4 -0
- package/src/models/ui/product-list/index.ts +26 -17
- package/src/models/ui/raffle-list/index.ts +1 -1
- package/src/models/ui/validator/form/raffle-form.ts +16 -3
- package/src/models/ui/validator/rules/index.ts +14 -13
- package/src/page-data-init/index.ts +159 -404
- package/src/pages/checkout.tsx +2 -1
- package/src/pages/editor.tsx +5 -2
- package/src/store/base.ts +2 -2
- package/src/store/cart/index.ts +2 -2
- package/src/store/customer/index.ts +7 -17
- package/src/store/index.ts +2 -0
- package/src/store/raffle/index.ts +7 -10
- package/src/utils/constants.ts +1 -1
- package/src/utils/currency.ts +9 -183
- package/src/components/checkout/components/phone-number-input/locale/en.ts +0 -257
- package/src/models/data/category/init.ts +0 -33
|
@@ -160,7 +160,7 @@ export class IkasApplicableProductFilterValue
|
|
|
160
160
|
resultCount?: number | null;
|
|
161
161
|
|
|
162
162
|
// Extra
|
|
163
|
-
|
|
163
|
+
isSelected: boolean;
|
|
164
164
|
|
|
165
165
|
constructor(data: IApplicableProductFilterValue) {
|
|
166
166
|
this.id = data.id || "";
|
|
@@ -174,7 +174,7 @@ export class IkasApplicableProductFilterValue
|
|
|
174
174
|
isVideo: false,
|
|
175
175
|
});
|
|
176
176
|
|
|
177
|
-
this.
|
|
177
|
+
this.isSelected = data.isSelected || false;
|
|
178
178
|
this.resultCount =
|
|
179
179
|
data.resultCount !== undefined && data.resultCount !== null
|
|
180
180
|
? data.resultCount
|
|
@@ -182,17 +182,6 @@ export class IkasApplicableProductFilterValue
|
|
|
182
182
|
|
|
183
183
|
makeAutoObservable(this);
|
|
184
184
|
}
|
|
185
|
-
|
|
186
|
-
get isSelected() {
|
|
187
|
-
return this._isSelected;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
toJSON() {
|
|
191
|
-
return {
|
|
192
|
-
...this,
|
|
193
|
-
isSelected: this._isSelected,
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
185
|
}
|
|
197
186
|
|
|
198
187
|
export class IkasProductFilterValue implements IProductFilterValue {
|
|
@@ -216,12 +205,14 @@ export class IkasProductFilterSettings implements IProductFilterSettings {
|
|
|
216
205
|
showCollapsedOnDesktop: boolean;
|
|
217
206
|
showCollapsedOnMobile: boolean;
|
|
218
207
|
sortType: IkasProductFilterSortType;
|
|
208
|
+
customSortedValues: string[] | null;
|
|
219
209
|
|
|
220
210
|
constructor(data: Partial<IkasProductFilterSettings>) {
|
|
221
211
|
this.useAndFilter = data.useAndFilter || false;
|
|
222
212
|
this.showCollapsedOnDesktop = data.showCollapsedOnDesktop || false;
|
|
223
213
|
this.showCollapsedOnMobile = data.showCollapsedOnMobile || false;
|
|
224
214
|
this.sortType = data.sortType || IkasProductFilterSortType.ALPHABETICAL_ASC;
|
|
215
|
+
this.customSortedValues = data.customSortedValues || null;
|
|
225
216
|
|
|
226
217
|
makeAutoObservable(this);
|
|
227
218
|
}
|
|
@@ -13,16 +13,17 @@ import {
|
|
|
13
13
|
} from "@ikas/storefront-models";
|
|
14
14
|
import { IkasProductOptionSet } from "./option-set";
|
|
15
15
|
import { makeAutoObservable } from "mobx";
|
|
16
|
-
import {
|
|
17
|
-
IkasProductFunctions,
|
|
18
|
-
IkasProductOptionSetFunctions,
|
|
19
|
-
} from "@ikas/storefront-model-functions";
|
|
16
|
+
import { IkasProductFunctions } from "@ikas/storefront-model-functions";
|
|
20
17
|
import { IkasVariantValue } from "../variant-type/variant-value";
|
|
21
18
|
import { IkasProductCampaign } from "./campaign";
|
|
22
19
|
import { IkasStorefrontConfig } from "@ikas/storefront-config";
|
|
23
20
|
import { Analytics } from "../../../analytics";
|
|
24
21
|
import { IkasVariantType } from "../variant-type";
|
|
25
22
|
import { IkasBaseStore } from "../../../store/base";
|
|
23
|
+
import { IkasProductAttributeMap } from "./attribute-value";
|
|
24
|
+
import _groupBy from "lodash/groupBy";
|
|
25
|
+
import { IkasProductBaseUnit } from "./base-unit";
|
|
26
|
+
import { formatCurrency } from "../../../utils";
|
|
26
27
|
|
|
27
28
|
export class IkasProduct implements IProduct {
|
|
28
29
|
id: string;
|
|
@@ -38,6 +39,7 @@ export class IkasProduct implements IProduct {
|
|
|
38
39
|
attributes: IkasProductAttributeValue[];
|
|
39
40
|
variantTypes: IkasProductVariantType[];
|
|
40
41
|
productOptionSetId: string | null = null;
|
|
42
|
+
baseUnit: IkasProductBaseUnit | null;
|
|
41
43
|
|
|
42
44
|
// Extra
|
|
43
45
|
productOptionSet?: IkasProductOptionSet | null = null;
|
|
@@ -69,6 +71,9 @@ export class IkasProduct implements IProduct {
|
|
|
69
71
|
? data.variantTypes.map((v) => new IkasProductVariantType(v))
|
|
70
72
|
: [];
|
|
71
73
|
this.productOptionSetId = data.productOptionSetId || null;
|
|
74
|
+
this.baseUnit = data.baseUnit
|
|
75
|
+
? new IkasProductBaseUnit(data.baseUnit)
|
|
76
|
+
: null;
|
|
72
77
|
|
|
73
78
|
this.productOptionSet = data.productOptionSet
|
|
74
79
|
? new IkasProductOptionSet(data.productOptionSet)
|
|
@@ -94,9 +99,7 @@ export class IkasProduct implements IProduct {
|
|
|
94
99
|
|
|
95
100
|
get hasValidProductOptionValues() {
|
|
96
101
|
if (this.productOptionSet) {
|
|
97
|
-
return
|
|
98
|
-
this.productOptionSet
|
|
99
|
-
);
|
|
102
|
+
return this.productOptionSet.hasValidValues;
|
|
100
103
|
} else {
|
|
101
104
|
return true;
|
|
102
105
|
}
|
|
@@ -161,6 +164,28 @@ export class IkasProduct implements IProduct {
|
|
|
161
164
|
);
|
|
162
165
|
}
|
|
163
166
|
|
|
167
|
+
get groupedAttributeValues(): IkasProductAttributeMap[] {
|
|
168
|
+
const groupedValues = _groupBy(this.attributes, "productAttributeId");
|
|
169
|
+
|
|
170
|
+
return (this.attributes
|
|
171
|
+
?.map((attribute) => {
|
|
172
|
+
const attributeId = attribute.productAttributeId;
|
|
173
|
+
if (!attributeId) return;
|
|
174
|
+
|
|
175
|
+
const values = groupedValues[attributeId];
|
|
176
|
+
if (values?.length && values[0].productAttribute)
|
|
177
|
+
return {
|
|
178
|
+
attribute: values[0].productAttribute,
|
|
179
|
+
values: values,
|
|
180
|
+
};
|
|
181
|
+
})
|
|
182
|
+
.filter((v) => !!v) || []) as IkasProductAttributeMap[];
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
get selectedVariantUnitPriceText() {
|
|
186
|
+
return this.getVariantUnitPriceText(this.selectedVariant);
|
|
187
|
+
}
|
|
188
|
+
|
|
164
189
|
selectVariantValue(variantValue: IkasVariantValue) {
|
|
165
190
|
const metaData = this.metaData;
|
|
166
191
|
const selectedVariantValues = this.selectedVariantValues.map((vv) => {
|
|
@@ -258,6 +283,19 @@ export class IkasProduct implements IProduct {
|
|
|
258
283
|
Analytics.productView(this);
|
|
259
284
|
}
|
|
260
285
|
|
|
286
|
+
getVariantUnitPriceText(variant: IkasProductVariant) {
|
|
287
|
+
const price = variant.price;
|
|
288
|
+
if (!price.unitPrice || !this.baseUnit) {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return `${formatCurrency(
|
|
293
|
+
price.unitPrice,
|
|
294
|
+
price.currency || "",
|
|
295
|
+
price.currencySymbol || ""
|
|
296
|
+
)} / ${this.baseUnit?.unit?.name}`;
|
|
297
|
+
}
|
|
298
|
+
|
|
261
299
|
private setOptionPrices() {
|
|
262
300
|
const variant = this.variants[0];
|
|
263
301
|
if (!variant) return;
|
|
@@ -79,13 +79,18 @@ export class IkasProductOptionSet implements IProductOptionSet {
|
|
|
79
79
|
? data.translations?.map((o) => new IkasProductOptionSetTranslations(o))
|
|
80
80
|
: null;
|
|
81
81
|
|
|
82
|
+
this.initOptionValues();
|
|
82
83
|
makeAutoObservable(this);
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
get displayedOptions() {
|
|
86
|
-
return IkasProductOptionSetFunctions.getDisplayedOptions(
|
|
87
|
-
|
|
88
|
-
);
|
|
87
|
+
return IkasProductOptionSetFunctions.getDisplayedOptions(
|
|
88
|
+
this
|
|
89
|
+
) as IkasProductOption[];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
get hasValidValues() {
|
|
93
|
+
return this.displayedOptions.every((o) => o.hasValidValues);
|
|
89
94
|
}
|
|
90
95
|
|
|
91
96
|
initOptionValues = async () => {
|
|
@@ -13,7 +13,7 @@ import { makeAutoObservable } from "mobx";
|
|
|
13
13
|
import { IkasImage } from "../../../image";
|
|
14
14
|
import _sortBy from "lodash/sortBy";
|
|
15
15
|
import { IkasProductOptionFunctions } from "@ikas/storefront-model-functions";
|
|
16
|
-
import {
|
|
16
|
+
import { getProductOptionFileUrl, uploadFile } from "@ikas/storefront-api";
|
|
17
17
|
|
|
18
18
|
export class IkasProductOptionOtherPrice implements IProductOptionOtherPrice {
|
|
19
19
|
currencyCode: string;
|
|
@@ -181,16 +181,17 @@ export class IkasProductOption implements IProductOption {
|
|
|
181
181
|
this.requiredOptionValueIds = data.requiredOptionValueIds || null;
|
|
182
182
|
|
|
183
183
|
this.values = data.values || [];
|
|
184
|
-
|
|
185
|
-
|
|
184
|
+
this.childOptions = data.childOptions
|
|
185
|
+
? data.childOptions.map((co) => new IkasProductOption(co))
|
|
186
|
+
: [];
|
|
186
187
|
|
|
187
188
|
makeAutoObservable(this);
|
|
188
189
|
}
|
|
189
190
|
|
|
190
191
|
get displayedChildOptions() {
|
|
191
|
-
return IkasProductOptionFunctions.getDisplayedChildOptions(
|
|
192
|
-
|
|
193
|
-
);
|
|
192
|
+
return IkasProductOptionFunctions.getDisplayedChildOptions(
|
|
193
|
+
this
|
|
194
|
+
) as IkasProductOption[];
|
|
194
195
|
}
|
|
195
196
|
|
|
196
197
|
productOptionFileUpload = async (files: File[]) => {
|
|
@@ -202,15 +203,37 @@ export class IkasProductOption implements IProductOption {
|
|
|
202
203
|
)
|
|
203
204
|
return [];
|
|
204
205
|
|
|
205
|
-
let
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
206
|
+
let tempUploadFiles = (
|
|
207
|
+
await Promise.all(
|
|
208
|
+
files.map((file) =>
|
|
209
|
+
getProductOptionFileUrl(
|
|
210
|
+
{
|
|
211
|
+
fileName: file.name,
|
|
212
|
+
productOptionSetId: this.productOptionSetId,
|
|
213
|
+
productOptionId: this.id,
|
|
214
|
+
},
|
|
215
|
+
file
|
|
216
|
+
)
|
|
217
|
+
)
|
|
218
|
+
)
|
|
219
|
+
).filter((file) => file.data);
|
|
220
|
+
|
|
221
|
+
const uploadedFiles: string[] = [];
|
|
222
|
+
for (const file of tempUploadFiles) {
|
|
223
|
+
const isSuccess = await uploadFile(file.data!, file.data!.file);
|
|
224
|
+
if (isSuccess) {
|
|
225
|
+
uploadedFiles.push(file.data!.optionUrl);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return uploadedFiles;
|
|
210
230
|
};
|
|
211
231
|
|
|
212
|
-
get hasValidValues() {
|
|
213
|
-
return
|
|
232
|
+
get hasValidValues(): boolean {
|
|
233
|
+
return (
|
|
234
|
+
IkasProductOptionFunctions.hasValidValues(this) &&
|
|
235
|
+
this.displayedChildOptions.every((o) => o.hasValidValues)
|
|
236
|
+
);
|
|
214
237
|
}
|
|
215
238
|
|
|
216
239
|
get values() {
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { IkasProductPrice } from "./price";
|
|
2
2
|
import { IkasVariantValue } from "../../variant-type/variant-value";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
IkasProductAttributeMap,
|
|
5
|
+
IkasProductAttributeValue,
|
|
6
|
+
} from "../attribute-value";
|
|
4
7
|
import { IkasProductCampaign } from "../campaign";
|
|
5
8
|
import { IkasProductImage } from "../image";
|
|
6
9
|
import { IkasProductVariant as IProductVariant } from "@ikas/storefront-models";
|
|
@@ -11,6 +14,8 @@ import {
|
|
|
11
14
|
listProductBackInStockRemind,
|
|
12
15
|
saveProductBackInStockRemind,
|
|
13
16
|
} from "@ikas/storefront-api";
|
|
17
|
+
import _groupBy from "lodash/groupBy";
|
|
18
|
+
import { IkasProductVariantUnit } from "./unit";
|
|
14
19
|
|
|
15
20
|
export class IkasProductVariant implements IProductVariant {
|
|
16
21
|
id: string;
|
|
@@ -25,6 +30,7 @@ export class IkasProductVariant implements IProductVariant {
|
|
|
25
30
|
sellIfOutOfStock: boolean;
|
|
26
31
|
images: IkasProductImage[] | null;
|
|
27
32
|
campaigns?: IkasProductCampaign[];
|
|
33
|
+
unit: IkasProductVariantUnit | null;
|
|
28
34
|
private _backInStockReminderSaved = false;
|
|
29
35
|
|
|
30
36
|
constructor(data: Partial<IProductVariant> = {}) {
|
|
@@ -47,6 +53,7 @@ export class IkasProductVariant implements IProductVariant {
|
|
|
47
53
|
this.stock = data.stock || 0;
|
|
48
54
|
this.isActive = data.isActive !== undefined ? data.isActive : true;
|
|
49
55
|
this.campaigns = data.campaigns || [];
|
|
56
|
+
this.unit = data.unit ? new IkasProductVariantUnit(data.unit) : null;
|
|
50
57
|
this.sellIfOutOfStock = data.sellIfOutOfStock || false;
|
|
51
58
|
|
|
52
59
|
makeAutoObservable(this);
|
|
@@ -73,6 +80,24 @@ export class IkasProductVariant implements IProductVariant {
|
|
|
73
80
|
return this._backInStockReminderSaved;
|
|
74
81
|
}
|
|
75
82
|
|
|
83
|
+
get groupedAttributeValues(): IkasProductAttributeMap[] {
|
|
84
|
+
const groupedValues = _groupBy(this.attributes, "productAttributeId");
|
|
85
|
+
|
|
86
|
+
return (this.attributes
|
|
87
|
+
?.map((attribute) => {
|
|
88
|
+
const attributeId = attribute.productAttributeId;
|
|
89
|
+
if (!attributeId) return;
|
|
90
|
+
|
|
91
|
+
const values = groupedValues[attributeId];
|
|
92
|
+
if (values?.length && values[0].productAttribute)
|
|
93
|
+
return {
|
|
94
|
+
attribute: values[0].productAttribute,
|
|
95
|
+
values: values,
|
|
96
|
+
};
|
|
97
|
+
})
|
|
98
|
+
.filter((v) => !!v) || []) as IkasProductAttributeMap[];
|
|
99
|
+
}
|
|
100
|
+
|
|
76
101
|
async saveBackInStockReminder(email: string) {
|
|
77
102
|
const listResponse = await listProductBackInStockRemind({
|
|
78
103
|
email: { eq: email },
|
|
@@ -1,47 +1,63 @@
|
|
|
1
1
|
import { IkasProductPriceFunctions } from "@ikas/storefront-model-functions";
|
|
2
2
|
import { IkasProductPrice as IProductPrice } from "@ikas/storefront-models";
|
|
3
3
|
import { makeAutoObservable } from "mobx";
|
|
4
|
-
import {
|
|
4
|
+
import { formatCurrency } from "../../../../../utils/currency";
|
|
5
5
|
|
|
6
6
|
export class IkasProductPrice implements IProductPrice {
|
|
7
7
|
buyPrice: number | null = null;
|
|
8
8
|
currency: string | null = null;
|
|
9
|
+
currencySymbol: string | null = null;
|
|
9
10
|
discountPrice: number | null = null;
|
|
10
11
|
priceListId: string | null = null;
|
|
11
12
|
sellPrice: number;
|
|
13
|
+
unitPrice: number | null = null;
|
|
12
14
|
|
|
13
15
|
constructor(data?: IProductPrice) {
|
|
14
16
|
this.buyPrice = data?.buyPrice ?? null;
|
|
15
17
|
this.currency = data?.currency ?? null;
|
|
18
|
+
this.currencySymbol = data?.currencySymbol ?? "";
|
|
16
19
|
this.discountPrice = data?.discountPrice ?? null;
|
|
17
20
|
this.priceListId = data?.priceListId ?? null;
|
|
18
21
|
this.sellPrice = data?.sellPrice ?? 0;
|
|
22
|
+
this.unitPrice = data?.unitPrice ?? null;
|
|
19
23
|
|
|
20
24
|
makeAutoObservable(this);
|
|
21
25
|
}
|
|
22
26
|
|
|
23
|
-
get currencySymbol() {
|
|
24
|
-
return getCurrencySymbol(this.currency || "");
|
|
25
|
-
}
|
|
26
|
-
|
|
27
27
|
get finalPrice() {
|
|
28
28
|
return IkasProductPriceFunctions.getFinalPrice(this);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
get formattedFinalPrice() {
|
|
32
|
-
return
|
|
32
|
+
return formatCurrency(
|
|
33
|
+
this.finalPrice,
|
|
34
|
+
this.currency || "",
|
|
35
|
+
this.currencySymbol || ""
|
|
36
|
+
);
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
get formattedBuyPrice() {
|
|
36
|
-
return
|
|
40
|
+
return formatCurrency(
|
|
41
|
+
this.buyPrice || 0,
|
|
42
|
+
this.currency || "",
|
|
43
|
+
this.currencySymbol || ""
|
|
44
|
+
);
|
|
37
45
|
}
|
|
38
46
|
|
|
39
47
|
get formattedDiscountPrice() {
|
|
40
|
-
return
|
|
48
|
+
return formatCurrency(
|
|
49
|
+
this.discountPrice || 0,
|
|
50
|
+
this.currency || "",
|
|
51
|
+
this.currencySymbol || ""
|
|
52
|
+
);
|
|
41
53
|
}
|
|
42
54
|
|
|
43
55
|
get formattedSellPrice() {
|
|
44
|
-
return
|
|
56
|
+
return formatCurrency(
|
|
57
|
+
this.sellPrice || 0,
|
|
58
|
+
this.currency || "",
|
|
59
|
+
this.currencySymbol || ""
|
|
60
|
+
);
|
|
45
61
|
}
|
|
46
62
|
|
|
47
63
|
get hasDiscount() {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IkasProductUnitType,
|
|
3
|
+
IkasProductVariantUnit as IProductVariantUnit,
|
|
4
|
+
} from "@ikas/storefront-models";
|
|
5
|
+
import { makeAutoObservable } from "mobx";
|
|
6
|
+
|
|
7
|
+
export class IkasProductVariantUnit implements IProductVariantUnit {
|
|
8
|
+
amount: number | null;
|
|
9
|
+
type: IkasProductUnitType;
|
|
10
|
+
|
|
11
|
+
constructor(data: IProductVariantUnit) {
|
|
12
|
+
this.amount = data.amount;
|
|
13
|
+
this.type = data.type;
|
|
14
|
+
|
|
15
|
+
makeAutoObservable(this);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -3,10 +3,12 @@ import { IkasProductVariantType as IProductVariantType } from "@ikas/storefront-
|
|
|
3
3
|
import { makeAutoObservable } from "mobx";
|
|
4
4
|
|
|
5
5
|
export class IkasProductVariantType implements IProductVariantType {
|
|
6
|
+
order: number;
|
|
6
7
|
variantType: IkasVariantType;
|
|
7
8
|
variantValueIds: string[];
|
|
8
9
|
|
|
9
10
|
constructor(data: Partial<IkasProductVariantType>) {
|
|
11
|
+
this.order = data.order || 0;
|
|
10
12
|
this.variantType = data.variantType
|
|
11
13
|
? new IkasVariantType(data.variantType)
|
|
12
14
|
: new IkasVariantType();
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
IkasRaffleAppliedProduct as IRaffleAppliedProduct,
|
|
9
9
|
IkasRaffleVerificationType,
|
|
10
10
|
IkasRaffleMetadataTargetType,
|
|
11
|
+
IkasRaffleParticipantStatus,
|
|
11
12
|
} from "@ikas/storefront-models";
|
|
12
13
|
import { IkasRaffleFunctions } from "@ikas/storefront-model-functions";
|
|
13
14
|
|
|
@@ -33,13 +34,12 @@ export class IkasRaffle implements IRaffle {
|
|
|
33
34
|
dateRange: IkasRaffleDateRangeField | null;
|
|
34
35
|
metadata: IkasRaffleMetaData | null;
|
|
35
36
|
name: string;
|
|
36
|
-
participantCount?: number | null;
|
|
37
37
|
requiredCustomerAccount: boolean;
|
|
38
38
|
status: boolean;
|
|
39
39
|
variants: IkasRaffleAppliedProduct[] | null;
|
|
40
|
-
products: IkasProduct[];
|
|
41
40
|
verificationType: IkasRaffleVerificationType;
|
|
42
|
-
|
|
41
|
+
|
|
42
|
+
products: IkasProduct[];
|
|
43
43
|
|
|
44
44
|
constructor(data: Partial<IkasRaffle> = {}) {
|
|
45
45
|
this.id = data.id || Date.now() + "";
|
|
@@ -47,12 +47,10 @@ export class IkasRaffle implements IRaffle {
|
|
|
47
47
|
this.updatedAt = data.updatedAt || Date.now();
|
|
48
48
|
this.deleted = data.deleted || null;
|
|
49
49
|
this.name = data.name || "";
|
|
50
|
-
this.participantCount = data.participantCount || 0;
|
|
51
50
|
this.requiredCustomerAccount = data.requiredCustomerAccount || false;
|
|
52
51
|
this.status = data.status || false;
|
|
53
52
|
this.verificationType =
|
|
54
53
|
data.verificationType || IkasRaffleVerificationType.EMAIL;
|
|
55
|
-
this.isCustomerWinner = data.isCustomerWinner || null;
|
|
56
54
|
|
|
57
55
|
this.dateRange = data.dateRange
|
|
58
56
|
? new IkasRaffleDateRangeField(data.dateRange)
|
|
@@ -113,8 +111,10 @@ export class IkasRaffleParticipant implements IRaffleParticipant {
|
|
|
113
111
|
email: string;
|
|
114
112
|
applicationDate: number;
|
|
115
113
|
phone: string | null = null;
|
|
116
|
-
|
|
114
|
+
isDeliveredCargo: boolean | null;
|
|
117
115
|
|
|
116
|
+
raffle: IkasRaffle | null;
|
|
117
|
+
status: IkasRaffleParticipantStatus | null;
|
|
118
118
|
extraData: Record<string, any> | null = null;
|
|
119
119
|
appliedProduct: IkasRaffleAppliedProduct;
|
|
120
120
|
|
|
@@ -131,8 +131,10 @@ export class IkasRaffleParticipant implements IRaffleParticipant {
|
|
|
131
131
|
this.email = data.email || "";
|
|
132
132
|
this.applicationDate = data.applicationDate || 0;
|
|
133
133
|
this.phone = data.phone || null;
|
|
134
|
-
this.
|
|
134
|
+
this.isDeliveredCargo = data.isDeliveredCargo || false;
|
|
135
135
|
|
|
136
|
+
this.raffle = data.raffle ? new IkasRaffle(data.raffle) : null;
|
|
137
|
+
this.status = data.status || null;
|
|
136
138
|
this.extraData = data.extraData || {};
|
|
137
139
|
this.appliedProduct = new IkasRaffleAppliedProduct(
|
|
138
140
|
data.appliedProduct || {}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IkasBaseModel } from "../base";
|
|
2
2
|
import { IkasState as IState } from "@ikas/storefront-models";
|
|
3
|
-
import {
|
|
3
|
+
import { makeObservable, observable } from "mobx";
|
|
4
4
|
|
|
5
5
|
export class IkasState extends IkasBaseModel implements IState {
|
|
6
6
|
countryId: string;
|
|
@@ -13,6 +13,10 @@ export class IkasState extends IkasBaseModel implements IState {
|
|
|
13
13
|
this.name = data.name;
|
|
14
14
|
this.stateCode = data.stateCode;
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
makeObservable(this, {
|
|
17
|
+
countryId: observable,
|
|
18
|
+
name: observable,
|
|
19
|
+
stateCode: observable,
|
|
20
|
+
});
|
|
17
21
|
}
|
|
18
22
|
}
|
|
@@ -20,6 +20,7 @@ export class IkasStorefront implements IStorefront {
|
|
|
20
20
|
analytics4Id: string | null;
|
|
21
21
|
universalAnalyticsId: string | null;
|
|
22
22
|
tiktokPixelId: string | null;
|
|
23
|
+
token: string | null;
|
|
23
24
|
|
|
24
25
|
localizations: IkasStorefrontLocalization[];
|
|
25
26
|
routings: IkasStorefrontRouting[];
|
|
@@ -40,6 +41,7 @@ export class IkasStorefront implements IStorefront {
|
|
|
40
41
|
this.analytics4Id = data.analytics4Id || null;
|
|
41
42
|
this.universalAnalyticsId = data.universalAnalyticsId || null;
|
|
42
43
|
this.tiktokPixelId = data.tiktokPixelId || null;
|
|
44
|
+
this.token = data.token || null;
|
|
43
45
|
|
|
44
46
|
// Sub Models
|
|
45
47
|
this.localizations = data.localizations
|
|
@@ -10,6 +10,8 @@ export class IkasStorefrontRouting implements IStorefrontRouting {
|
|
|
10
10
|
path: string | null;
|
|
11
11
|
priceListId: string | null;
|
|
12
12
|
dynamicCurrencySettings: IkasStorefrontDynamicCurrencySettings | null;
|
|
13
|
+
currencyCode: string | null;
|
|
14
|
+
currencySymbol: string | null;
|
|
13
15
|
|
|
14
16
|
constructor(data: IStorefrontRouting) {
|
|
15
17
|
this.id = data.id;
|
|
@@ -19,6 +21,8 @@ export class IkasStorefrontRouting implements IStorefrontRouting {
|
|
|
19
21
|
this.path = data.path;
|
|
20
22
|
this.priceListId = data.priceListId;
|
|
21
23
|
this.dynamicCurrencySettings = data.dynamicCurrencySettings;
|
|
24
|
+
this.currencyCode = data.currencyCode;
|
|
25
|
+
this.currencySymbol = data.currencySymbol;
|
|
22
26
|
|
|
23
27
|
makeAutoObservable(this);
|
|
24
28
|
}
|
|
@@ -56,31 +56,45 @@ export class IkasProductList {
|
|
|
56
56
|
private _fetchRequestTime = 0;
|
|
57
57
|
private router?: NextRouter | null = null;
|
|
58
58
|
|
|
59
|
-
constructor(
|
|
59
|
+
constructor(
|
|
60
|
+
data: IkasProductListParams | IkasProductList,
|
|
61
|
+
router?: NextRouter
|
|
62
|
+
) {
|
|
63
|
+
const _params = data as IkasProductListParams;
|
|
64
|
+
const _list = data as IkasProductList;
|
|
65
|
+
|
|
60
66
|
this.data = data.data ? data.data.map((d) => new IkasProduct(d)) : [];
|
|
61
67
|
this._type =
|
|
62
|
-
|
|
63
|
-
|
|
68
|
+
_params.type ||
|
|
69
|
+
_list._type ||
|
|
70
|
+
_params.productListPropValue.productListType ||
|
|
71
|
+
_list._productListPropValue.productListType ||
|
|
64
72
|
IkasProductListType.ALL;
|
|
65
73
|
this._pageType = data.pageType;
|
|
66
74
|
this._sort =
|
|
67
75
|
data.sort ||
|
|
68
76
|
data.productListPropValue.initialSort ||
|
|
69
77
|
IkasProductListSortType.LAST_ADDED;
|
|
70
|
-
|
|
71
|
-
|
|
78
|
+
this._limit =
|
|
79
|
+
data.limit ||
|
|
80
|
+
_params.productListPropValue.initialLimit ||
|
|
81
|
+
_list._productListPropValue.initialLimit ||
|
|
82
|
+
20;
|
|
72
83
|
this._page = data.page || 1;
|
|
73
84
|
this._minPage = data.minPage || null;
|
|
74
85
|
this._count = data.count || 0;
|
|
75
86
|
this._searchKeyword = data.searchKeyword || "";
|
|
76
|
-
this._productListPropValue =
|
|
87
|
+
this._productListPropValue =
|
|
88
|
+
_params.productListPropValue || _list._productListPropValue;
|
|
77
89
|
|
|
78
|
-
this._filterBrandId =
|
|
79
|
-
this._filterCategoryId =
|
|
90
|
+
this._filterBrandId = _params.filterBrandId || _list._filterBrandId || null;
|
|
91
|
+
this._filterCategoryId =
|
|
92
|
+
_params.filterCategoryId || _list._filterCategoryId || null;
|
|
80
93
|
|
|
81
|
-
this._relatedProductData =
|
|
94
|
+
this._relatedProductData =
|
|
95
|
+
_params.relatedProductData || _list._relatedProductData || null;
|
|
82
96
|
|
|
83
|
-
this._recommendFor =
|
|
97
|
+
this._recommendFor = _params.recommendFor || _list._recommendFor;
|
|
84
98
|
|
|
85
99
|
this.filters = data.filters
|
|
86
100
|
? data.filters.map((f) => new IkasProductFilter(f, this))
|
|
@@ -88,7 +102,8 @@ export class IkasProductList {
|
|
|
88
102
|
this._filterCategories = data.filterCategories
|
|
89
103
|
? data.filterCategories.map((c) => new IkasFilterCategory(c))
|
|
90
104
|
: null;
|
|
91
|
-
this.pageSpecificData =
|
|
105
|
+
this.pageSpecificData =
|
|
106
|
+
_params.pageSpecificData || _list.pageSpecificData || null;
|
|
92
107
|
|
|
93
108
|
this.router = router;
|
|
94
109
|
|
|
@@ -221,12 +236,6 @@ export class IkasProductList {
|
|
|
221
236
|
|
|
222
237
|
get filterQueryParams() {
|
|
223
238
|
const queryParams: Record<string, any> = {};
|
|
224
|
-
const _getQueryParams = this.getQueryParams();
|
|
225
|
-
if (_getQueryParams) {
|
|
226
|
-
_getQueryParams.forEach((value, key) => {
|
|
227
|
-
queryParams[key] = value;
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
239
|
|
|
231
240
|
this.filters?.forEach((f) => {
|
|
232
241
|
if (f.keyList.length) queryParams[f.key] = f.keyList;
|
|
@@ -75,7 +75,7 @@ export class IkasRaffleList {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
private async getRaffleList(page: number, limit: number) {
|
|
78
|
-
const response = await RaffleStore.
|
|
78
|
+
const response = await RaffleStore.listStorefrontRaffle({
|
|
79
79
|
start: this._start ? { eq: this._start } : undefined,
|
|
80
80
|
end: this._end ? { eq: this._end } : undefined,
|
|
81
81
|
includeDeleted: this._includeDeleted || false,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { saveRaffleParticipant } from "@ikas/storefront-api";
|
|
2
2
|
import { action, computed, makeObservable, observable } from "mobx";
|
|
3
|
+
import { GraphQLError } from "graphql";
|
|
3
4
|
|
|
4
5
|
import { Validator } from "..";
|
|
5
6
|
import { IkasBaseStore } from "../../../../store";
|
|
@@ -237,7 +238,11 @@ export class RaffleForm {
|
|
|
237
238
|
}
|
|
238
239
|
|
|
239
240
|
async submit() {
|
|
240
|
-
const response
|
|
241
|
+
const response: {
|
|
242
|
+
isFormError: boolean;
|
|
243
|
+
isSuccess: boolean;
|
|
244
|
+
errors?: readonly GraphQLError[];
|
|
245
|
+
} = { isFormError: false, isSuccess: false };
|
|
241
246
|
const hasFormError = await this.validateAll();
|
|
242
247
|
if (hasFormError) {
|
|
243
248
|
response.isFormError = true;
|
|
@@ -246,7 +251,7 @@ export class RaffleForm {
|
|
|
246
251
|
|
|
247
252
|
try {
|
|
248
253
|
const selectedVariant = this.raffle.products[0].selectedVariant;
|
|
249
|
-
const
|
|
254
|
+
const saveRaffleParticipantResponse = await saveRaffleParticipant({
|
|
250
255
|
input: {
|
|
251
256
|
appliedProduct: {
|
|
252
257
|
productId: selectedVariant.productId,
|
|
@@ -264,12 +269,20 @@ export class RaffleForm {
|
|
|
264
269
|
},
|
|
265
270
|
});
|
|
266
271
|
|
|
267
|
-
if (
|
|
272
|
+
if (saveRaffleParticipantResponse?.graphQLErrors) {
|
|
273
|
+
response.errors = saveRaffleParticipantResponse.graphQLErrors;
|
|
274
|
+
response.isSuccess = false;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (saveRaffleParticipantResponse.data) {
|
|
268
278
|
response.isSuccess = true;
|
|
269
279
|
}
|
|
270
280
|
|
|
271
281
|
return response;
|
|
272
282
|
} catch (error) {
|
|
283
|
+
if (error) {
|
|
284
|
+
response.errors = error;
|
|
285
|
+
}
|
|
273
286
|
return response;
|
|
274
287
|
}
|
|
275
288
|
}
|