@ikas/storefront-model-functions 4.0.0-alpha.10
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 +39 -0
- package/src/functions/blog/category/index.ts +6 -0
- package/src/functions/blog/index.ts +6 -0
- package/src/functions/brand/index.ts +6 -0
- package/src/functions/category/index.ts +6 -0
- package/src/functions/category/path-item/index.ts +15 -0
- package/src/functions/checkout/index.ts +35 -0
- package/src/functions/customer/address/index.ts +90 -0
- package/src/functions/customer/attribute/index.ts +18 -0
- package/src/functions/customer/index.ts +23 -0
- package/src/functions/filter-category/index.ts +6 -0
- package/src/functions/image/index.ts +27 -0
- package/src/functions/order/address/index.ts +110 -0
- package/src/functions/order/index.ts +92 -0
- package/src/functions/order/line-item/index.ts +30 -0
- package/src/functions/order/line-item/variant/index.ts +15 -0
- package/src/functions/order/line-item/variant/value/index.ts +18 -0
- package/src/functions/payment-gateway/index.ts +44 -0
- package/src/functions/product/attribute-value/index.ts +5 -0
- package/src/functions/product/filter/index.ts +197 -0
- package/src/functions/product/index.ts +145 -0
- package/src/functions/product/option-set/index.ts +19 -0
- package/src/functions/product/option-set/option/index.ts +189 -0
- package/src/functions/product/variant/index.ts +9 -0
- package/src/functions/product/variant/price/index.ts +20 -0
- package/src/functions/raffle/index.ts +14 -0
- package/src/functions/variant-type/index.ts +13 -0
- package/src/functions/variant-type/variant-value/index.ts +13 -0
- package/src/index.ts +107 -0
- package/src/utils/helper.ts +59 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IkasApplicableProductFilterValue,
|
|
3
|
+
IkasFilterRangeValue,
|
|
4
|
+
IkasProductFilter,
|
|
5
|
+
IkasProductFilterDisplayType,
|
|
6
|
+
IkasProductFilterNumberRangeListOption,
|
|
7
|
+
IkasProductFilterSortType,
|
|
8
|
+
IkasProductFilterType,
|
|
9
|
+
} from "@ikas/storefront-models";
|
|
10
|
+
import _sortBy from "lodash/sortBy";
|
|
11
|
+
import _cloneDeep from "lodash/cloneDeep";
|
|
12
|
+
|
|
13
|
+
export function isCustomValueFilter(filter: IkasProductFilter) {
|
|
14
|
+
return [
|
|
15
|
+
IkasProductFilterDisplayType.NUMBER_RANGE_LIST,
|
|
16
|
+
IkasProductFilterDisplayType.NUMBER_RANGE,
|
|
17
|
+
].includes(filter.displayType);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function isStockFilter(filter: IkasProductFilter) {
|
|
21
|
+
return filter.type === IkasProductFilterType.STOCK_STATUS;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function getValueList(filter: IkasProductFilter) {
|
|
25
|
+
if (filter.numberRange) return [rangeToId(filter.numberRange)];
|
|
26
|
+
if (filter.numberRangeListOptions)
|
|
27
|
+
return filter.numberRangeListOptions
|
|
28
|
+
.filter((o) => o.isSelected)
|
|
29
|
+
.map((o) => rangeToId(o));
|
|
30
|
+
|
|
31
|
+
return filter.values?.filter((v) => v.isSelected).map((v) => v.id) || [];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function getKeyList(filter: IkasProductFilter) {
|
|
35
|
+
if (filter.numberRange) return [rangeToId(filter.numberRange)];
|
|
36
|
+
if (filter.numberRangeListOptions)
|
|
37
|
+
return filter.numberRangeListOptions
|
|
38
|
+
.filter((o) => o.isSelected)
|
|
39
|
+
.map((o) => rangeToId(o));
|
|
40
|
+
|
|
41
|
+
return filter.values?.filter((v) => v.isSelected).map((v) => v.key) || [];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function getDisplayedValues(filter: IkasProductFilter) {
|
|
45
|
+
const sortType =
|
|
46
|
+
filter.settings?.sortType || IkasProductFilterSortType.ALPHABETICAL_ASC;
|
|
47
|
+
|
|
48
|
+
const isDesc = [
|
|
49
|
+
IkasProductFilterSortType.ALPHABETICAL_DESC,
|
|
50
|
+
IkasProductFilterSortType.PRODUCT_COUNT_DESC,
|
|
51
|
+
].includes(sortType);
|
|
52
|
+
const isAlphabetical = [
|
|
53
|
+
IkasProductFilterSortType.ALPHABETICAL_ASC,
|
|
54
|
+
IkasProductFilterSortType.ALPHABETICAL_DESC,
|
|
55
|
+
].includes(sortType);
|
|
56
|
+
|
|
57
|
+
let _values = filter.values?.filter((v) =>
|
|
58
|
+
v.resultCount === 0 ? v.isSelected : true
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
if (isAlphabetical) _values = _sortBy(_values, "name");
|
|
62
|
+
else _values = _sortBy(_values, "resultCount");
|
|
63
|
+
|
|
64
|
+
if (isDesc) _values = _values?.reverse();
|
|
65
|
+
|
|
66
|
+
return _values;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function onFilterValueClick(
|
|
70
|
+
filter: IkasProductFilter,
|
|
71
|
+
filterValue: IkasApplicableProductFilterValue
|
|
72
|
+
) {
|
|
73
|
+
if (isCustomValueFilter(filter)) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
"onFilterValueClick cannot be used with NUMBER_RANGE | NUMBER_RANGE_LIST types!"
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
filterValue.isSelected = !filterValue.isSelected;
|
|
80
|
+
|
|
81
|
+
if (!filter.isMultiSelect && filterValue.isSelected) {
|
|
82
|
+
filter.values?.forEach((fv) => {
|
|
83
|
+
if (fv.id !== filterValue.id) (fv as any)._isSelected = false;
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function onNumberRangeClick(
|
|
89
|
+
filter: IkasProductFilter,
|
|
90
|
+
option: IkasProductFilterNumberRangeListOption
|
|
91
|
+
) {
|
|
92
|
+
if (filter.displayType !== IkasProductFilterDisplayType.NUMBER_RANGE_LIST)
|
|
93
|
+
throw new Error(
|
|
94
|
+
"onNumberRangeClick can only be used with NUMBER_RANGE filters!"
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
(option as any)._isSelected = !option.isSelected;
|
|
98
|
+
|
|
99
|
+
if (!filter.isMultiSelect && option.isSelected) {
|
|
100
|
+
filter.numberRangeListOptions?.forEach((nro) => {
|
|
101
|
+
if (nro.key !== option.key) (nro as any)._isSelected = false;
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function onNumberRangeChange(
|
|
107
|
+
filter: IkasProductFilter,
|
|
108
|
+
numberRange: IkasFilterRangeValue | null
|
|
109
|
+
) {
|
|
110
|
+
if (filter.displayType !== IkasProductFilterDisplayType.NUMBER_RANGE)
|
|
111
|
+
throw new Error(
|
|
112
|
+
"onNumberRangeChange can only be used with NUMBER_RANGE filters!"
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
if (!numberRange) {
|
|
116
|
+
filter.numberRange = null;
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const newRange = _cloneDeep(numberRange);
|
|
121
|
+
if (newRange.from < filter.numberRangeLimit!.from)
|
|
122
|
+
newRange.from = filter.numberRange!.from;
|
|
123
|
+
if (
|
|
124
|
+
newRange.to &&
|
|
125
|
+
filter.numberRangeLimit?.to &&
|
|
126
|
+
newRange.to > filter.numberRangeLimit.to
|
|
127
|
+
)
|
|
128
|
+
newRange.to = filter.numberRangeLimit.to;
|
|
129
|
+
|
|
130
|
+
filter.numberRange = newRange;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function clear(filter: IkasProductFilter) {
|
|
134
|
+
filter.numberRange = null;
|
|
135
|
+
filter.numberRangeListOptions?.forEach(
|
|
136
|
+
(o) => ((o as any)._isSelected = false)
|
|
137
|
+
);
|
|
138
|
+
filter.values?.forEach((v) => ((v as any)._isSelected = false));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function toInput(
|
|
142
|
+
filter: IkasProductFilter
|
|
143
|
+
): IkasSearchInputFilterListInput {
|
|
144
|
+
return {
|
|
145
|
+
id: filter.key,
|
|
146
|
+
type: filter.type as any,
|
|
147
|
+
valueList: getValueList(filter),
|
|
148
|
+
useAndFilter: filter.settings?.useAndFilter,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function applyQueryParam(filter: IkasProductFilter, value: string) {
|
|
153
|
+
const valueKeys = value.split(",");
|
|
154
|
+
|
|
155
|
+
if (filter.displayType === IkasProductFilterDisplayType.NUMBER_RANGE) {
|
|
156
|
+
filter.numberRange = parseRangeStr(value);
|
|
157
|
+
} else if (
|
|
158
|
+
filter.displayType === IkasProductFilterDisplayType.NUMBER_RANGE_LIST
|
|
159
|
+
) {
|
|
160
|
+
filter.numberRangeListOptions?.forEach((o) => {
|
|
161
|
+
if (valueKeys.includes(o.key)) (o as any)._isSelected = true;
|
|
162
|
+
});
|
|
163
|
+
} else {
|
|
164
|
+
filter.values?.forEach((filterValue) => {
|
|
165
|
+
if (valueKeys.includes(filterValue.key) && filterValue.resultCount !== 0)
|
|
166
|
+
(filterValue as any)._isSelected = true;
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export function rangeToId(range: IkasFilterRangeValue) {
|
|
172
|
+
return `${range.from}:${range.to || ""}`;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export function parseRangeStr(rangeStr: string): IkasFilterRangeValue {
|
|
176
|
+
try {
|
|
177
|
+
const parsedValues = rangeStr.split(":").map((i) => parseInt(i));
|
|
178
|
+
return {
|
|
179
|
+
from: isNaN(parsedValues[0]) ? 0 : parsedValues[0],
|
|
180
|
+
to: isNaN(parsedValues[1]) ? undefined : parsedValues[1],
|
|
181
|
+
};
|
|
182
|
+
} catch (err) {
|
|
183
|
+
console.log(err);
|
|
184
|
+
return {
|
|
185
|
+
from: 0,
|
|
186
|
+
to: 0,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export type IkasSearchInputFilterListInput = {
|
|
192
|
+
displayType?: IkasProductFilterDisplayType | null;
|
|
193
|
+
id: string;
|
|
194
|
+
type: IkasProductFilterType;
|
|
195
|
+
useAndFilter?: boolean | null;
|
|
196
|
+
valueList: string[];
|
|
197
|
+
};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IkasDisplayedVariantType,
|
|
3
|
+
IkasDisplayedVariantValue,
|
|
4
|
+
IkasProduct,
|
|
5
|
+
IkasProductOptionSet,
|
|
6
|
+
IkasProductVariant,
|
|
7
|
+
IkasVariantValue,
|
|
8
|
+
} from "@ikas/storefront-models";
|
|
9
|
+
import { getIkasVariantTypeSlug } from "../variant-type";
|
|
10
|
+
import { getIkasVariantValueSlug } from "../variant-type/variant-value";
|
|
11
|
+
import { hasValidValues as hasValidProductOptionSetValues } from "./option-set";
|
|
12
|
+
import { hasStock as hasVariantStock } from "./variant/index";
|
|
13
|
+
|
|
14
|
+
export function hasVariant(product: IkasProduct) {
|
|
15
|
+
return !!product.variantTypes.length;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function hasStock(product: IkasProduct) {
|
|
19
|
+
return product.variants.some((v) => v.stock > 0);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function getMainVariantValue(selectedVariantValues: IkasVariantValue[]) {
|
|
23
|
+
return selectedVariantValues.length ? selectedVariantValues[0] : undefined;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function getMainVariantType(product: IkasProduct) {
|
|
27
|
+
if (!hasVariant(product)) return;
|
|
28
|
+
return product.variantTypes[0].variantType;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function getSelectedVariantHref(
|
|
32
|
+
product: IkasProduct,
|
|
33
|
+
selectedVariantValues: IkasVariantValue[]
|
|
34
|
+
) {
|
|
35
|
+
const metaData = product.metaData;
|
|
36
|
+
if (!metaData?.slug) return "";
|
|
37
|
+
|
|
38
|
+
const variantParams = product.variantTypes
|
|
39
|
+
.map((pvt) => {
|
|
40
|
+
const vt = pvt.variantType;
|
|
41
|
+
const selectedVariantValue = vt.values.find((vv) =>
|
|
42
|
+
selectedVariantValues.some((svv) => svv.id === vv.id)
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
if (selectedVariantValue)
|
|
46
|
+
return `${getIkasVariantTypeSlug(vt)}=${getIkasVariantValueSlug(
|
|
47
|
+
selectedVariantValue
|
|
48
|
+
)}`;
|
|
49
|
+
})
|
|
50
|
+
.filter((param) => !!param)
|
|
51
|
+
.join("&");
|
|
52
|
+
|
|
53
|
+
if (variantParams) return `/${metaData!.slug}?${variantParams}`;
|
|
54
|
+
else return `/${metaData!.slug}`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function getProductHref(product: IkasProduct) {
|
|
58
|
+
const metaData = product.metaData;
|
|
59
|
+
if (!metaData?.slug) return "";
|
|
60
|
+
|
|
61
|
+
return `/${metaData.slug}`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function getDisplayedVariantTypes(
|
|
65
|
+
product: IkasProduct,
|
|
66
|
+
selectedVariantValues: IkasVariantValue[]
|
|
67
|
+
): IkasDisplayedVariantType[] {
|
|
68
|
+
const displayedVariantTypes = product.variantTypes.map(
|
|
69
|
+
(productVariantType, index) => {
|
|
70
|
+
const variantType = productVariantType.variantType;
|
|
71
|
+
const displayedVariantValues: IkasDisplayedVariantValue[] = [];
|
|
72
|
+
|
|
73
|
+
const parentProductVariantTypes =
|
|
74
|
+
index > 0 ? product.variantTypes.slice(0, index) : null;
|
|
75
|
+
let parentSelectedVariantValues: IkasVariantValue[] = [];
|
|
76
|
+
|
|
77
|
+
if (parentProductVariantTypes) {
|
|
78
|
+
parentSelectedVariantValues = selectedVariantValues.filter((vv) =>
|
|
79
|
+
parentProductVariantTypes.some(
|
|
80
|
+
(pvt) => pvt.variantType.id === vv.variantTypeId
|
|
81
|
+
)
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
variantType.values.forEach((variantValue) => {
|
|
86
|
+
const variantValues = [...parentSelectedVariantValues, variantValue];
|
|
87
|
+
const variant = product.variants.find(
|
|
88
|
+
(variant) =>
|
|
89
|
+
variant.isActive &&
|
|
90
|
+
variantValues.every((vv) =>
|
|
91
|
+
variant.variantValues.some((vvv) => vvv.id === vv.id)
|
|
92
|
+
)
|
|
93
|
+
);
|
|
94
|
+
const variantWithStock = product.variants.find(
|
|
95
|
+
(variant) =>
|
|
96
|
+
variant.isActive &&
|
|
97
|
+
hasVariantStock(variant) &&
|
|
98
|
+
variantValues.every((vv) =>
|
|
99
|
+
variant.variantValues.some((vvv) => vvv.id === vv.id)
|
|
100
|
+
)
|
|
101
|
+
);
|
|
102
|
+
const isSelected = selectedVariantValues.some(
|
|
103
|
+
(vv) => vv.id === variantValue.id
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
if (variant) {
|
|
107
|
+
displayedVariantValues.push({
|
|
108
|
+
variant,
|
|
109
|
+
variantValue,
|
|
110
|
+
hasStock: !!variantWithStock,
|
|
111
|
+
isSelected,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
variantType,
|
|
118
|
+
displayedVariantValues,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
// Filter inactive variantValues if there is only a single variant type
|
|
124
|
+
if (displayedVariantTypes.length === 1) {
|
|
125
|
+
displayedVariantTypes[0].displayedVariantValues =
|
|
126
|
+
displayedVariantTypes[0].displayedVariantValues.filter(
|
|
127
|
+
(dvv) => dvv.variant.isActive
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return displayedVariantTypes;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function isAddToCartEnabled(
|
|
135
|
+
selectedVariant: IkasProductVariant,
|
|
136
|
+
productOptionSet?: IkasProductOptionSet
|
|
137
|
+
) {
|
|
138
|
+
const _hasValidProductOptionValues = productOptionSet
|
|
139
|
+
? hasValidProductOptionSetValues(productOptionSet)
|
|
140
|
+
: true;
|
|
141
|
+
return (
|
|
142
|
+
_hasValidProductOptionValues &&
|
|
143
|
+
(hasVariantStock(selectedVariant) || selectedVariant.sellIfOutOfStock)
|
|
144
|
+
);
|
|
145
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { IkasProductOptionSet } from "@ikas/storefront-models";
|
|
2
|
+
import _sortBy from "lodash/sortBy";
|
|
3
|
+
import { initValues } from "./option";
|
|
4
|
+
import { hasValidValues as hasValidOptionValues } from "./option";
|
|
5
|
+
|
|
6
|
+
export function getDisplayedOptions(optionSet: IkasProductOptionSet) {
|
|
7
|
+
return _sortBy(
|
|
8
|
+
optionSet.options.filter((o) => !o.requiredOptionId),
|
|
9
|
+
"order"
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function initOptionValues(optionSet: IkasProductOptionSet) {
|
|
14
|
+
optionSet.options.forEach((o) => initValues(o));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function hasValidValues(optionSet: IkasProductOptionSet) {
|
|
18
|
+
return getDisplayedOptions(optionSet).every(hasValidOptionValues);
|
|
19
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IkasProductOption,
|
|
3
|
+
IkasProductOptionType,
|
|
4
|
+
} from "@ikas/storefront-models";
|
|
5
|
+
import _sortBy from "lodash/sortBy";
|
|
6
|
+
|
|
7
|
+
export function getDisplayedChildOptions(option: IkasProductOption) {
|
|
8
|
+
return _sortBy(
|
|
9
|
+
option.childOptions.filter((co) => {
|
|
10
|
+
// Check if all required options are selected
|
|
11
|
+
if (co.requiredOptionValueIds?.length) {
|
|
12
|
+
return co.requiredOptionValueIds.every((rovId) =>
|
|
13
|
+
option.values.some((v) => v === rovId)
|
|
14
|
+
);
|
|
15
|
+
} else {
|
|
16
|
+
if (option.type === IkasProductOptionType.CHECKBOX) {
|
|
17
|
+
return !!option.values.length && option.values[0] === "true";
|
|
18
|
+
}
|
|
19
|
+
return !!option.values.length;
|
|
20
|
+
}
|
|
21
|
+
}),
|
|
22
|
+
"order"
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function hasValidValues(option: IkasProductOption): boolean {
|
|
27
|
+
if (!option.values.length && !option.isOptional) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let _hasValidValues = false;
|
|
32
|
+
|
|
33
|
+
switch (option.type) {
|
|
34
|
+
case IkasProductOptionType.TEXT:
|
|
35
|
+
case IkasProductOptionType.TEXT_AREA:
|
|
36
|
+
_hasValidValues = isValidTextOptionValue(option);
|
|
37
|
+
break;
|
|
38
|
+
|
|
39
|
+
case IkasProductOptionType.CHECKBOX:
|
|
40
|
+
case IkasProductOptionType.COLOR_PICKER:
|
|
41
|
+
_hasValidValues = true;
|
|
42
|
+
break;
|
|
43
|
+
|
|
44
|
+
case IkasProductOptionType.CHOICE:
|
|
45
|
+
_hasValidValues = isValidChoiceOptionValue(option);
|
|
46
|
+
break;
|
|
47
|
+
|
|
48
|
+
case IkasProductOptionType.DATE_PICKER:
|
|
49
|
+
_hasValidValues = isValidDateOptionValue(option);
|
|
50
|
+
break;
|
|
51
|
+
|
|
52
|
+
case IkasProductOptionType.FILE:
|
|
53
|
+
_hasValidValues = isValidFileOptionValue(option);
|
|
54
|
+
break;
|
|
55
|
+
|
|
56
|
+
default:
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
_hasValidValues &&
|
|
62
|
+
getDisplayedChildOptions(option).every((co) => hasValidValues(co))
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function setValues(option: IkasProductOption, values: string[]) {
|
|
67
|
+
option.values = values;
|
|
68
|
+
if (!values.length) {
|
|
69
|
+
option.childOptions.forEach((co) => (co.values = []));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function initValues(option: IkasProductOption) {
|
|
74
|
+
if (!option.isOptional) {
|
|
75
|
+
option.values = [];
|
|
76
|
+
if (option.childOptions) {
|
|
77
|
+
option.childOptions.forEach((co) => initValues(co));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function isValidTextOptionValue(option: IkasProductOption) {
|
|
83
|
+
const value = option.values[0];
|
|
84
|
+
if (!value) {
|
|
85
|
+
return !!option.isOptional;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
!!option.textSettings &&
|
|
90
|
+
(option.textSettings.min !== null
|
|
91
|
+
? value.length >= option.textSettings.min
|
|
92
|
+
: true) &&
|
|
93
|
+
(option.textSettings.max !== null
|
|
94
|
+
? value.length <= option.textSettings.max
|
|
95
|
+
: true)
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function isValidChoiceOptionValue(option: IkasProductOption) {
|
|
100
|
+
if (!option.values.length) {
|
|
101
|
+
return !!option.isOptional;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
!!option.selectSettings &&
|
|
106
|
+
(option.selectSettings.minSelect !== null
|
|
107
|
+
? option.values.length >= option.selectSettings.minSelect
|
|
108
|
+
: true) &&
|
|
109
|
+
(option.selectSettings.maxSelect !== null
|
|
110
|
+
? option.values.length <= option.selectSettings.maxSelect
|
|
111
|
+
: true)
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function isValidFileOptionValue(option: IkasProductOption) {
|
|
116
|
+
if (!option.values.length) {
|
|
117
|
+
return !!option.isOptional;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
!!option.fileSettings &&
|
|
122
|
+
(option.fileSettings.minQuantity !== null
|
|
123
|
+
? option.values.length >= option.fileSettings.minQuantity
|
|
124
|
+
: true) &&
|
|
125
|
+
(option.fileSettings.maxQuantity !== null
|
|
126
|
+
? option.values.length <= option.fileSettings.maxQuantity
|
|
127
|
+
: true)
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function isValidDateOptionValue(option: IkasProductOption) {
|
|
132
|
+
if (!option.values.length) {
|
|
133
|
+
return !!option.isOptional;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (!!option.dateSettings) {
|
|
137
|
+
let minDate: Date | null = null;
|
|
138
|
+
let maxDate: Date | null = null;
|
|
139
|
+
|
|
140
|
+
if (option.dateSettings.minRelativeNextDate !== null) {
|
|
141
|
+
minDate = new Date();
|
|
142
|
+
if (option.dateSettings.minRelativeNextDate < 0) {
|
|
143
|
+
minDate = new Date(
|
|
144
|
+
minDate.setDate(
|
|
145
|
+
minDate.getDate() -
|
|
146
|
+
Math.abs(option.dateSettings.minRelativeNextDate)
|
|
147
|
+
)
|
|
148
|
+
);
|
|
149
|
+
} else {
|
|
150
|
+
minDate = new Date(
|
|
151
|
+
minDate.setDate(
|
|
152
|
+
minDate.getDate() +
|
|
153
|
+
Math.abs(option.dateSettings.minRelativeNextDate)
|
|
154
|
+
)
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
minDate = new Date(minDate.setHours(23, 59, 0));
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (option.dateSettings.maxRelativeNextDate !== null) {
|
|
162
|
+
maxDate = new Date();
|
|
163
|
+
if (option.dateSettings.maxRelativeNextDate < 0) {
|
|
164
|
+
maxDate = new Date(
|
|
165
|
+
maxDate.setDate(
|
|
166
|
+
maxDate.getDate() -
|
|
167
|
+
Math.abs(option.dateSettings.maxRelativeNextDate)
|
|
168
|
+
)
|
|
169
|
+
);
|
|
170
|
+
} else {
|
|
171
|
+
maxDate = new Date(
|
|
172
|
+
maxDate.setDate(
|
|
173
|
+
maxDate.getDate() +
|
|
174
|
+
Math.abs(option.dateSettings.maxRelativeNextDate)
|
|
175
|
+
)
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
maxDate = new Date(maxDate.setHours(23, 59, 59));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const value = new Date(new Date(option.values[0]).setHours(23, 59, 59));
|
|
183
|
+
|
|
184
|
+
return (
|
|
185
|
+
(minDate ? value.getTime() >= minDate.getTime() : true) &&
|
|
186
|
+
(maxDate ? value.getTime() <= maxDate.getTime() : true)
|
|
187
|
+
);
|
|
188
|
+
} else return true;
|
|
189
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { IkasProductVariant } from "@ikas/storefront-models";
|
|
2
|
+
|
|
3
|
+
export function getMainImage(variant: IkasProductVariant) {
|
|
4
|
+
return variant.images?.length ? variant.images[0] : undefined;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function hasStock(variant: IkasProductVariant) {
|
|
8
|
+
return variant.stock > 0;
|
|
9
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { IkasProductPrice } from "@ikas/storefront-models";
|
|
2
|
+
|
|
3
|
+
export function getFinalPrice(price: IkasProductPrice) {
|
|
4
|
+
return price.discountPrice !== null ? price.discountPrice : price.sellPrice;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function hasDiscount(price: IkasProductPrice) {
|
|
8
|
+
return price.discountPrice !== null;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function getDiscountAmount(price: IkasProductPrice) {
|
|
12
|
+
if (hasDiscount(price)) return price.sellPrice - price.discountPrice!;
|
|
13
|
+
return 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function getDiscountPercentage(price: IkasProductPrice) {
|
|
17
|
+
if (hasDiscount(price))
|
|
18
|
+
return (100 - (getFinalPrice(price) * 100) / price.sellPrice).toFixed(0);
|
|
19
|
+
return 0;
|
|
20
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { IkasRaffle } from "@ikas/storefront-models";
|
|
2
|
+
|
|
3
|
+
export function isRaffleAvailable(raffle: IkasRaffle) {
|
|
4
|
+
if (!raffle.status) return false;
|
|
5
|
+
|
|
6
|
+
const now = Date.now();
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
raffle.dateRange?.start &&
|
|
10
|
+
now > raffle.dateRange.start &&
|
|
11
|
+
raffle.dateRange.end &&
|
|
12
|
+
now < raffle.dateRange.end
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IkasVariantSelectionType,
|
|
3
|
+
IkasVariantType,
|
|
4
|
+
} from "@ikas/storefront-models";
|
|
5
|
+
import { stringToSlug } from "../../utils/helper";
|
|
6
|
+
|
|
7
|
+
export function isColorSelection(variantType: IkasVariantType) {
|
|
8
|
+
return variantType.selectionType === IkasVariantSelectionType.COLOR;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function getIkasVariantTypeSlug(variantType: IkasVariantType) {
|
|
12
|
+
return stringToSlug(variantType.name);
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { IkasImage, IkasVariantValue } from "@ikas/storefront-models";
|
|
2
|
+
import { stringToSlug } from "../../../utils/helper";
|
|
3
|
+
|
|
4
|
+
export function getIkasVariantValueSlug(variantValue: IkasVariantValue) {
|
|
5
|
+
return stringToSlug(variantValue.name);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function getThumbnailImage(
|
|
9
|
+
variantValue: IkasVariantValue
|
|
10
|
+
): IkasImage | undefined {
|
|
11
|
+
if (variantValue.thumbnailImageId)
|
|
12
|
+
return { id: variantValue.thumbnailImageId, isVideo: false };
|
|
13
|
+
}
|