@ordergroove/offers 2.34.8-alpha-PR-793-2.0 → 2.35.0
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/CHANGELOG.md +30 -0
- package/dist/bundle-report.html +11 -11
- package/dist/offers.js +36 -36
- package/dist/offers.js.map +3 -3
- package/package.json +4 -3
- package/src/shopify/__tests__/productPlan.spec.js +13 -13
- package/src/shopify/__tests__/shopifyReducer.spec.js +417 -350
- package/src/shopify/__tests__/utils.spec.js +7 -3
- package/src/shopify/reducers/productPlans.ts +26 -22
- package/src/shopify/shopifyBootstrap.ts +9 -1
- package/src/shopify/shopifyMiddleware.ts +38 -9
- package/src/shopify/shopifyReducer.js +3 -3
- package/src/shopify/types/shopify.ts +133 -0
- package/src/shopify/utils.ts +7 -1
|
@@ -4,14 +4,18 @@ describe('Shopify Utils', () => {
|
|
|
4
4
|
describe('Money', () => {
|
|
5
5
|
it('Should return formatted greater than $1 money price', () => {
|
|
6
6
|
const price = 1000;
|
|
7
|
-
const formattedPrice = money(price);
|
|
7
|
+
const formattedPrice = money(price, 'USD');
|
|
8
8
|
expect(formattedPrice).toBe('$10.00');
|
|
9
9
|
});
|
|
10
10
|
|
|
11
11
|
it('Should return formatted lower than $1 money price', () => {
|
|
12
12
|
const price = 50;
|
|
13
|
-
const formattedPrice = money(price);
|
|
14
|
-
expect(formattedPrice).toBe('
|
|
13
|
+
const formattedPrice = money(price, 'USD');
|
|
14
|
+
expect(formattedPrice).toBe('$0.50');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('Should format JPY values', () => {
|
|
18
|
+
expect(money(310000, 'JPY')).toBe('¥3,100');
|
|
15
19
|
});
|
|
16
20
|
});
|
|
17
21
|
|
|
@@ -20,25 +20,25 @@ export const getAllocationFrequency = (allocation: ShopifySellingPlanAllocations
|
|
|
20
20
|
return (allocation.selling_plan_id || (allocation.selling_plan?.id ?? '')).toString();
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
-
export const getAllocationRegularPrice = (allocation: ShopifySellingPlanAllocationsEntity) => {
|
|
24
|
-
return money(allocation.compare_at_price);
|
|
23
|
+
export const getAllocationRegularPrice = (allocation: ShopifySellingPlanAllocationsEntity, currency: string) => {
|
|
24
|
+
return money(allocation.compare_at_price, currency);
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
-
export const getAllocationSubscriptionPrice = (allocation: ShopifySellingPlanAllocationsEntity) => {
|
|
27
|
+
export const getAllocationSubscriptionPrice = (allocation: ShopifySellingPlanAllocationsEntity, currency: string) => {
|
|
28
28
|
if (isPrepaidAllocation(allocation)) {
|
|
29
29
|
const prepaidShipmentsPerBilling = getPrepaidShipmentsNumberFromOptions(allocation.selling_plan?.options);
|
|
30
30
|
const pricePerShipment = Math.round(allocation.price / prepaidShipmentsPerBilling);
|
|
31
|
-
return money(pricePerShipment);
|
|
31
|
+
return money(pricePerShipment, currency);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
return money(allocation.price);
|
|
34
|
+
return money(allocation.price, currency);
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
const getPrepaidPercentage = (allocation: ShopifySellingPlanAllocationsEntity, pricePerShipment: number) => {
|
|
38
38
|
return Math.round(((allocation.compare_at_price - pricePerShipment) * 100) / allocation.compare_at_price);
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
-
export const getAllocationDiscountRate = (allocation: ShopifySellingPlanAllocationsEntity) => {
|
|
41
|
+
export const getAllocationDiscountRate = (allocation: ShopifySellingPlanAllocationsEntity, currency: string) => {
|
|
42
42
|
if (isPrepaidAllocation(allocation)) {
|
|
43
43
|
const prepaidShipmentsPerBilling = getPrepaidShipmentsNumberFromOptions(allocation.selling_plan?.options);
|
|
44
44
|
const pricePerShipment = allocation.price / prepaidShipmentsPerBilling;
|
|
@@ -52,9 +52,9 @@ export const getAllocationDiscountRate = (allocation: ShopifySellingPlanAllocati
|
|
|
52
52
|
if (allocation.price_adjustments[0]?.value_type === 'percentage') {
|
|
53
53
|
formatted_discount = percentage(allocation.price_adjustments[0].value);
|
|
54
54
|
} else if (allocation.price_adjustments[0]?.value) {
|
|
55
|
-
formatted_discount = money(allocation.price_adjustments[0].value);
|
|
55
|
+
formatted_discount = money(allocation.price_adjustments[0].value, currency);
|
|
56
56
|
} else if (allocation.compare_at_price) {
|
|
57
|
-
formatted_discount = money(allocation.compare_at_price - allocation.price);
|
|
57
|
+
formatted_discount = money(allocation.compare_at_price - allocation.price, currency);
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
return formatted_discount;
|
|
@@ -70,7 +70,8 @@ export const getAllocationNumberOfShipments = (allocation: ShopifySellingPlanAll
|
|
|
70
70
|
export const addPrepaidPriceAndSavings = (
|
|
71
71
|
allocation: ShopifySellingPlanAllocationsEntity,
|
|
72
72
|
productPlan: ProductPlanEntity,
|
|
73
|
-
payAsYouGoPlan: ShopifySellingPlansEntity
|
|
73
|
+
payAsYouGoPlan: ShopifySellingPlansEntity,
|
|
74
|
+
currency: string
|
|
74
75
|
) => {
|
|
75
76
|
const prepaidShipmentsPerBilling = getPrepaidShipmentsNumberFromOptions(allocation.selling_plan?.options);
|
|
76
77
|
const pricePerShipment = allocation.price / prepaidShipmentsPerBilling;
|
|
@@ -80,9 +81,9 @@ export const addPrepaidPriceAndSavings = (
|
|
|
80
81
|
const payAsYouGoPercentage =
|
|
81
82
|
payAsYouGoAdjustment && payAsYouGoAdjustment.value_type === 'percentage' ? payAsYouGoAdjustment.value : null;
|
|
82
83
|
|
|
83
|
-
productPlan['regularPrepaidPrice'] = money(allocation.price);
|
|
84
|
-
productPlan['prepaidSavingsPerShipment'] = money(Math.round(prepaidSaving));
|
|
85
|
-
productPlan['prepaidSavingsTotal'] = money(Math.round(prepaidSaving * prepaidShipmentsPerBilling));
|
|
84
|
+
productPlan['regularPrepaidPrice'] = money(allocation.price, currency);
|
|
85
|
+
productPlan['prepaidSavingsPerShipment'] = money(Math.round(prepaidSaving), currency);
|
|
86
|
+
productPlan['prepaidSavingsTotal'] = money(Math.round(prepaidSaving * prepaidShipmentsPerBilling), currency);
|
|
86
87
|
|
|
87
88
|
if (payAsYouGoPercentage && prepaidPercentageSavings) {
|
|
88
89
|
productPlan['prepaidExtraSavingsPercentage'] = percentage(prepaidPercentageSavings - payAsYouGoPercentage);
|
|
@@ -95,7 +96,8 @@ export const DEFAULT_PAY_AS_YOU_GO_GROUP_NAME = 'Subscribe and Save';
|
|
|
95
96
|
|
|
96
97
|
export const mapSellingPlanToDiscount = (
|
|
97
98
|
allocation: ShopifySellingPlanAllocationsEntity,
|
|
98
|
-
sellingPlans: ShopifySellingPlansEntity[]
|
|
99
|
+
sellingPlans: ShopifySellingPlansEntity[],
|
|
100
|
+
currency: string
|
|
99
101
|
) => {
|
|
100
102
|
if (!allocation.selling_plan) {
|
|
101
103
|
allocation.selling_plan = sellingPlans.find(plan => plan.id === allocation.selling_plan_id);
|
|
@@ -103,9 +105,9 @@ export const mapSellingPlanToDiscount = (
|
|
|
103
105
|
|
|
104
106
|
const productPlan: ProductPlanEntity = {
|
|
105
107
|
frequency: getAllocationFrequency(allocation),
|
|
106
|
-
regularPrice: getAllocationRegularPrice(allocation),
|
|
107
|
-
subscriptionPrice: getAllocationSubscriptionPrice(allocation),
|
|
108
|
-
discountRate: getAllocationDiscountRate(allocation),
|
|
108
|
+
regularPrice: getAllocationRegularPrice(allocation, currency),
|
|
109
|
+
subscriptionPrice: getAllocationSubscriptionPrice(allocation, currency),
|
|
110
|
+
discountRate: getAllocationDiscountRate(allocation, currency),
|
|
109
111
|
prepaidShipments: getAllocationNumberOfShipments(allocation)
|
|
110
112
|
};
|
|
111
113
|
|
|
@@ -113,19 +115,21 @@ export const mapSellingPlanToDiscount = (
|
|
|
113
115
|
const payAsYouGoPlan = sellingPlans.find(
|
|
114
116
|
plan => plan.group_name === DEFAULT_PAY_AS_YOU_GO_GROUP_NAME && plan.options.length === 1
|
|
115
117
|
);
|
|
116
|
-
return addPrepaidPriceAndSavings(allocation, productPlan, payAsYouGoPlan);
|
|
118
|
+
return addPrepaidPriceAndSavings(allocation, productPlan, payAsYouGoPlan, currency);
|
|
117
119
|
}
|
|
118
120
|
|
|
119
121
|
return productPlan;
|
|
120
122
|
};
|
|
121
123
|
|
|
122
|
-
export const sellingPlanAllocationsReducer = (
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
]
|
|
124
|
+
export const sellingPlanAllocationsReducer = (
|
|
125
|
+
acc: ProductPlanEntity[],
|
|
126
|
+
cur: ShopifySellingPlanAllocationsEntity,
|
|
127
|
+
sellingPlans: ShopifySellingPlansEntity[] = [],
|
|
128
|
+
currency: string
|
|
129
|
+
) => [...acc, mapSellingPlanToDiscount(cur, sellingPlans, currency)];
|
|
126
130
|
|
|
127
131
|
export const getSellingPlans = (product: ShopifyProductEntity) =>
|
|
128
|
-
product.selling_plan_groups.reduce(
|
|
132
|
+
product.selling_plan_groups.reduce<ShopifySellingPlansEntity[]>(
|
|
129
133
|
(allGroups, group) => [
|
|
130
134
|
...allGroups,
|
|
131
135
|
...group.selling_plans.map(selling_plan => ({ ...selling_plan, group_name: group.name }))
|
|
@@ -45,7 +45,15 @@ declare global {
|
|
|
45
45
|
previewMode: boolean;
|
|
46
46
|
};
|
|
47
47
|
ogShopifyConfig: OgShopifyConfig;
|
|
48
|
-
Shopify
|
|
48
|
+
Shopify?: {
|
|
49
|
+
routes?: {
|
|
50
|
+
root: string;
|
|
51
|
+
};
|
|
52
|
+
currency?: {
|
|
53
|
+
active: string;
|
|
54
|
+
rate: string;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
49
57
|
}
|
|
50
58
|
}
|
|
51
59
|
|
|
@@ -17,12 +17,22 @@ import {
|
|
|
17
17
|
import { makeSubscribedSelector } from '../core/selectors';
|
|
18
18
|
import { getOrCreateHidden, safeProductId } from '../core/utils';
|
|
19
19
|
import { getTrackingKey } from './shopifyTrackingMiddleware';
|
|
20
|
+
import { ShopifyCart, ShopifyProductEntity } from './types/shopify';
|
|
20
21
|
|
|
21
22
|
const SHOPIFY_ROOT = window.Shopify?.routes?.root || '/';
|
|
22
23
|
const CART_PAGE_URL = '/cart';
|
|
23
24
|
const CART_JS_URL = `${SHOPIFY_ROOT}cart.js`;
|
|
25
|
+
const CART_CHANGE_URL = `${SHOPIFY_ROOT}cart/change.js`;
|
|
24
26
|
const PRODUCTS_URL = `${SHOPIFY_ROOT}products/`;
|
|
25
27
|
|
|
28
|
+
type SetupProductPayload = {
|
|
29
|
+
product: ShopifyProductEntity;
|
|
30
|
+
offer: any;
|
|
31
|
+
currency: string;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
type SetupCartPayload = ShopifyCart;
|
|
35
|
+
|
|
26
36
|
/**
|
|
27
37
|
* List of section DOM elements to update via section-rendering api https://shopify.dev/api/section-rendering
|
|
28
38
|
*/
|
|
@@ -38,12 +48,22 @@ const makeSyncProductId = offer =>
|
|
|
38
48
|
}
|
|
39
49
|
});
|
|
40
50
|
|
|
51
|
+
async function getCurrency() {
|
|
52
|
+
const windowCurrency = window.Shopify?.currency?.active;
|
|
53
|
+
if (windowCurrency) {
|
|
54
|
+
return windowCurrency;
|
|
55
|
+
}
|
|
56
|
+
const cart = await getCart();
|
|
57
|
+
return cart.currency;
|
|
58
|
+
}
|
|
59
|
+
|
|
41
60
|
async function setupPdp(store, offer) {
|
|
42
61
|
const handle = guessProductHandle(offer);
|
|
43
62
|
if (handle) {
|
|
44
63
|
try {
|
|
45
|
-
const product = await getProduct(handle);
|
|
46
|
-
|
|
64
|
+
const [product, currency] = await Promise.all([getProduct(handle), getCurrency()]);
|
|
65
|
+
const payload: SetupProductPayload = { product, offer, currency: currency };
|
|
66
|
+
store.dispatch({ type: SETUP_PRODUCT, payload });
|
|
47
67
|
} catch (err) {
|
|
48
68
|
console.warn('OG: Unable to fetch product details for PDP', err);
|
|
49
69
|
}
|
|
@@ -79,7 +99,9 @@ async function setupPdp(store, offer) {
|
|
|
79
99
|
}
|
|
80
100
|
}
|
|
81
101
|
|
|
82
|
-
|
|
102
|
+
async function getCart(): Promise<ShopifyCart> {
|
|
103
|
+
return (await fetch(CART_JS_URL)).json();
|
|
104
|
+
}
|
|
83
105
|
|
|
84
106
|
/**
|
|
85
107
|
* Attemps to guess the product handle o
|
|
@@ -120,12 +142,15 @@ export function guessProductHandle(offer): string {
|
|
|
120
142
|
);
|
|
121
143
|
}
|
|
122
144
|
|
|
123
|
-
const getProduct = memoize(async handle
|
|
145
|
+
const getProduct = memoize(async function(handle: string): Promise<ShopifyProductEntity> {
|
|
146
|
+
return (await fetch(`${PRODUCTS_URL}${handle}.js`)).json();
|
|
147
|
+
});
|
|
124
148
|
|
|
125
149
|
async function setupCart(store, offer) {
|
|
126
150
|
const cart = await getCart();
|
|
127
151
|
const { items } = cart;
|
|
128
|
-
|
|
152
|
+
const cartPayload: SetupCartPayload = cart;
|
|
153
|
+
store.dispatch({ type: SETUP_CART, payload: cartPayload });
|
|
129
154
|
|
|
130
155
|
// some minicart templates does not contains line.key but contains line which corresponds to
|
|
131
156
|
// the index on the cart items (Vedge)
|
|
@@ -136,7 +161,10 @@ async function setupCart(store, offer) {
|
|
|
136
161
|
}
|
|
137
162
|
|
|
138
163
|
const products = await Promise.all(Array.from(new Set(items.map(({ handle }) => handle))).map(getProduct));
|
|
139
|
-
products.forEach(product =>
|
|
164
|
+
products.forEach(product => {
|
|
165
|
+
const payload: SetupProductPayload = { product, offer, currency: cart.currency };
|
|
166
|
+
store.dispatch({ type: SETUP_PRODUCT, payload });
|
|
167
|
+
});
|
|
140
168
|
}
|
|
141
169
|
|
|
142
170
|
/**
|
|
@@ -168,7 +196,7 @@ export async function synchronizeCartOptin(action: any, store: any) {
|
|
|
168
196
|
const qty = item.quantity;
|
|
169
197
|
const productId = safeProductId(key);
|
|
170
198
|
|
|
171
|
-
const res = await fetch(
|
|
199
|
+
const res = await fetch(CART_CHANGE_URL, {
|
|
172
200
|
method: 'POST',
|
|
173
201
|
credentials: 'same-origin',
|
|
174
202
|
headers: { 'Content-Type': 'application/json' },
|
|
@@ -184,7 +212,7 @@ export async function synchronizeCartOptin(action: any, store: any) {
|
|
|
184
212
|
|
|
185
213
|
if (res.status !== 200) throw new Error('Cart not updated');
|
|
186
214
|
|
|
187
|
-
const newCart = await res.json();
|
|
215
|
+
const newCart: ShopifyCart = await res.json();
|
|
188
216
|
|
|
189
217
|
// If both carts have same length we can update the item.key
|
|
190
218
|
// to the original offer element, at least provide
|
|
@@ -213,7 +241,8 @@ export async function synchronizeCartOptin(action: any, store: any) {
|
|
|
213
241
|
}
|
|
214
242
|
|
|
215
243
|
// dispatch SETUP_CART so offer does not flip the state
|
|
216
|
-
|
|
244
|
+
const newCartPayload: SetupCartPayload = newCart;
|
|
245
|
+
store.dispatch({ type: SETUP_CART, payload: newCartPayload });
|
|
217
246
|
|
|
218
247
|
// Use a custom event to hook custom cart updates.
|
|
219
248
|
const cartUpdateEvent = new CustomEvent(CART_UPDATED_EVENT, { bubbles: true, cancelable: true });
|
|
@@ -440,7 +440,7 @@ export const productOffer = (state = {}, _action) => state;
|
|
|
440
440
|
export const productPlans = (state = {}, action) => {
|
|
441
441
|
if (constants.SETUP_PRODUCT === action.type) {
|
|
442
442
|
const {
|
|
443
|
-
payload: { product }
|
|
443
|
+
payload: { product, currency }
|
|
444
444
|
} = action;
|
|
445
445
|
|
|
446
446
|
const sellingPlans = getSellingPlans(product);
|
|
@@ -451,7 +451,7 @@ export const productPlans = (state = {}, action) => {
|
|
|
451
451
|
(acc, cur) => ({
|
|
452
452
|
...acc,
|
|
453
453
|
[cur.id]: cur.selling_plan_allocations?.reduce(
|
|
454
|
-
(accumulator, current) => sellingPlanAllocationsReducer(accumulator, current, sellingPlans),
|
|
454
|
+
(accumulator, current) => sellingPlanAllocationsReducer(accumulator, current, sellingPlans, currency),
|
|
455
455
|
[]
|
|
456
456
|
)
|
|
457
457
|
}),
|
|
@@ -467,7 +467,7 @@ export const productPlans = (state = {}, action) => {
|
|
|
467
467
|
cur.selling_plan_allocation
|
|
468
468
|
? {
|
|
469
469
|
...acc,
|
|
470
|
-
[cur.key]: sellingPlanAllocationsReducer([], cur.selling_plan_allocation)
|
|
470
|
+
[cur.key]: sellingPlanAllocationsReducer([], cur.selling_plan_allocation, [], cart.currency)
|
|
471
471
|
}
|
|
472
472
|
: acc,
|
|
473
473
|
state
|
|
@@ -96,3 +96,136 @@ export interface ShopifyProductEntity {
|
|
|
96
96
|
requires_selling_plan: boolean;
|
|
97
97
|
selling_plan_groups?: ShopifySellingPlanGroupsEntity[] | null;
|
|
98
98
|
}
|
|
99
|
+
|
|
100
|
+
export interface ShopifyCart {
|
|
101
|
+
token: string;
|
|
102
|
+
note: string;
|
|
103
|
+
attributes: Record<string, string>;
|
|
104
|
+
original_total_price: number;
|
|
105
|
+
total_price: number;
|
|
106
|
+
total_discount: number;
|
|
107
|
+
total_weight: number;
|
|
108
|
+
item_count: number;
|
|
109
|
+
items: CartItem[];
|
|
110
|
+
requires_shipping: boolean;
|
|
111
|
+
currency: string;
|
|
112
|
+
items_subtotal_price: number;
|
|
113
|
+
cart_level_discount_applications: CartLevelDiscountApplication[];
|
|
114
|
+
sections?: Record<string, string>;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
interface CartItem {
|
|
118
|
+
id: number;
|
|
119
|
+
properties: Record<string, string>;
|
|
120
|
+
quantity: number;
|
|
121
|
+
variant_id: number;
|
|
122
|
+
key: string;
|
|
123
|
+
title: string;
|
|
124
|
+
price: number;
|
|
125
|
+
original_price: number;
|
|
126
|
+
discounted_price: number;
|
|
127
|
+
line_price: number;
|
|
128
|
+
original_line_price: number;
|
|
129
|
+
total_discount: number;
|
|
130
|
+
discounts: Discount[];
|
|
131
|
+
sku: string;
|
|
132
|
+
grams: number;
|
|
133
|
+
vendor: string;
|
|
134
|
+
taxable: boolean;
|
|
135
|
+
product_id: number;
|
|
136
|
+
product_has_only_default_variant: boolean;
|
|
137
|
+
gift_card: boolean;
|
|
138
|
+
final_price: number;
|
|
139
|
+
final_line_price: number;
|
|
140
|
+
url: string;
|
|
141
|
+
featured_image: FeaturedImage;
|
|
142
|
+
image: string;
|
|
143
|
+
handle: string;
|
|
144
|
+
requires_shipping: boolean;
|
|
145
|
+
product_type: string;
|
|
146
|
+
product_title: string;
|
|
147
|
+
product_description: string;
|
|
148
|
+
variant_title?: string;
|
|
149
|
+
variant_options: string[];
|
|
150
|
+
options_with_values: OptionsWithValue[];
|
|
151
|
+
line_level_discount_allocations: LineLevelDiscountAllocation[];
|
|
152
|
+
line_level_total_discount: number;
|
|
153
|
+
quantity_rule: QuantityRule;
|
|
154
|
+
has_components: boolean;
|
|
155
|
+
selling_plan_allocation?: SellingPlanAllocation;
|
|
156
|
+
unit_price?: number;
|
|
157
|
+
unit_price_measurement?: UnitPriceMeasurement;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
interface Discount {
|
|
161
|
+
amount: number;
|
|
162
|
+
title: string;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
interface FeaturedImage {
|
|
166
|
+
aspect_ratio: number;
|
|
167
|
+
alt: string;
|
|
168
|
+
height: number;
|
|
169
|
+
url: string;
|
|
170
|
+
width: number;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
interface OptionsWithValue {
|
|
174
|
+
name: string;
|
|
175
|
+
value: string;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
interface LineLevelDiscountAllocation {
|
|
179
|
+
amount: number;
|
|
180
|
+
discount_application: DiscountApplication;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
interface DiscountApplication {
|
|
184
|
+
type: string;
|
|
185
|
+
key: string;
|
|
186
|
+
title: string;
|
|
187
|
+
description: string;
|
|
188
|
+
value: string;
|
|
189
|
+
created_at: string;
|
|
190
|
+
value_type: string;
|
|
191
|
+
allocation_method: string;
|
|
192
|
+
target_selection: string;
|
|
193
|
+
target_type: string;
|
|
194
|
+
total_allocated_amount: number;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
interface QuantityRule {
|
|
198
|
+
min: number;
|
|
199
|
+
max?: number;
|
|
200
|
+
increment: number;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
interface SellingPlanAllocation {
|
|
204
|
+
price_adjustments: ShopifyPriceAdjustmentsEntity[];
|
|
205
|
+
price: number;
|
|
206
|
+
compare_at_price: number;
|
|
207
|
+
per_delivery_price: number;
|
|
208
|
+
selling_plan: ShopifySellingPlansEntity;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
interface UnitPriceMeasurement {
|
|
212
|
+
measured_type: string;
|
|
213
|
+
quantity_value: string;
|
|
214
|
+
quantity_unit: string;
|
|
215
|
+
reference_value: number;
|
|
216
|
+
reference_unit: string;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
interface CartLevelDiscountApplication {
|
|
220
|
+
type: string;
|
|
221
|
+
key: string;
|
|
222
|
+
title: string;
|
|
223
|
+
description: string;
|
|
224
|
+
value: string;
|
|
225
|
+
created_at: string;
|
|
226
|
+
value_type: string;
|
|
227
|
+
allocation_method: string;
|
|
228
|
+
target_selection: string;
|
|
229
|
+
target_type: string;
|
|
230
|
+
total_allocated_amount: number;
|
|
231
|
+
}
|
package/src/shopify/utils.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
export const money =
|
|
1
|
+
export const money = (val: number, currency: string) =>
|
|
2
|
+
val === null
|
|
3
|
+
? ''
|
|
4
|
+
: new Intl.NumberFormat(navigator.language, {
|
|
5
|
+
style: 'currency',
|
|
6
|
+
currency
|
|
7
|
+
}).format(val / 100);
|
|
2
8
|
|
|
3
9
|
export const percentage = val => `${val}%`;
|