@juo/blocks 1.12.0-alpha.1 → 1.12.0-alpha.3
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/dist/{ExtensionRoot-Z2DlF9X6.js → ExtensionRoot-peABLAZZ.js} +3 -2
- package/dist/{block-Bh3z0B3y.js → block-B6s9jL7l.js} +37 -42
- package/dist/block.d.ts +1 -1
- package/dist/block.d.ts.map +1 -1
- package/dist/{bridge-w5KQ-czl.js → bridge-r7Yk8fjY.js} +34 -25
- package/dist/core.js +669 -460
- package/dist/devtools/env.d.ts +3 -0
- package/dist/devtools/env.d.ts.map +1 -0
- package/dist/devtools/hook.d.ts +35 -0
- package/dist/devtools/hook.d.ts.map +1 -0
- package/dist/devtools/index.d.ts +4 -0
- package/dist/devtools/index.d.ts.map +1 -0
- package/dist/devtools/protocol.d.ts +91 -0
- package/dist/devtools/protocol.d.ts.map +1 -0
- package/dist/devtools.js +44 -0
- package/dist/editor/bridge.d.ts +7 -0
- package/dist/editor/bridge.d.ts.map +1 -1
- package/dist/editor/components.d.ts.map +1 -1
- package/dist/editor/main.d.ts +2 -1
- package/dist/editor/main.d.ts.map +1 -1
- package/dist/editor/messages.d.ts +13 -2
- package/dist/editor/messages.d.ts.map +1 -1
- package/dist/editor/messages.test.d.ts +2 -0
- package/dist/editor/messages.test.d.ts.map +1 -0
- package/dist/editor/overlays.d.ts +14 -0
- package/dist/editor/overlays.d.ts.map +1 -0
- package/dist/editor/overlays.test.d.ts +2 -0
- package/dist/editor/overlays.test.d.ts.map +1 -0
- package/dist/editor.js +63 -45
- package/dist/{juo-workflow-D3c29mxb.js → juo-workflow-DY4rd256.js} +29 -9
- package/dist/main.d.ts +1 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/overlay-wrapper.d.ts +1 -0
- package/dist/overlay-wrapper.d.ts.map +1 -1
- package/dist/overlay-wrapper.test.d.ts +2 -0
- package/dist/overlay-wrapper.test.d.ts.map +1 -0
- package/dist/overlays/OverlayService.d.ts +34 -0
- package/dist/overlays/OverlayService.d.ts.map +1 -0
- package/dist/overlays/OverlayService.test.d.ts +2 -0
- package/dist/overlays/OverlayService.test.d.ts.map +1 -0
- package/dist/preact.js +1 -1
- package/dist/react.js +1 -1
- package/dist/services/product/adapter.d.ts.map +1 -1
- package/dist/services/schedules/adapter.d.ts +23 -1
- package/dist/services/schedules/adapter.d.ts.map +1 -1
- package/dist/services/subscription/adapter.d.ts +18 -0
- package/dist/services/subscription/adapter.d.ts.map +1 -1
- package/dist/services/subscription/subscriptionService.d.ts.map +1 -1
- package/dist/services/subscription/types.d.ts +38 -0
- package/dist/services/subscription/types.d.ts.map +1 -1
- package/dist/theme-state.d.ts.map +1 -1
- package/dist/vue.js +3 -2
- package/dist/web-components-editor.js +4 -4
- package/dist/web-components-runtime.js +3 -3
- package/package.json +6 -3
package/dist/core.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
-
import {
|
|
5
|
-
import { B,
|
|
6
|
-
import { D as D2,
|
|
4
|
+
import { e as createContext, d, k as w, l as defineBlock, g as createBlockInstance, h as getDefinedBlocks, r as registerBlock, E, u } from "./block-B6s9jL7l.js";
|
|
5
|
+
import { B, m, p, S, q, _, t, b, v, f, x, y, z, A, D, i, F, a, o, G, j, H, s, n, w as w2 } from "./block-B6s9jL7l.js";
|
|
6
|
+
import { D as D2, a as a2, T, W, c, b as b2, d as d2, e, g, h, i as i2 } from "./juo-workflow-DY4rd256.js";
|
|
7
7
|
import { reportBlockWarning, reportBlockError } from "./observability.js";
|
|
8
8
|
function createState() {
|
|
9
9
|
const discountCode = d(null);
|
|
@@ -105,6 +105,7 @@ function defineOverlayWrapper(opts) {
|
|
|
105
105
|
const layout = opts.layout ?? "sidebar";
|
|
106
106
|
const canAbort = opts.canAbort ?? true;
|
|
107
107
|
return defineBlock(opts.name, {
|
|
108
|
+
displayName: opts.title,
|
|
108
109
|
group: "internal",
|
|
109
110
|
schema: OVERLAY_WRAPPER_SCHEMA,
|
|
110
111
|
initialValue: () => ({
|
|
@@ -116,6 +117,67 @@ function defineOverlayWrapper(opts) {
|
|
|
116
117
|
renderer: () => null
|
|
117
118
|
});
|
|
118
119
|
}
|
|
120
|
+
const OVERLAY_PREFIX$1 = "overlay:";
|
|
121
|
+
function callInitialValue(block) {
|
|
122
|
+
if (typeof block.initialValue !== "function") return block.initialValue;
|
|
123
|
+
try {
|
|
124
|
+
return block.initialValue();
|
|
125
|
+
} catch (error) {
|
|
126
|
+
console.warn(
|
|
127
|
+
`[overlays] initialValue() threw for "${block.name}"; its content block will not be hidden from the palette.`,
|
|
128
|
+
error
|
|
129
|
+
);
|
|
130
|
+
return void 0;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function buildOverlayRegistry(blocks) {
|
|
134
|
+
var _a, _b;
|
|
135
|
+
const registry = {};
|
|
136
|
+
for (const block of blocks) {
|
|
137
|
+
if (!block.name.startsWith(OVERLAY_PREFIX$1)) continue;
|
|
138
|
+
const id = block.name.slice(OVERLAY_PREFIX$1.length);
|
|
139
|
+
const initial = callInitialValue(block);
|
|
140
|
+
const first = (_b = (_a = initial == null ? void 0 : initial.slots) == null ? void 0 : _a.content) == null ? void 0 : _b[0];
|
|
141
|
+
const contentBlock = typeof (first == null ? void 0 : first.type) === "string" ? first.type : "";
|
|
142
|
+
registry[id] = {
|
|
143
|
+
block: block.name,
|
|
144
|
+
title: block.displayName ?? id,
|
|
145
|
+
contentBlock
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
return registry;
|
|
149
|
+
}
|
|
150
|
+
const OVERLAY_PREFIX = "overlay:";
|
|
151
|
+
const OverlayServiceContext = createContext("services/overlay");
|
|
152
|
+
function createOverlayService(themeState, options = {}) {
|
|
153
|
+
const getBlocks = options.getBlocks ?? getDefinedBlocks;
|
|
154
|
+
const current = w(() => {
|
|
155
|
+
const root = themeState.overlay.blocks.value[0];
|
|
156
|
+
const type = root == null ? void 0 : root.type;
|
|
157
|
+
if (typeof type !== "string" || !type.startsWith(OVERLAY_PREFIX)) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
const props = root.props ?? {};
|
|
161
|
+
return {
|
|
162
|
+
name: type,
|
|
163
|
+
// Defaults mirror defineOverlayWrapper's seeding in overlay-wrapper.ts — keep in sync.
|
|
164
|
+
layout: props.layout ?? "sidebar",
|
|
165
|
+
canAbort: Boolean(props.canAbort ?? true)
|
|
166
|
+
};
|
|
167
|
+
});
|
|
168
|
+
return {
|
|
169
|
+
getEditableOverlays() {
|
|
170
|
+
return buildOverlayRegistry(getBlocks());
|
|
171
|
+
},
|
|
172
|
+
open(name, params) {
|
|
173
|
+
void themeState.resolve("overlay", name, params);
|
|
174
|
+
},
|
|
175
|
+
close() {
|
|
176
|
+
themeState.overlay.blocks.value = [];
|
|
177
|
+
},
|
|
178
|
+
current
|
|
179
|
+
};
|
|
180
|
+
}
|
|
119
181
|
function isLocalhostOrigin(origin) {
|
|
120
182
|
try {
|
|
121
183
|
const url = new URL(origin);
|
|
@@ -231,8 +293,8 @@ function createApiCustomerAdapter(fetcher) {
|
|
|
231
293
|
_tag: "Success",
|
|
232
294
|
data: { id: data.id, name, email: data.email }
|
|
233
295
|
};
|
|
234
|
-
} catch (
|
|
235
|
-
return { _tag: "Failure", error:
|
|
296
|
+
} catch (e2) {
|
|
297
|
+
return { _tag: "Failure", error: e2 };
|
|
236
298
|
}
|
|
237
299
|
}
|
|
238
300
|
};
|
|
@@ -320,8 +382,8 @@ function createApiLoginAdapter(fetcher, opts) {
|
|
|
320
382
|
lang
|
|
321
383
|
);
|
|
322
384
|
return { _tag: "Success", data: void 0 };
|
|
323
|
-
} catch (
|
|
324
|
-
return { _tag: "Failure", error:
|
|
385
|
+
} catch (e2) {
|
|
386
|
+
return { _tag: "Failure", error: e2 };
|
|
325
387
|
}
|
|
326
388
|
},
|
|
327
389
|
async authenticate(params) {
|
|
@@ -355,8 +417,8 @@ function createApiLoginAdapter(fetcher, opts) {
|
|
|
355
417
|
throw new Error(`Unexpected response: ${res.statusText}`);
|
|
356
418
|
}
|
|
357
419
|
return { _tag: "Success", data: await res.json() };
|
|
358
|
-
} catch (
|
|
359
|
-
return { _tag: "Failure", error:
|
|
420
|
+
} catch (e2) {
|
|
421
|
+
return { _tag: "Failure", error: e2 };
|
|
360
422
|
}
|
|
361
423
|
},
|
|
362
424
|
getAuthorizeUrl({ connection, state, shop }) {
|
|
@@ -699,7 +761,7 @@ function createMockProductAdapter() {
|
|
|
699
761
|
id: "sample-1",
|
|
700
762
|
title: "Hydrating Gel Cleanser for Face and Eye Area",
|
|
701
763
|
featuredImage: {
|
|
702
|
-
url: "https://
|
|
764
|
+
url: "https://placehold.co/400x400?text=Product+1"
|
|
703
765
|
},
|
|
704
766
|
hasOnlyDefaultVariant: true,
|
|
705
767
|
variants: [
|
|
@@ -707,7 +769,7 @@ function createMockProductAdapter() {
|
|
|
707
769
|
id: "sample-1-1",
|
|
708
770
|
title: "150 ml bottle",
|
|
709
771
|
image: {
|
|
710
|
-
url: "https://
|
|
772
|
+
url: "https://placehold.co/400x400?text=Product+1"
|
|
711
773
|
},
|
|
712
774
|
price: {
|
|
713
775
|
amount: "12.49",
|
|
@@ -733,7 +795,7 @@ function createMockProductAdapter() {
|
|
|
733
795
|
id: "sample-2",
|
|
734
796
|
title: "More COLLAGEN",
|
|
735
797
|
featuredImage: {
|
|
736
|
-
url: "https://
|
|
798
|
+
url: "https://placehold.co/400x400?text=Product+2"
|
|
737
799
|
},
|
|
738
800
|
hasOnlyDefaultVariant: true,
|
|
739
801
|
variants: [
|
|
@@ -741,7 +803,7 @@ function createMockProductAdapter() {
|
|
|
741
803
|
id: "sample-2-1",
|
|
742
804
|
title: "blackcurrant",
|
|
743
805
|
image: {
|
|
744
|
-
url: "https://
|
|
806
|
+
url: "https://placehold.co/400x400?text=Product+2"
|
|
745
807
|
},
|
|
746
808
|
price: {
|
|
747
809
|
amount: "12.49",
|
|
@@ -762,7 +824,7 @@ function createMockProductAdapter() {
|
|
|
762
824
|
id: "sample-3",
|
|
763
825
|
title: "Gentle deodorant for underarms and bust",
|
|
764
826
|
featuredImage: {
|
|
765
|
-
url: "https://
|
|
827
|
+
url: "https://placehold.co/400x400?text=Product+3"
|
|
766
828
|
},
|
|
767
829
|
hasOnlyDefaultVariant: false,
|
|
768
830
|
variants: [
|
|
@@ -770,7 +832,7 @@ function createMockProductAdapter() {
|
|
|
770
832
|
id: "sample-3-1",
|
|
771
833
|
title: "Green tea and jasmine",
|
|
772
834
|
image: {
|
|
773
|
-
url: "https://
|
|
835
|
+
url: "https://placehold.co/400x400?text=Product+3a"
|
|
774
836
|
},
|
|
775
837
|
price: {
|
|
776
838
|
amount: "6.7",
|
|
@@ -788,7 +850,7 @@ function createMockProductAdapter() {
|
|
|
788
850
|
id: "sample-3-2",
|
|
789
851
|
title: "Lavender and mint",
|
|
790
852
|
image: {
|
|
791
|
-
url: "https://
|
|
853
|
+
url: "https://placehold.co/400x400?text=Product+3b"
|
|
792
854
|
},
|
|
793
855
|
price: {
|
|
794
856
|
amount: "7.5",
|
|
@@ -820,6 +882,48 @@ function createMockProductAdapter() {
|
|
|
820
882
|
}
|
|
821
883
|
};
|
|
822
884
|
}
|
|
885
|
+
function toAvailableProduct(product) {
|
|
886
|
+
return {
|
|
887
|
+
id: product.id,
|
|
888
|
+
title: product.title,
|
|
889
|
+
description: `Sample description for ${product.title}.`,
|
|
890
|
+
featuredImage: product.featuredImage ?? void 0,
|
|
891
|
+
hasOnlyDefaultVariant: product.hasOnlyDefaultVariant,
|
|
892
|
+
variants: product.variants.map((variant) => {
|
|
893
|
+
var _a, _b, _c;
|
|
894
|
+
const base = Number.parseFloat(variant.price.amount);
|
|
895
|
+
const sub = (_b = (_a = variant.purchaseOptions) == null ? void 0 : _a[0]) == null ? void 0 : _b.price.amount;
|
|
896
|
+
const current = sub == null ? base : Number.parseFloat(sub);
|
|
897
|
+
return {
|
|
898
|
+
id: variant.id,
|
|
899
|
+
availableForSale: true,
|
|
900
|
+
title: variant.title,
|
|
901
|
+
currentPrice: { amount: current, currencyCode: variant.price.currencyCode },
|
|
902
|
+
basePrice: { amount: base, currencyCode: variant.price.currencyCode },
|
|
903
|
+
image: variant.image ?? void 0,
|
|
904
|
+
recurring: (((_c = variant.purchaseOptions) == null ? void 0 : _c.length) ?? 0) > 0
|
|
905
|
+
};
|
|
906
|
+
})
|
|
907
|
+
};
|
|
908
|
+
}
|
|
909
|
+
const sampleBox = {
|
|
910
|
+
id: "sample-box-1",
|
|
911
|
+
title: "Build Your Own Box",
|
|
912
|
+
minProductsCount: 3,
|
|
913
|
+
parentProduct: "sample-1",
|
|
914
|
+
tiers: [
|
|
915
|
+
{ value: 5, threshold: 3 },
|
|
916
|
+
{ value: 10, threshold: 5 }
|
|
917
|
+
],
|
|
918
|
+
variants: products.map((product) => ({
|
|
919
|
+
id: product.id,
|
|
920
|
+
variants: product.variants.map((variant) => ({ id: variant.id }))
|
|
921
|
+
})),
|
|
922
|
+
freeVariants: [],
|
|
923
|
+
thresholdType: "LINES_COUNT",
|
|
924
|
+
type: "PERCENTAGE",
|
|
925
|
+
restrictQuantityToTiers: false
|
|
926
|
+
};
|
|
823
927
|
return {
|
|
824
928
|
async getById(id) {
|
|
825
929
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
@@ -833,17 +937,26 @@ function createMockProductAdapter() {
|
|
|
833
937
|
);
|
|
834
938
|
return product == null ? null : processProduct(product);
|
|
835
939
|
},
|
|
836
|
-
async getProductsByIds() {
|
|
837
|
-
|
|
940
|
+
async getProductsByIds({ ids }) {
|
|
941
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
942
|
+
return products.filter((product) => ids.includes(product.id)).map(({ variants: _variants, ...product }) => product);
|
|
838
943
|
},
|
|
839
|
-
async getBoxVariants() {
|
|
840
|
-
|
|
944
|
+
async getBoxVariants({ ids }) {
|
|
945
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
946
|
+
return products.filter((product) => ids.includes(product.id)).map(toAvailableProduct);
|
|
841
947
|
},
|
|
842
|
-
async getAvailableProducts() {
|
|
843
|
-
|
|
948
|
+
async getAvailableProducts({ q: q2 }) {
|
|
949
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
950
|
+
const queryLower = q2 == null ? void 0 : q2.toLowerCase();
|
|
951
|
+
return products.filter(
|
|
952
|
+
(product) => !queryLower || product.title.toLowerCase().includes(queryLower) || product.variants.some(
|
|
953
|
+
(variant) => variant.title.toLowerCase().includes(queryLower)
|
|
954
|
+
)
|
|
955
|
+
).map(toAvailableProduct);
|
|
844
956
|
},
|
|
845
|
-
async getBox() {
|
|
846
|
-
|
|
957
|
+
async getBox({ id }) {
|
|
958
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
959
|
+
return id === sampleBox.id ? sampleBox : null;
|
|
847
960
|
},
|
|
848
961
|
async search(opts) {
|
|
849
962
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
@@ -1133,347 +1246,6 @@ function createMockRouterService() {
|
|
|
1133
1246
|
}
|
|
1134
1247
|
}).routerService;
|
|
1135
1248
|
}
|
|
1136
|
-
function futureDateStr(daysFromNow) {
|
|
1137
|
-
const d3 = /* @__PURE__ */ new Date();
|
|
1138
|
-
d3.setDate(d3.getDate() + daysFromNow);
|
|
1139
|
-
return d3.toISOString().split("T")[0] ?? "";
|
|
1140
|
-
}
|
|
1141
|
-
function createMockSchedulesAdapter() {
|
|
1142
|
-
let orders = [
|
|
1143
|
-
{
|
|
1144
|
-
id: "sched_1",
|
|
1145
|
-
customerId: "customer_1",
|
|
1146
|
-
subscriptionId: "sub_1",
|
|
1147
|
-
date: "2026-05-22T12:00:00Z",
|
|
1148
|
-
skipped: false,
|
|
1149
|
-
currencyCode: "USD",
|
|
1150
|
-
subtotal: 2999,
|
|
1151
|
-
deliveryPrice: 500,
|
|
1152
|
-
cycleIndex: 4,
|
|
1153
|
-
deliveryDate: futureDateStr(7),
|
|
1154
|
-
status: "scheduled",
|
|
1155
|
-
items: [
|
|
1156
|
-
{
|
|
1157
|
-
id: "sched_item_1",
|
|
1158
|
-
title: "Rose Face Serum",
|
|
1159
|
-
subtitle: null,
|
|
1160
|
-
imageUrl: "https://images.unsplash.com/photo-1611930022073-b7a4ba5fcccd?w=200",
|
|
1161
|
-
variantId: "variant_1",
|
|
1162
|
-
quantity: 1,
|
|
1163
|
-
price: 2999,
|
|
1164
|
-
totalPrice: 2999,
|
|
1165
|
-
variantImage: null,
|
|
1166
|
-
variantAvailableForSale: true,
|
|
1167
|
-
subscriptionId: "sub_1",
|
|
1168
|
-
subscriptionLineId: "item_1",
|
|
1169
|
-
productId: "product_1",
|
|
1170
|
-
parentProductId: null,
|
|
1171
|
-
parentLineId: null,
|
|
1172
|
-
isVirtual: false,
|
|
1173
|
-
isUpsell: false,
|
|
1174
|
-
isOneTime: false,
|
|
1175
|
-
customAttributes: []
|
|
1176
|
-
},
|
|
1177
|
-
{
|
|
1178
|
-
id: "sched_item_2",
|
|
1179
|
-
title: "Vitamin C Moisturizer",
|
|
1180
|
-
subtitle: null,
|
|
1181
|
-
imageUrl: "https://images.unsplash.com/photo-1556228578-8c89e6adf883?w=200",
|
|
1182
|
-
variantId: "variant_2",
|
|
1183
|
-
quantity: 1,
|
|
1184
|
-
price: 2999,
|
|
1185
|
-
totalPrice: 2999,
|
|
1186
|
-
variantImage: null,
|
|
1187
|
-
variantAvailableForSale: true,
|
|
1188
|
-
subscriptionId: "sub_1",
|
|
1189
|
-
subscriptionLineId: "item_2",
|
|
1190
|
-
productId: "product_2",
|
|
1191
|
-
parentProductId: null,
|
|
1192
|
-
parentLineId: null,
|
|
1193
|
-
isVirtual: false,
|
|
1194
|
-
isUpsell: false,
|
|
1195
|
-
isOneTime: false,
|
|
1196
|
-
customAttributes: []
|
|
1197
|
-
}
|
|
1198
|
-
],
|
|
1199
|
-
discounts: []
|
|
1200
|
-
},
|
|
1201
|
-
{
|
|
1202
|
-
id: "sched_2",
|
|
1203
|
-
customerId: "customer_1",
|
|
1204
|
-
subscriptionId: "sub_1",
|
|
1205
|
-
date: "2026-05-22T12:00:00Z",
|
|
1206
|
-
skipped: false,
|
|
1207
|
-
currencyCode: "USD",
|
|
1208
|
-
subtotal: 2999,
|
|
1209
|
-
deliveryPrice: 500,
|
|
1210
|
-
cycleIndex: 4,
|
|
1211
|
-
deliveryDate: futureDateStr(7),
|
|
1212
|
-
status: "scheduled",
|
|
1213
|
-
items: [
|
|
1214
|
-
{
|
|
1215
|
-
id: "sched_item_3",
|
|
1216
|
-
title: "Rose Face Serum",
|
|
1217
|
-
subtitle: null,
|
|
1218
|
-
imageUrl: "https://images.unsplash.com/photo-1611930022073-b7a4ba5fcccd?w=200",
|
|
1219
|
-
variantId: "variant_1",
|
|
1220
|
-
quantity: 1,
|
|
1221
|
-
price: 2999,
|
|
1222
|
-
totalPrice: 2999,
|
|
1223
|
-
variantImage: null,
|
|
1224
|
-
variantAvailableForSale: true,
|
|
1225
|
-
subscriptionId: "sub_1",
|
|
1226
|
-
subscriptionLineId: "item_1",
|
|
1227
|
-
productId: "product_1",
|
|
1228
|
-
parentProductId: null,
|
|
1229
|
-
parentLineId: null,
|
|
1230
|
-
isVirtual: false,
|
|
1231
|
-
isUpsell: false,
|
|
1232
|
-
isOneTime: false,
|
|
1233
|
-
customAttributes: []
|
|
1234
|
-
},
|
|
1235
|
-
{
|
|
1236
|
-
id: "sched_item_4",
|
|
1237
|
-
title: "Hyaluronic Acid Serum",
|
|
1238
|
-
subtitle: null,
|
|
1239
|
-
imageUrl: "https://images.unsplash.com/photo-1621232201696-ba6c9db10a97?w=200",
|
|
1240
|
-
variantId: "variant_3",
|
|
1241
|
-
quantity: 1,
|
|
1242
|
-
price: 2999,
|
|
1243
|
-
totalPrice: 2999,
|
|
1244
|
-
variantImage: null,
|
|
1245
|
-
variantAvailableForSale: true,
|
|
1246
|
-
subscriptionId: "sub_1",
|
|
1247
|
-
subscriptionLineId: "item_3",
|
|
1248
|
-
productId: "product_3",
|
|
1249
|
-
parentProductId: null,
|
|
1250
|
-
parentLineId: null,
|
|
1251
|
-
isVirtual: false,
|
|
1252
|
-
isUpsell: false,
|
|
1253
|
-
isOneTime: false,
|
|
1254
|
-
customAttributes: []
|
|
1255
|
-
}
|
|
1256
|
-
],
|
|
1257
|
-
discounts: []
|
|
1258
|
-
}
|
|
1259
|
-
];
|
|
1260
|
-
let adjustments = [];
|
|
1261
|
-
return {
|
|
1262
|
-
async getUpcomingOrders(params) {
|
|
1263
|
-
await new Promise((r) => setTimeout(r, 200));
|
|
1264
|
-
const filtered = params.subscriptionId ? orders.filter((o2) => o2.subscriptionId === params.subscriptionId) : orders;
|
|
1265
|
-
return { _tag: "Success", data: filtered.slice(0, params.count) };
|
|
1266
|
-
},
|
|
1267
|
-
async getAdjustments() {
|
|
1268
|
-
await new Promise((r) => setTimeout(r, 200));
|
|
1269
|
-
return { _tag: "Success", data: [...adjustments] };
|
|
1270
|
-
},
|
|
1271
|
-
async skipOrder({ subscriptionId }) {
|
|
1272
|
-
await new Promise((r) => setTimeout(r, 300));
|
|
1273
|
-
const order = orders.find(
|
|
1274
|
-
(o2) => o2.subscriptionId === subscriptionId && o2.status === "scheduled"
|
|
1275
|
-
);
|
|
1276
|
-
if (!order) return { _tag: "Failure", error: "No scheduled order found" };
|
|
1277
|
-
orders = orders.map(
|
|
1278
|
-
(o2) => o2.id === order.id ? { ...o2, status: "skipped" } : o2
|
|
1279
|
-
);
|
|
1280
|
-
const adj = {
|
|
1281
|
-
id: `adj-${Date.now()}`,
|
|
1282
|
-
subscriptionId,
|
|
1283
|
-
type: "skip"
|
|
1284
|
-
};
|
|
1285
|
-
adjustments = [...adjustments, adj];
|
|
1286
|
-
return { _tag: "Success", data: void 0 };
|
|
1287
|
-
},
|
|
1288
|
-
async changeDateAdjustment({ subscriptionId, newDate }) {
|
|
1289
|
-
await new Promise((r) => setTimeout(r, 300));
|
|
1290
|
-
const order = orders.find(
|
|
1291
|
-
(o2) => o2.subscriptionId === subscriptionId && o2.status === "scheduled"
|
|
1292
|
-
);
|
|
1293
|
-
if (!order) return { _tag: "Failure", error: "No scheduled order found" };
|
|
1294
|
-
orders = orders.map(
|
|
1295
|
-
(o2) => o2.id === order.id ? { ...o2, deliveryDate: newDate } : o2
|
|
1296
|
-
);
|
|
1297
|
-
const adj = {
|
|
1298
|
-
id: `adj-${Date.now()}`,
|
|
1299
|
-
subscriptionId,
|
|
1300
|
-
type: "date_change",
|
|
1301
|
-
newDate
|
|
1302
|
-
};
|
|
1303
|
-
adjustments = [...adjustments, adj];
|
|
1304
|
-
return { _tag: "Success", data: void 0 };
|
|
1305
|
-
},
|
|
1306
|
-
async removeAdjustment({ adjustmentId }) {
|
|
1307
|
-
await new Promise((r) => setTimeout(r, 200));
|
|
1308
|
-
adjustments = adjustments.filter((a2) => a2.id !== adjustmentId);
|
|
1309
|
-
return { _tag: "Success", data: void 0 };
|
|
1310
|
-
}
|
|
1311
|
-
};
|
|
1312
|
-
}
|
|
1313
|
-
function createApiSchedulesAdapter(fetcher) {
|
|
1314
|
-
return {
|
|
1315
|
-
async getUpcomingOrders({ count, subscriptionId }) {
|
|
1316
|
-
try {
|
|
1317
|
-
const params = new URLSearchParams({ count: String(count) });
|
|
1318
|
-
if (subscriptionId) params.set("query", `id:"${subscriptionId}"`);
|
|
1319
|
-
const res = await fetcher(`/customer/v1/schedules/?${params.toString()}`);
|
|
1320
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1321
|
-
const data = await res.json();
|
|
1322
|
-
return { _tag: "Success", data: data.orders };
|
|
1323
|
-
} catch (e3) {
|
|
1324
|
-
return { _tag: "Failure", error: e3 };
|
|
1325
|
-
}
|
|
1326
|
-
},
|
|
1327
|
-
async getAdjustments() {
|
|
1328
|
-
try {
|
|
1329
|
-
const res = await fetcher(`/customer/v1/schedules/adjustments`);
|
|
1330
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1331
|
-
const data = await res.json();
|
|
1332
|
-
const adjustments = data.data.map((a2) => ({
|
|
1333
|
-
id: a2.id,
|
|
1334
|
-
subscriptionId: a2.subscriptionId ?? "",
|
|
1335
|
-
type: a2.type === "CHANGE_DATE" ? "date_change" : "skip",
|
|
1336
|
-
newDate: a2.newDate
|
|
1337
|
-
}));
|
|
1338
|
-
return { _tag: "Success", data: adjustments };
|
|
1339
|
-
} catch (e3) {
|
|
1340
|
-
return { _tag: "Failure", error: e3 };
|
|
1341
|
-
}
|
|
1342
|
-
},
|
|
1343
|
-
async skipOrder({ cycle, date }) {
|
|
1344
|
-
if (cycle == null && date == null) {
|
|
1345
|
-
return { _tag: "Failure", error: "Either cycle or date is required for skipOrder" };
|
|
1346
|
-
}
|
|
1347
|
-
try {
|
|
1348
|
-
const matcher = cycle != null ? { type: "CYCLE", input: { cycle } } : { type: "DATE", input: { date: new Date(date).toISOString() } };
|
|
1349
|
-
const res = await fetcher(`/customer/v1/schedules/adjustments`, {
|
|
1350
|
-
method: "POST",
|
|
1351
|
-
headers: { "Content-Type": "application/json" },
|
|
1352
|
-
body: JSON.stringify({
|
|
1353
|
-
matcher,
|
|
1354
|
-
action: { type: "SKIP_ORDER", input: { reason: "" } }
|
|
1355
|
-
})
|
|
1356
|
-
});
|
|
1357
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1358
|
-
return { _tag: "Success", data: void 0 };
|
|
1359
|
-
} catch (e3) {
|
|
1360
|
-
return { _tag: "Failure", error: e3 };
|
|
1361
|
-
}
|
|
1362
|
-
},
|
|
1363
|
-
async changeDateAdjustment({ newDate, currentDate }) {
|
|
1364
|
-
if (currentDate == null) {
|
|
1365
|
-
return {
|
|
1366
|
-
_tag: "Failure",
|
|
1367
|
-
error: "currentDate is required for changeDateAdjustment"
|
|
1368
|
-
};
|
|
1369
|
-
}
|
|
1370
|
-
try {
|
|
1371
|
-
const matcher = { type: "DATE", input: { date: new Date(currentDate).toISOString() } };
|
|
1372
|
-
const res = await fetcher(`/customer/v1/schedules/adjustments`, {
|
|
1373
|
-
method: "POST",
|
|
1374
|
-
headers: { "Content-Type": "application/json" },
|
|
1375
|
-
body: JSON.stringify({
|
|
1376
|
-
matcher,
|
|
1377
|
-
action: {
|
|
1378
|
-
type: "CHANGE_DATE",
|
|
1379
|
-
input: { newDate: new Date(newDate).toISOString() }
|
|
1380
|
-
}
|
|
1381
|
-
})
|
|
1382
|
-
});
|
|
1383
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1384
|
-
return { _tag: "Success", data: void 0 };
|
|
1385
|
-
} catch (e3) {
|
|
1386
|
-
return { _tag: "Failure", error: e3 };
|
|
1387
|
-
}
|
|
1388
|
-
},
|
|
1389
|
-
async removeAdjustment({ adjustmentId }) {
|
|
1390
|
-
try {
|
|
1391
|
-
const res = await fetcher(
|
|
1392
|
-
`/customer/v1/schedules/adjustments/${adjustmentId}`,
|
|
1393
|
-
{ method: "DELETE" }
|
|
1394
|
-
);
|
|
1395
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1396
|
-
return { _tag: "Success", data: void 0 };
|
|
1397
|
-
} catch (e3) {
|
|
1398
|
-
return { _tag: "Failure", error: e3 };
|
|
1399
|
-
}
|
|
1400
|
-
}
|
|
1401
|
-
};
|
|
1402
|
-
}
|
|
1403
|
-
const SchedulesServiceContext = createContext("services/schedules");
|
|
1404
|
-
function createSchedulesService(adapter, opts) {
|
|
1405
|
-
const current = d(null);
|
|
1406
|
-
const currentLoading = d(false);
|
|
1407
|
-
const hasPendingBilling = (opts == null ? void 0 : opts.hasPendingBilling) ?? d(false);
|
|
1408
|
-
let reloadToken = 0;
|
|
1409
|
-
async function getUpcomingOrder() {
|
|
1410
|
-
const result = await adapter.getUpcomingOrders({ count: 1 });
|
|
1411
|
-
if (result._tag === "Failure") return result;
|
|
1412
|
-
return { _tag: "Success", data: result.data[0] ?? null };
|
|
1413
|
-
}
|
|
1414
|
-
async function getUpcomingOrders(count) {
|
|
1415
|
-
return adapter.getUpcomingOrders({ count });
|
|
1416
|
-
}
|
|
1417
|
-
async function reloadCurrent(subscriptionId) {
|
|
1418
|
-
var _a;
|
|
1419
|
-
const token = ++reloadToken;
|
|
1420
|
-
currentLoading.value = true;
|
|
1421
|
-
const count = Math.max(((_a = current.value) == null ? void 0 : _a.length) ?? 0, 3);
|
|
1422
|
-
const result = await adapter.getUpcomingOrders({
|
|
1423
|
-
count,
|
|
1424
|
-
subscriptionId
|
|
1425
|
-
});
|
|
1426
|
-
if (token !== reloadToken) return;
|
|
1427
|
-
currentLoading.value = false;
|
|
1428
|
-
if (result._tag === "Success") {
|
|
1429
|
-
current.value = result.data;
|
|
1430
|
-
}
|
|
1431
|
-
}
|
|
1432
|
-
return {
|
|
1433
|
-
current,
|
|
1434
|
-
currentLoading,
|
|
1435
|
-
hasPendingBilling,
|
|
1436
|
-
getUpcomingOrder,
|
|
1437
|
-
getUpcomingOrders,
|
|
1438
|
-
async getAdjustments() {
|
|
1439
|
-
return adapter.getAdjustments();
|
|
1440
|
-
},
|
|
1441
|
-
async skipOrder(params) {
|
|
1442
|
-
const result = await adapter.skipOrder(params);
|
|
1443
|
-
if (result._tag === "Success") {
|
|
1444
|
-
await reloadCurrent(params.subscriptionId);
|
|
1445
|
-
}
|
|
1446
|
-
return result;
|
|
1447
|
-
},
|
|
1448
|
-
async changeDateAdjustment(params) {
|
|
1449
|
-
const result = await adapter.changeDateAdjustment(params);
|
|
1450
|
-
if (result._tag === "Success") {
|
|
1451
|
-
await reloadCurrent(params.subscriptionId);
|
|
1452
|
-
}
|
|
1453
|
-
return result;
|
|
1454
|
-
},
|
|
1455
|
-
async removeAdjustment(params) {
|
|
1456
|
-
return adapter.removeAdjustment(params);
|
|
1457
|
-
},
|
|
1458
|
-
reloadCurrent
|
|
1459
|
-
};
|
|
1460
|
-
}
|
|
1461
|
-
const SettingsServiceContext = createContext("services/settings");
|
|
1462
|
-
function createSettingsService(initial = {}) {
|
|
1463
|
-
const current = d(initial);
|
|
1464
|
-
return {
|
|
1465
|
-
current,
|
|
1466
|
-
get(key) {
|
|
1467
|
-
return current.value[key];
|
|
1468
|
-
}
|
|
1469
|
-
};
|
|
1470
|
-
}
|
|
1471
|
-
function createShopService(options) {
|
|
1472
|
-
const contactEmail = d(options.getContactEmail());
|
|
1473
|
-
const service = { contactEmail };
|
|
1474
|
-
return service;
|
|
1475
|
-
}
|
|
1476
|
-
const ShopServiceContext = createContext("services/shop");
|
|
1477
1249
|
function createMockSubscriptionAdapter(options = {}) {
|
|
1478
1250
|
const richBase = (id, itemId, renewalId) => ({
|
|
1479
1251
|
id,
|
|
@@ -1481,17 +1253,25 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1481
1253
|
items: [
|
|
1482
1254
|
{
|
|
1483
1255
|
id: itemId,
|
|
1484
|
-
|
|
1485
|
-
|
|
1256
|
+
// Aligned with the mock product catalog (createMockProductAdapter):
|
|
1257
|
+
// sample-3 "Gentle deodorant", variant sample-3-1 "Green tea and jasmine",
|
|
1258
|
+
// recurring price 5.36 EUR (10% off → 4.82 with SAVE10).
|
|
1259
|
+
productId: "sample-3",
|
|
1260
|
+
variantId: "sample-3-1",
|
|
1486
1261
|
quantity: 2,
|
|
1487
|
-
price: { amount: "
|
|
1262
|
+
price: { amount: "5.36", currencyCode: "EUR" },
|
|
1488
1263
|
nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-15"),
|
|
1489
1264
|
isUpsell: false,
|
|
1490
1265
|
isVirtual: false,
|
|
1491
1266
|
nextBillingDate: "2025-11-15T00:00:00Z",
|
|
1492
|
-
currentPrice: { amount: "
|
|
1493
|
-
lineDiscountedPrice: { amount: "
|
|
1494
|
-
variantAvailableForSale: true
|
|
1267
|
+
currentPrice: { amount: "5.36", currencyCode: "EUR" },
|
|
1268
|
+
lineDiscountedPrice: { amount: "4.82", currencyCode: "EUR" },
|
|
1269
|
+
variantAvailableForSale: true,
|
|
1270
|
+
title: "Gentle deodorant for underarms and bust",
|
|
1271
|
+
variantTitle: "Green tea and jasmine",
|
|
1272
|
+
variantImage: { url: "https://placehold.co/400x400?text=Product+3a" },
|
|
1273
|
+
billingPolicy: { intervalCount: 1, interval: "MONTH" },
|
|
1274
|
+
deliveryPolicy: { intervalCount: 1, interval: "MONTH" }
|
|
1495
1275
|
}
|
|
1496
1276
|
],
|
|
1497
1277
|
discounts: [
|
|
@@ -1538,22 +1318,27 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1538
1318
|
items: [
|
|
1539
1319
|
{
|
|
1540
1320
|
id: "item_1",
|
|
1541
|
-
|
|
1542
|
-
|
|
1321
|
+
// Aligned with the mock product catalog (createMockProductAdapter):
|
|
1322
|
+
// sample-1 "Hydrating Gel Cleanser" (default variant), recurring price
|
|
1323
|
+
// 9.99 EUR (10% off → 8.99 with SAVE10).
|
|
1324
|
+
productId: "sample-1",
|
|
1325
|
+
variantId: "sample-1-1",
|
|
1543
1326
|
quantity: 2,
|
|
1544
|
-
price: { amount: "
|
|
1327
|
+
price: { amount: "9.99", currencyCode: "EUR" },
|
|
1545
1328
|
nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-15"),
|
|
1546
1329
|
isUpsell: false,
|
|
1547
1330
|
isVirtual: false,
|
|
1548
1331
|
nextBillingDate: "2025-11-15T00:00:00Z",
|
|
1549
|
-
currentPrice: { amount: "
|
|
1550
|
-
lineDiscountedPrice: { amount: "
|
|
1332
|
+
currentPrice: { amount: "9.99", currencyCode: "EUR" },
|
|
1333
|
+
lineDiscountedPrice: { amount: "8.99", currencyCode: "EUR" },
|
|
1551
1334
|
variantAvailableForSale: true,
|
|
1335
|
+
title: "Hydrating Gel Cleanser for Face and Eye Area",
|
|
1336
|
+
variantImage: { url: "https://placehold.co/400x400?text=Product+1" },
|
|
1552
1337
|
billingPolicy: { intervalCount: 1, interval: "MONTH" },
|
|
1553
1338
|
deliveryPolicy: { intervalCount: 1, interval: "MONTH" },
|
|
1554
1339
|
customAttributes: [
|
|
1555
|
-
{ key: "
|
|
1556
|
-
{ key: "
|
|
1340
|
+
{ key: "skin_type", value: "combination" },
|
|
1341
|
+
{ key: "fragrance", value: "fragrance_free" }
|
|
1557
1342
|
]
|
|
1558
1343
|
}
|
|
1559
1344
|
],
|
|
@@ -1595,7 +1380,7 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1595
1380
|
isEditable: true,
|
|
1596
1381
|
customAttributes: [
|
|
1597
1382
|
{ key: "subscription_tier", value: "premium" },
|
|
1598
|
-
{ key: "gift_message", value: "Enjoy your
|
|
1383
|
+
{ key: "gift_message", value: "Enjoy your skincare routine!" }
|
|
1599
1384
|
]
|
|
1600
1385
|
},
|
|
1601
1386
|
{
|
|
@@ -1604,11 +1389,15 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1604
1389
|
items: [
|
|
1605
1390
|
{
|
|
1606
1391
|
id: "item_2",
|
|
1607
|
-
|
|
1608
|
-
|
|
1392
|
+
// Aligned with the mock product catalog (createMockProductAdapter):
|
|
1393
|
+
// sample-2 "More COLLAGEN" (default variant), recurring price 10.99 EUR.
|
|
1394
|
+
productId: "sample-2",
|
|
1395
|
+
variantId: "sample-2-1",
|
|
1609
1396
|
quantity: 1,
|
|
1610
|
-
price: { amount: "
|
|
1397
|
+
price: { amount: "10.99", currencyCode: "EUR" },
|
|
1611
1398
|
nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-20"),
|
|
1399
|
+
title: "More COLLAGEN",
|
|
1400
|
+
variantImage: { url: "https://placehold.co/400x400?text=Product+2" },
|
|
1612
1401
|
billingPolicy: { intervalCount: 2, interval: "WEEK" },
|
|
1613
1402
|
deliveryPolicy: { intervalCount: 2, interval: "WEEK" },
|
|
1614
1403
|
customAttributes: []
|
|
@@ -1668,8 +1457,15 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1668
1457
|
return {
|
|
1669
1458
|
async getById(id) {
|
|
1670
1459
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1671
|
-
const subscription = mockSubscriptions.find((sub) => sub.id === id)
|
|
1672
|
-
return {
|
|
1460
|
+
const subscription = mockSubscriptions.find((sub) => sub.id === id);
|
|
1461
|
+
return {
|
|
1462
|
+
_tag: "Success",
|
|
1463
|
+
data: subscription ? {
|
|
1464
|
+
...subscription,
|
|
1465
|
+
items: subscription.items.map((item) => ({ ...item })),
|
|
1466
|
+
discounts: subscription.discounts.map((d3) => ({ ...d3 }))
|
|
1467
|
+
} : null
|
|
1468
|
+
};
|
|
1673
1469
|
},
|
|
1674
1470
|
async search(options2 = {}) {
|
|
1675
1471
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
@@ -1706,16 +1502,58 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1706
1502
|
}
|
|
1707
1503
|
};
|
|
1708
1504
|
},
|
|
1709
|
-
async addItem() {
|
|
1505
|
+
async addItem({ subscriptionId, item }) {
|
|
1506
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1710
1507
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1508
|
+
const subscription = mockSubscriptions.find((sub) => sub.id === subscriptionId);
|
|
1509
|
+
if (!subscription) {
|
|
1510
|
+
return { _tag: "Failure", error: "Subscription not found" };
|
|
1511
|
+
}
|
|
1512
|
+
const currencyCode = ((_a = subscription.items[0]) == null ? void 0 : _a.price.currencyCode) ?? "USD";
|
|
1513
|
+
const product = await ((_b = options.productAdapter) == null ? void 0 : _b.getByVariantId(item.variantId)) ?? await ((_c = options.productAdapter) == null ? void 0 : _c.getById(item.variantId)) ?? null;
|
|
1514
|
+
const variant = (product == null ? void 0 : product.variants.items.find((v2) => v2.id === item.variantId)) ?? (product == null ? void 0 : product.variants.items[0]);
|
|
1515
|
+
const linePrice = ((_e = (_d = variant == null ? void 0 : variant.purchaseOptions) == null ? void 0 : _d[0]) == null ? void 0 : _e.price) ?? (variant == null ? void 0 : variant.price);
|
|
1516
|
+
subscription.items.push({
|
|
1517
|
+
id: `item_${Date.now()}_${subscription.items.length}`,
|
|
1518
|
+
productId: (product == null ? void 0 : product.id) ?? "",
|
|
1519
|
+
variantId: item.variantId,
|
|
1520
|
+
quantity: item.quantity,
|
|
1521
|
+
price: linePrice ? { ...linePrice } : { amount: "0.00", currencyCode },
|
|
1522
|
+
...linePrice ? { currentPrice: { ...linePrice } } : {},
|
|
1523
|
+
title: (product == null ? void 0 : product.title) ?? `Product ${item.variantId}`,
|
|
1524
|
+
...variant && product && !product.hasOnlyDefaultVariant ? { variantTitle: variant.title } : {},
|
|
1525
|
+
...(variant == null ? void 0 : variant.image) ? { variantImage: variant.image } : {},
|
|
1526
|
+
variantAvailableForSale: true,
|
|
1527
|
+
billingPolicy: ((_f = subscription.items[0]) == null ? void 0 : _f.billingPolicy) ?? subscription.billingPolicy ?? null,
|
|
1528
|
+
deliveryPolicy: ((_g = subscription.items[0]) == null ? void 0 : _g.deliveryPolicy) ?? subscription.deliveryPolicy ?? null
|
|
1529
|
+
});
|
|
1530
|
+
subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1711
1531
|
return { _tag: "Success", data: void 0 };
|
|
1712
1532
|
},
|
|
1713
|
-
async removeItem() {
|
|
1533
|
+
async removeItem({ subscriptionId, itemId }) {
|
|
1714
1534
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1535
|
+
const subscription = mockSubscriptions.find((sub) => sub.id === subscriptionId);
|
|
1536
|
+
if (!subscription) {
|
|
1537
|
+
return { _tag: "Failure", error: "Subscription not found" };
|
|
1538
|
+
}
|
|
1539
|
+
subscription.items = subscription.items.filter((i3) => i3.id !== itemId);
|
|
1540
|
+
subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1715
1541
|
return { _tag: "Success", data: void 0 };
|
|
1716
1542
|
},
|
|
1717
|
-
async updateItem() {
|
|
1543
|
+
async updateItem({ subscriptionId, lineId, update }) {
|
|
1718
1544
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1545
|
+
const subscription = mockSubscriptions.find((sub) => sub.id === subscriptionId);
|
|
1546
|
+
if (!subscription) {
|
|
1547
|
+
return { _tag: "Failure", error: "Subscription not found" };
|
|
1548
|
+
}
|
|
1549
|
+
const item = subscription.items.find((i3) => i3.id === lineId);
|
|
1550
|
+
if (!item) {
|
|
1551
|
+
return { _tag: "Failure", error: "Line item not found" };
|
|
1552
|
+
}
|
|
1553
|
+
if (update.variantId !== void 0) item.variantId = update.variantId;
|
|
1554
|
+
if (update.quantity !== void 0) item.quantity = update.quantity;
|
|
1555
|
+
if (update.billingPolicy !== void 0) item.billingPolicy = update.billingPolicy;
|
|
1556
|
+
subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1719
1557
|
return { _tag: "Success", data: void 0 };
|
|
1720
1558
|
},
|
|
1721
1559
|
async skipLineItem() {
|
|
@@ -1976,7 +1814,7 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
1976
1814
|
try {
|
|
1977
1815
|
const params = new URLSearchParams();
|
|
1978
1816
|
if ((_a = options == null ? void 0 : options.filters) == null ? void 0 : _a.length) {
|
|
1979
|
-
const q2 = options.filters.filter((f2) => Object.keys(f2).length > 0).flatMap((f2) => Object.entries(f2).filter(([, v2]) => Boolean(v2))).map(([
|
|
1817
|
+
const q2 = options.filters.filter((f2) => Object.keys(f2).length > 0).flatMap((f2) => Object.entries(f2).filter(([, v2]) => Boolean(v2))).map(([k, v2]) => `${k}:'${v2}'`).join(" AND ");
|
|
1980
1818
|
if (q2) params.set("query", q2);
|
|
1981
1819
|
}
|
|
1982
1820
|
if (options == null ? void 0 : options.pagination) {
|
|
@@ -2001,8 +1839,8 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2001
1839
|
}
|
|
2002
1840
|
}
|
|
2003
1841
|
};
|
|
2004
|
-
} catch (
|
|
2005
|
-
return { _tag: "Failure", error:
|
|
1842
|
+
} catch (e2) {
|
|
1843
|
+
return { _tag: "Failure", error: e2 };
|
|
2006
1844
|
}
|
|
2007
1845
|
},
|
|
2008
1846
|
async getById(id) {
|
|
@@ -2014,8 +1852,8 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2014
1852
|
const body = await res.json();
|
|
2015
1853
|
const raw = body.data[0];
|
|
2016
1854
|
return { _tag: "Success", data: raw ? mapSubscription(raw) : null };
|
|
2017
|
-
} catch (
|
|
2018
|
-
return { _tag: "Failure", error:
|
|
1855
|
+
} catch (e2) {
|
|
1856
|
+
return { _tag: "Failure", error: e2 };
|
|
2019
1857
|
}
|
|
2020
1858
|
},
|
|
2021
1859
|
async addItem({ subscriptionId, item }) {
|
|
@@ -2030,8 +1868,8 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2030
1868
|
);
|
|
2031
1869
|
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2032
1870
|
return { _tag: "Success", data: void 0 };
|
|
2033
|
-
} catch (
|
|
2034
|
-
return { _tag: "Failure", error:
|
|
1871
|
+
} catch (e2) {
|
|
1872
|
+
return { _tag: "Failure", error: e2 };
|
|
2035
1873
|
}
|
|
2036
1874
|
},
|
|
2037
1875
|
async removeItem({ subscriptionId, itemId }) {
|
|
@@ -2042,8 +1880,8 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2042
1880
|
);
|
|
2043
1881
|
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2044
1882
|
return { _tag: "Success", data: void 0 };
|
|
2045
|
-
} catch (
|
|
2046
|
-
return { _tag: "Failure", error:
|
|
1883
|
+
} catch (e2) {
|
|
1884
|
+
return { _tag: "Failure", error: e2 };
|
|
2047
1885
|
}
|
|
2048
1886
|
},
|
|
2049
1887
|
async updateItem({ subscriptionId, lineId, update }) {
|
|
@@ -2064,8 +1902,8 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2064
1902
|
);
|
|
2065
1903
|
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2066
1904
|
return { _tag: "Success", data: void 0 };
|
|
2067
|
-
} catch (
|
|
2068
|
-
return { _tag: "Failure", error:
|
|
1905
|
+
} catch (e2) {
|
|
1906
|
+
return { _tag: "Failure", error: e2 };
|
|
2069
1907
|
}
|
|
2070
1908
|
},
|
|
2071
1909
|
async skipLineItem({ subscriptionId, lineId, nextBillingDate }) {
|
|
@@ -2080,8 +1918,8 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2080
1918
|
);
|
|
2081
1919
|
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2082
1920
|
return { _tag: "Success", data: void 0 };
|
|
2083
|
-
} catch (
|
|
2084
|
-
return { _tag: "Failure", error:
|
|
1921
|
+
} catch (e2) {
|
|
1922
|
+
return { _tag: "Failure", error: e2 };
|
|
2085
1923
|
}
|
|
2086
1924
|
},
|
|
2087
1925
|
async updateBoxItems({ subscriptionId, parentId, items, shippingMethodHandle }) {
|
|
@@ -2096,8 +1934,8 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2096
1934
|
);
|
|
2097
1935
|
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2098
1936
|
return { _tag: "Success", data: void 0 };
|
|
2099
|
-
} catch (
|
|
2100
|
-
return { _tag: "Failure", error:
|
|
1937
|
+
} catch (e2) {
|
|
1938
|
+
return { _tag: "Failure", error: e2 };
|
|
2101
1939
|
}
|
|
2102
1940
|
},
|
|
2103
1941
|
async addDiscount({ subscriptionId, code }) {
|
|
@@ -2112,8 +1950,8 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2112
1950
|
);
|
|
2113
1951
|
if (!res.ok) return { _tag: "Failure", error: { kind: "NETWORK", message: `HTTP ${res.status}` } };
|
|
2114
1952
|
return { _tag: "Success", data: void 0 };
|
|
2115
|
-
} catch (
|
|
2116
|
-
return { _tag: "Failure", error: { kind: "UNKNOWN", message:
|
|
1953
|
+
} catch (e2) {
|
|
1954
|
+
return { _tag: "Failure", error: { kind: "UNKNOWN", message: e2 instanceof Error ? e2.message : void 0 } };
|
|
2117
1955
|
}
|
|
2118
1956
|
},
|
|
2119
1957
|
async removeDiscount({ subscriptionId, discountId }) {
|
|
@@ -2124,8 +1962,8 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2124
1962
|
);
|
|
2125
1963
|
if (!res.ok) return { _tag: "Failure", error: { kind: "NETWORK", message: `HTTP ${res.status}` } };
|
|
2126
1964
|
return { _tag: "Success", data: void 0 };
|
|
2127
|
-
} catch (
|
|
2128
|
-
return { _tag: "Failure", error: { kind: "UNKNOWN", message:
|
|
1965
|
+
} catch (e2) {
|
|
1966
|
+
return { _tag: "Failure", error: { kind: "UNKNOWN", message: e2 instanceof Error ? e2.message : void 0 } };
|
|
2129
1967
|
}
|
|
2130
1968
|
},
|
|
2131
1969
|
// Uses PATCH /customer/v1/subscriptions/{id} — the dedicated /reschedule route does not exist.
|
|
@@ -2142,8 +1980,8 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2142
1980
|
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2143
1981
|
const data = await res.json();
|
|
2144
1982
|
return { _tag: "Success", data: mapSubscription(data) };
|
|
2145
|
-
} catch (
|
|
2146
|
-
return { _tag: "Failure", error:
|
|
1983
|
+
} catch (e2) {
|
|
1984
|
+
return { _tag: "Failure", error: e2 };
|
|
2147
1985
|
}
|
|
2148
1986
|
},
|
|
2149
1987
|
async resume({ subscriptionId }) {
|
|
@@ -2155,8 +1993,8 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2155
1993
|
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2156
1994
|
const data = await res.json();
|
|
2157
1995
|
return { _tag: "Success", data: mapSubscription(data) };
|
|
2158
|
-
} catch (
|
|
2159
|
-
return { _tag: "Failure", error:
|
|
1996
|
+
} catch (e2) {
|
|
1997
|
+
return { _tag: "Failure", error: e2 };
|
|
2160
1998
|
}
|
|
2161
1999
|
},
|
|
2162
2000
|
async pause({ subscriptionId }) {
|
|
@@ -2168,8 +2006,8 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2168
2006
|
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2169
2007
|
const data = await res.json();
|
|
2170
2008
|
return { _tag: "Success", data: mapSubscription(data) };
|
|
2171
|
-
} catch (
|
|
2172
|
-
return { _tag: "Failure", error:
|
|
2009
|
+
} catch (e2) {
|
|
2010
|
+
return { _tag: "Failure", error: e2 };
|
|
2173
2011
|
}
|
|
2174
2012
|
},
|
|
2175
2013
|
async reactivate({ subscriptionId }) {
|
|
@@ -2181,8 +2019,8 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2181
2019
|
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2182
2020
|
const data = await res.json();
|
|
2183
2021
|
return { _tag: "Success", data: mapSubscription(data) };
|
|
2184
|
-
} catch (
|
|
2185
|
-
return { _tag: "Failure", error:
|
|
2022
|
+
} catch (e2) {
|
|
2023
|
+
return { _tag: "Failure", error: e2 };
|
|
2186
2024
|
}
|
|
2187
2025
|
},
|
|
2188
2026
|
async cancel({ subscriptionId, reason }) {
|
|
@@ -2198,8 +2036,8 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2198
2036
|
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2199
2037
|
const data = await res.json();
|
|
2200
2038
|
return { _tag: "Success", data: mapSubscription(data) };
|
|
2201
|
-
} catch (
|
|
2202
|
-
return { _tag: "Failure", error:
|
|
2039
|
+
} catch (e2) {
|
|
2040
|
+
return { _tag: "Failure", error: e2 };
|
|
2203
2041
|
}
|
|
2204
2042
|
},
|
|
2205
2043
|
// Legacy endpoint — no /customer/v1/subscriptions/{id}/plans exists yet.
|
|
@@ -2211,8 +2049,8 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2211
2049
|
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2212
2050
|
const data = await res.json();
|
|
2213
2051
|
return { _tag: "Success", data };
|
|
2214
|
-
} catch (
|
|
2215
|
-
return { _tag: "Failure", error:
|
|
2052
|
+
} catch (e2) {
|
|
2053
|
+
return { _tag: "Failure", error: e2 };
|
|
2216
2054
|
}
|
|
2217
2055
|
},
|
|
2218
2056
|
// Legacy endpoint — no /customer/v1 equivalent exists yet.
|
|
@@ -2224,8 +2062,8 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2224
2062
|
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2225
2063
|
const data = await res.json();
|
|
2226
2064
|
return { _tag: "Success", data: (data == null ? void 0 : data.id) ?? null };
|
|
2227
|
-
} catch (
|
|
2228
|
-
return { _tag: "Failure", error:
|
|
2065
|
+
} catch (e2) {
|
|
2066
|
+
return { _tag: "Failure", error: e2 };
|
|
2229
2067
|
}
|
|
2230
2068
|
},
|
|
2231
2069
|
// Legacy endpoint — no /customer/v1/subscriptions/{id}/upsells exists yet.
|
|
@@ -2252,8 +2090,8 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2252
2090
|
};
|
|
2253
2091
|
});
|
|
2254
2092
|
return { _tag: "Success", data: products };
|
|
2255
|
-
} catch (
|
|
2256
|
-
return { _tag: "Failure", error:
|
|
2093
|
+
} catch (e2) {
|
|
2094
|
+
return { _tag: "Failure", error: e2 };
|
|
2257
2095
|
}
|
|
2258
2096
|
},
|
|
2259
2097
|
// Legacy endpoint — no /customer/v1/subscriptions/{id}/upsells POST exists yet.
|
|
@@ -2273,8 +2111,8 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2273
2111
|
);
|
|
2274
2112
|
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2275
2113
|
return { _tag: "Success", data: void 0 };
|
|
2276
|
-
} catch (
|
|
2277
|
-
return { _tag: "Failure", error:
|
|
2114
|
+
} catch (e2) {
|
|
2115
|
+
return { _tag: "Failure", error: e2 };
|
|
2278
2116
|
}
|
|
2279
2117
|
},
|
|
2280
2118
|
// Legacy endpoint — no /customer/v1 equivalent exists yet.
|
|
@@ -2290,8 +2128,8 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2290
2128
|
_tag: "Success",
|
|
2291
2129
|
data: { id: data.id, createdAt: data.createdAt }
|
|
2292
2130
|
};
|
|
2293
|
-
} catch (
|
|
2294
|
-
return { _tag: "Failure", error:
|
|
2131
|
+
} catch (e2) {
|
|
2132
|
+
return { _tag: "Failure", error: e2 };
|
|
2295
2133
|
}
|
|
2296
2134
|
},
|
|
2297
2135
|
// Legacy endpoints, split by stage (see SubscriptionService.renewNow docs):
|
|
@@ -2311,8 +2149,8 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2311
2149
|
result: (body == null ? void 0 : body.result) ?? "success"
|
|
2312
2150
|
}
|
|
2313
2151
|
};
|
|
2314
|
-
} catch (
|
|
2315
|
-
return { _tag: "Failure", error:
|
|
2152
|
+
} catch (e2) {
|
|
2153
|
+
return { _tag: "Failure", error: e2 };
|
|
2316
2154
|
}
|
|
2317
2155
|
},
|
|
2318
2156
|
// Legacy endpoint — POST /plan returns 204; re-fetch to return the updated subscription.
|
|
@@ -2334,13 +2172,374 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2334
2172
|
_tag: "Failure",
|
|
2335
2173
|
error: "Subscription not found after frequency change"
|
|
2336
2174
|
};
|
|
2337
|
-
} catch (
|
|
2338
|
-
return { _tag: "Failure", error:
|
|
2175
|
+
} catch (e2) {
|
|
2176
|
+
return { _tag: "Failure", error: e2 };
|
|
2339
2177
|
}
|
|
2340
2178
|
}
|
|
2341
2179
|
};
|
|
2342
2180
|
return adapter;
|
|
2343
2181
|
}
|
|
2182
|
+
const DELIVERY_PRICE_CENTS = 500;
|
|
2183
|
+
const DELIVERY_OFFSET_DAYS = 2;
|
|
2184
|
+
function toCents(amount) {
|
|
2185
|
+
const n2 = Number.parseFloat(amount ?? "0");
|
|
2186
|
+
return Number.isFinite(n2) ? Math.round(n2 * 100) : 0;
|
|
2187
|
+
}
|
|
2188
|
+
function addInterval(date, interval, units) {
|
|
2189
|
+
const d3 = new Date(date);
|
|
2190
|
+
switch (interval) {
|
|
2191
|
+
case "DAY":
|
|
2192
|
+
d3.setDate(d3.getDate() + units);
|
|
2193
|
+
break;
|
|
2194
|
+
case "WEEK":
|
|
2195
|
+
d3.setDate(d3.getDate() + units * 7);
|
|
2196
|
+
break;
|
|
2197
|
+
case "YEAR":
|
|
2198
|
+
d3.setFullYear(d3.getFullYear() + units);
|
|
2199
|
+
break;
|
|
2200
|
+
default:
|
|
2201
|
+
d3.setMonth(d3.getMonth() + units);
|
|
2202
|
+
break;
|
|
2203
|
+
}
|
|
2204
|
+
return d3;
|
|
2205
|
+
}
|
|
2206
|
+
function mapItem(sub, item, cycle) {
|
|
2207
|
+
var _a, _b;
|
|
2208
|
+
const price = toCents(((_a = item.currentPrice) == null ? void 0 : _a.amount) ?? item.price.amount);
|
|
2209
|
+
return {
|
|
2210
|
+
id: `${sub.id}_cycle_${cycle}_${item.id}`,
|
|
2211
|
+
title: item.title ?? `Product ${item.variantId}`,
|
|
2212
|
+
subtitle: item.variantTitle ?? null,
|
|
2213
|
+
imageUrl: (_b = item.variantImage) == null ? void 0 : _b.url,
|
|
2214
|
+
variantId: item.variantId,
|
|
2215
|
+
quantity: item.quantity,
|
|
2216
|
+
price,
|
|
2217
|
+
totalPrice: price * item.quantity,
|
|
2218
|
+
variantImage: item.variantImage ?? null,
|
|
2219
|
+
variantAvailableForSale: item.variantAvailableForSale ?? true,
|
|
2220
|
+
subscriptionId: sub.id,
|
|
2221
|
+
subscriptionLineId: item.id,
|
|
2222
|
+
productId: item.productId,
|
|
2223
|
+
parentProductId: item.parentProductId ?? null,
|
|
2224
|
+
parentLineId: item.parentLineId ?? null,
|
|
2225
|
+
isVirtual: item.isVirtual ?? false,
|
|
2226
|
+
isUpsell: item.isUpsell ?? false,
|
|
2227
|
+
isOneTime: item.isOneTime ?? false,
|
|
2228
|
+
customAttributes: (item.customAttributes ?? []).map((a3) => ({
|
|
2229
|
+
name: a3.key,
|
|
2230
|
+
value: a3.value
|
|
2231
|
+
}))
|
|
2232
|
+
};
|
|
2233
|
+
}
|
|
2234
|
+
function projectUpcomingOrders(sub, count) {
|
|
2235
|
+
var _a, _b;
|
|
2236
|
+
if (sub.status !== "active") return [];
|
|
2237
|
+
const billing = sub.billingPolicy ?? ((_a = sub.items[0]) == null ? void 0 : _a.billingPolicy) ?? { interval: "MONTH", intervalCount: 1 };
|
|
2238
|
+
const baseStr = sub.nextBillingDate ?? (sub.nextDeliveryDate ? sub.nextDeliveryDate.toISOString() : null);
|
|
2239
|
+
const base = baseStr ? new Date(baseStr) : /* @__PURE__ */ new Date();
|
|
2240
|
+
const currencyCode = ((_b = sub.items[0]) == null ? void 0 : _b.price.currencyCode) ?? "USD";
|
|
2241
|
+
const orders = [];
|
|
2242
|
+
for (let cycle = 0; cycle < count; cycle++) {
|
|
2243
|
+
const billingDate = addInterval(
|
|
2244
|
+
base,
|
|
2245
|
+
billing.interval,
|
|
2246
|
+
cycle * billing.intervalCount
|
|
2247
|
+
);
|
|
2248
|
+
const deliveryDate = addInterval(billingDate, "DAY", DELIVERY_OFFSET_DAYS);
|
|
2249
|
+
const items = sub.items.map((item) => mapItem(sub, item, cycle));
|
|
2250
|
+
const subtotal = items.reduce((sum, it) => sum + it.totalPrice, 0);
|
|
2251
|
+
orders.push({
|
|
2252
|
+
id: `${sub.id}_cycle_${cycle}`,
|
|
2253
|
+
customerId: sub.customerId,
|
|
2254
|
+
subscriptionId: sub.id,
|
|
2255
|
+
date: billingDate.toISOString(),
|
|
2256
|
+
skipped: false,
|
|
2257
|
+
currencyCode,
|
|
2258
|
+
subtotal,
|
|
2259
|
+
deliveryPrice: DELIVERY_PRICE_CENTS,
|
|
2260
|
+
cycleIndex: cycle,
|
|
2261
|
+
deliveryDate: deliveryDate.toISOString(),
|
|
2262
|
+
status: "scheduled",
|
|
2263
|
+
items,
|
|
2264
|
+
discounts: sub.discounts.map((d3) => ({
|
|
2265
|
+
id: d3.id,
|
|
2266
|
+
title: d3.code,
|
|
2267
|
+
type: d3.type,
|
|
2268
|
+
value: d3.value
|
|
2269
|
+
}))
|
|
2270
|
+
});
|
|
2271
|
+
}
|
|
2272
|
+
return orders;
|
|
2273
|
+
}
|
|
2274
|
+
function applyAdjustments(orders, adjustments) {
|
|
2275
|
+
return orders.map((order) => {
|
|
2276
|
+
let next = order;
|
|
2277
|
+
for (const adj of adjustments) {
|
|
2278
|
+
if (adj.subscriptionId !== order.subscriptionId) continue;
|
|
2279
|
+
if (adj.cycle !== order.cycleIndex) continue;
|
|
2280
|
+
if (adj.type === "skip") {
|
|
2281
|
+
next = { ...next, skipped: true, status: "skipped" };
|
|
2282
|
+
} else if (adj.type === "date_change" && adj.newDate) {
|
|
2283
|
+
next = { ...next, date: adj.newDate, deliveryDate: adj.newDate };
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
return next;
|
|
2287
|
+
});
|
|
2288
|
+
}
|
|
2289
|
+
function createMockSchedulesAdapter(subscriptions = createMockSubscriptionAdapter()) {
|
|
2290
|
+
const RESOLVE_DEPTH = 12;
|
|
2291
|
+
let adjustments = [];
|
|
2292
|
+
async function subscriptionsToProject(subscriptionId) {
|
|
2293
|
+
if (subscriptionId) {
|
|
2294
|
+
const res = await subscriptions.getById(subscriptionId);
|
|
2295
|
+
return res._tag === "Success" && res.data ? [res.data] : [];
|
|
2296
|
+
}
|
|
2297
|
+
const all = [];
|
|
2298
|
+
let pagination;
|
|
2299
|
+
for (let guard = 0; guard < 50; guard++) {
|
|
2300
|
+
const res = await subscriptions.search(pagination ? { pagination } : {});
|
|
2301
|
+
if (res._tag !== "Success") break;
|
|
2302
|
+
all.push(...res.data.items);
|
|
2303
|
+
const { hasNextPage, endCursor } = res.data.pageInfo;
|
|
2304
|
+
if (!hasNextPage || !endCursor) break;
|
|
2305
|
+
pagination = { after: endCursor };
|
|
2306
|
+
}
|
|
2307
|
+
return all;
|
|
2308
|
+
}
|
|
2309
|
+
function resolveCycle(orders, opts) {
|
|
2310
|
+
if (opts.cycle != null) return opts.cycle;
|
|
2311
|
+
if (opts.date) {
|
|
2312
|
+
const target = new Date(opts.date).toISOString().split("T")[0];
|
|
2313
|
+
const match = orders.find(
|
|
2314
|
+
(o2) => o2.deliveryDate.split("T")[0] === target || o2.date.split("T")[0] === target
|
|
2315
|
+
);
|
|
2316
|
+
if (match) return match.cycleIndex;
|
|
2317
|
+
}
|
|
2318
|
+
const firstScheduled = orders.find((o2) => o2.status === "scheduled");
|
|
2319
|
+
return (firstScheduled == null ? void 0 : firstScheduled.cycleIndex) ?? null;
|
|
2320
|
+
}
|
|
2321
|
+
async function recordAdjustment(subscriptionId, opts, build) {
|
|
2322
|
+
const res = await subscriptions.getById(subscriptionId);
|
|
2323
|
+
const sub = res._tag === "Success" ? res.data : null;
|
|
2324
|
+
if (!sub) return { _tag: "Failure", error: "No scheduled order found" };
|
|
2325
|
+
const orders = applyAdjustments(
|
|
2326
|
+
projectUpcomingOrders(sub, RESOLVE_DEPTH),
|
|
2327
|
+
adjustments
|
|
2328
|
+
);
|
|
2329
|
+
const cycle = resolveCycle(orders, opts);
|
|
2330
|
+
if (cycle == null) {
|
|
2331
|
+
return { _tag: "Failure", error: "No scheduled order found" };
|
|
2332
|
+
}
|
|
2333
|
+
adjustments = [...adjustments, build(cycle)];
|
|
2334
|
+
return { _tag: "Success", data: void 0 };
|
|
2335
|
+
}
|
|
2336
|
+
return {
|
|
2337
|
+
async getUpcomingOrders({ count, subscriptionId }) {
|
|
2338
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
2339
|
+
const subs = await subscriptionsToProject(subscriptionId);
|
|
2340
|
+
const orders = subs.flatMap(
|
|
2341
|
+
(sub) => applyAdjustments(projectUpcomingOrders(sub, count), adjustments)
|
|
2342
|
+
).sort((a3, b3) => a3.date.localeCompare(b3.date));
|
|
2343
|
+
return { _tag: "Success", data: orders.slice(0, count) };
|
|
2344
|
+
},
|
|
2345
|
+
async getAdjustments() {
|
|
2346
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
2347
|
+
return { _tag: "Success", data: [...adjustments] };
|
|
2348
|
+
},
|
|
2349
|
+
async skipOrder({ subscriptionId, cycle, date }) {
|
|
2350
|
+
await new Promise((r) => setTimeout(r, 300));
|
|
2351
|
+
return recordAdjustment(subscriptionId, { cycle, date }, (resolved) => ({
|
|
2352
|
+
id: `adj-${Date.now()}`,
|
|
2353
|
+
subscriptionId,
|
|
2354
|
+
type: "skip",
|
|
2355
|
+
cycle: resolved
|
|
2356
|
+
}));
|
|
2357
|
+
},
|
|
2358
|
+
async changeDateAdjustment({ subscriptionId, newDate, currentDate }) {
|
|
2359
|
+
await new Promise((r) => setTimeout(r, 300));
|
|
2360
|
+
return recordAdjustment(
|
|
2361
|
+
subscriptionId,
|
|
2362
|
+
{ date: currentDate },
|
|
2363
|
+
(resolved) => ({
|
|
2364
|
+
id: `adj-${Date.now()}`,
|
|
2365
|
+
subscriptionId,
|
|
2366
|
+
type: "date_change",
|
|
2367
|
+
cycle: resolved,
|
|
2368
|
+
newDate
|
|
2369
|
+
})
|
|
2370
|
+
);
|
|
2371
|
+
},
|
|
2372
|
+
async removeAdjustment({ adjustmentId }) {
|
|
2373
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
2374
|
+
adjustments = adjustments.filter((a3) => a3.id !== adjustmentId);
|
|
2375
|
+
return { _tag: "Success", data: void 0 };
|
|
2376
|
+
}
|
|
2377
|
+
};
|
|
2378
|
+
}
|
|
2379
|
+
function createApiSchedulesAdapter(fetcher) {
|
|
2380
|
+
return {
|
|
2381
|
+
async getUpcomingOrders({ count, subscriptionId }) {
|
|
2382
|
+
try {
|
|
2383
|
+
const params = new URLSearchParams({ count: String(count) });
|
|
2384
|
+
if (subscriptionId) params.set("query", `id:"${subscriptionId}"`);
|
|
2385
|
+
const res = await fetcher(`/customer/v1/schedules/?${params.toString()}`);
|
|
2386
|
+
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2387
|
+
const data = await res.json();
|
|
2388
|
+
return { _tag: "Success", data: data.orders };
|
|
2389
|
+
} catch (e2) {
|
|
2390
|
+
return { _tag: "Failure", error: e2 };
|
|
2391
|
+
}
|
|
2392
|
+
},
|
|
2393
|
+
async getAdjustments() {
|
|
2394
|
+
try {
|
|
2395
|
+
const res = await fetcher(`/customer/v1/schedules/adjustments`);
|
|
2396
|
+
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2397
|
+
const data = await res.json();
|
|
2398
|
+
const adjustments = data.data.map((a3) => ({
|
|
2399
|
+
id: a3.id,
|
|
2400
|
+
subscriptionId: a3.subscriptionId ?? "",
|
|
2401
|
+
type: a3.type === "CHANGE_DATE" ? "date_change" : "skip",
|
|
2402
|
+
newDate: a3.newDate
|
|
2403
|
+
}));
|
|
2404
|
+
return { _tag: "Success", data: adjustments };
|
|
2405
|
+
} catch (e2) {
|
|
2406
|
+
return { _tag: "Failure", error: e2 };
|
|
2407
|
+
}
|
|
2408
|
+
},
|
|
2409
|
+
async skipOrder({ cycle, date }) {
|
|
2410
|
+
if (cycle == null && date == null) {
|
|
2411
|
+
return { _tag: "Failure", error: "Either cycle or date is required for skipOrder" };
|
|
2412
|
+
}
|
|
2413
|
+
try {
|
|
2414
|
+
const matcher = cycle != null ? { type: "CYCLE", input: { cycle } } : { type: "DATE", input: { date: new Date(date).toISOString() } };
|
|
2415
|
+
const res = await fetcher(`/customer/v1/schedules/adjustments`, {
|
|
2416
|
+
method: "POST",
|
|
2417
|
+
headers: { "Content-Type": "application/json" },
|
|
2418
|
+
body: JSON.stringify({
|
|
2419
|
+
matcher,
|
|
2420
|
+
action: { type: "SKIP_ORDER", input: { reason: "" } }
|
|
2421
|
+
})
|
|
2422
|
+
});
|
|
2423
|
+
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2424
|
+
return { _tag: "Success", data: void 0 };
|
|
2425
|
+
} catch (e2) {
|
|
2426
|
+
return { _tag: "Failure", error: e2 };
|
|
2427
|
+
}
|
|
2428
|
+
},
|
|
2429
|
+
async changeDateAdjustment({ newDate, currentDate }) {
|
|
2430
|
+
if (currentDate == null) {
|
|
2431
|
+
return {
|
|
2432
|
+
_tag: "Failure",
|
|
2433
|
+
error: "currentDate is required for changeDateAdjustment"
|
|
2434
|
+
};
|
|
2435
|
+
}
|
|
2436
|
+
try {
|
|
2437
|
+
const matcher = { type: "DATE", input: { date: new Date(currentDate).toISOString() } };
|
|
2438
|
+
const res = await fetcher(`/customer/v1/schedules/adjustments`, {
|
|
2439
|
+
method: "POST",
|
|
2440
|
+
headers: { "Content-Type": "application/json" },
|
|
2441
|
+
body: JSON.stringify({
|
|
2442
|
+
matcher,
|
|
2443
|
+
action: {
|
|
2444
|
+
type: "CHANGE_DATE",
|
|
2445
|
+
input: { newDate: new Date(newDate).toISOString() }
|
|
2446
|
+
}
|
|
2447
|
+
})
|
|
2448
|
+
});
|
|
2449
|
+
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2450
|
+
return { _tag: "Success", data: void 0 };
|
|
2451
|
+
} catch (e2) {
|
|
2452
|
+
return { _tag: "Failure", error: e2 };
|
|
2453
|
+
}
|
|
2454
|
+
},
|
|
2455
|
+
async removeAdjustment({ adjustmentId }) {
|
|
2456
|
+
try {
|
|
2457
|
+
const res = await fetcher(
|
|
2458
|
+
`/customer/v1/schedules/adjustments/${adjustmentId}`,
|
|
2459
|
+
{ method: "DELETE" }
|
|
2460
|
+
);
|
|
2461
|
+
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2462
|
+
return { _tag: "Success", data: void 0 };
|
|
2463
|
+
} catch (e2) {
|
|
2464
|
+
return { _tag: "Failure", error: e2 };
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
};
|
|
2468
|
+
}
|
|
2469
|
+
const SchedulesServiceContext = createContext("services/schedules");
|
|
2470
|
+
function createSchedulesService(adapter, opts) {
|
|
2471
|
+
const current = d(null);
|
|
2472
|
+
const currentLoading = d(false);
|
|
2473
|
+
const hasPendingBilling = (opts == null ? void 0 : opts.hasPendingBilling) ?? d(false);
|
|
2474
|
+
let reloadToken = 0;
|
|
2475
|
+
async function getUpcomingOrder() {
|
|
2476
|
+
const result = await adapter.getUpcomingOrders({ count: 1 });
|
|
2477
|
+
if (result._tag === "Failure") return result;
|
|
2478
|
+
return { _tag: "Success", data: result.data[0] ?? null };
|
|
2479
|
+
}
|
|
2480
|
+
async function getUpcomingOrders(count) {
|
|
2481
|
+
return adapter.getUpcomingOrders({ count });
|
|
2482
|
+
}
|
|
2483
|
+
async function reloadCurrent(subscriptionId) {
|
|
2484
|
+
var _a;
|
|
2485
|
+
const token = ++reloadToken;
|
|
2486
|
+
currentLoading.value = true;
|
|
2487
|
+
const count = Math.max(((_a = current.value) == null ? void 0 : _a.length) ?? 0, 3);
|
|
2488
|
+
const result = await adapter.getUpcomingOrders({
|
|
2489
|
+
count,
|
|
2490
|
+
subscriptionId
|
|
2491
|
+
});
|
|
2492
|
+
if (token !== reloadToken) return;
|
|
2493
|
+
currentLoading.value = false;
|
|
2494
|
+
if (result._tag === "Success") {
|
|
2495
|
+
current.value = result.data;
|
|
2496
|
+
}
|
|
2497
|
+
}
|
|
2498
|
+
return {
|
|
2499
|
+
current,
|
|
2500
|
+
currentLoading,
|
|
2501
|
+
hasPendingBilling,
|
|
2502
|
+
getUpcomingOrder,
|
|
2503
|
+
getUpcomingOrders,
|
|
2504
|
+
async getAdjustments() {
|
|
2505
|
+
return adapter.getAdjustments();
|
|
2506
|
+
},
|
|
2507
|
+
async skipOrder(params) {
|
|
2508
|
+
const result = await adapter.skipOrder(params);
|
|
2509
|
+
if (result._tag === "Success") {
|
|
2510
|
+
await reloadCurrent(params.subscriptionId);
|
|
2511
|
+
}
|
|
2512
|
+
return result;
|
|
2513
|
+
},
|
|
2514
|
+
async changeDateAdjustment(params) {
|
|
2515
|
+
const result = await adapter.changeDateAdjustment(params);
|
|
2516
|
+
if (result._tag === "Success") {
|
|
2517
|
+
await reloadCurrent(params.subscriptionId);
|
|
2518
|
+
}
|
|
2519
|
+
return result;
|
|
2520
|
+
},
|
|
2521
|
+
async removeAdjustment(params) {
|
|
2522
|
+
return adapter.removeAdjustment(params);
|
|
2523
|
+
},
|
|
2524
|
+
reloadCurrent
|
|
2525
|
+
};
|
|
2526
|
+
}
|
|
2527
|
+
const SettingsServiceContext = createContext("services/settings");
|
|
2528
|
+
function createSettingsService(initial = {}) {
|
|
2529
|
+
const current = d(initial);
|
|
2530
|
+
return {
|
|
2531
|
+
current,
|
|
2532
|
+
get(key) {
|
|
2533
|
+
return current.value[key];
|
|
2534
|
+
}
|
|
2535
|
+
};
|
|
2536
|
+
}
|
|
2537
|
+
function createShopService(options) {
|
|
2538
|
+
const contactEmail = d(options.getContactEmail());
|
|
2539
|
+
const service = { contactEmail };
|
|
2540
|
+
return service;
|
|
2541
|
+
}
|
|
2542
|
+
const ShopServiceContext = createContext("services/shop");
|
|
2344
2543
|
const SubscriptionServiceContext = createContext("services/subscription");
|
|
2345
2544
|
function getCurrentSubscriptionId() {
|
|
2346
2545
|
if (typeof window === "undefined") {
|
|
@@ -2398,6 +2597,14 @@ function createSubscriptionService(adapter) {
|
|
|
2398
2597
|
itemsChangedAt,
|
|
2399
2598
|
lastOrder,
|
|
2400
2599
|
search: adapter.search,
|
|
2600
|
+
// Prefer the adapter's rich cross-subscription list (legacy endpoint, active-first).
|
|
2601
|
+
// Fall back to a single `search` page for adapters that don't implement it
|
|
2602
|
+
// (e.g. the editor mock) so the cross-subscription views still render.
|
|
2603
|
+
listAll: adapter.listAll ? adapter.listAll.bind(adapter) : async () => {
|
|
2604
|
+
const result = await adapter.search();
|
|
2605
|
+
if (result._tag !== "Success") return result;
|
|
2606
|
+
return { _tag: "Success", data: result.data.items };
|
|
2607
|
+
},
|
|
2401
2608
|
getById: adapter.getById,
|
|
2402
2609
|
getCurrentSubscriptionId,
|
|
2403
2610
|
addItem: async (subscriptionId, item) => {
|
|
@@ -2746,13 +2953,14 @@ export {
|
|
|
2746
2953
|
AuthenticationError,
|
|
2747
2954
|
AuthenticationErrorReason,
|
|
2748
2955
|
B as BlockWrapperEvent,
|
|
2749
|
-
|
|
2750
|
-
|
|
2956
|
+
m as ContextProvideEvent,
|
|
2957
|
+
p as ContextRequestEvent,
|
|
2751
2958
|
CustomerServiceContext,
|
|
2752
2959
|
D2 as DEFAULT_GLOBAL_STYLES,
|
|
2753
2960
|
DISCOUNT_REJECTION_REASONS,
|
|
2754
2961
|
LoginServiceContext,
|
|
2755
2962
|
OrdersServiceContext,
|
|
2963
|
+
OverlayServiceContext,
|
|
2756
2964
|
ProductServiceContext,
|
|
2757
2965
|
RouterServiceContext,
|
|
2758
2966
|
SchedulesServiceContext,
|
|
@@ -2762,13 +2970,13 @@ export {
|
|
|
2762
2970
|
u as Signal,
|
|
2763
2971
|
StateContext,
|
|
2764
2972
|
SubscriptionServiceContext,
|
|
2765
|
-
|
|
2766
|
-
|
|
2973
|
+
a2 as ThemeStateContext,
|
|
2974
|
+
T as TranslationContext,
|
|
2767
2975
|
W as WorkflowServiceContext,
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2976
|
+
q as __recordDevtoolsInstance,
|
|
2977
|
+
_ as __recordDevtoolsPropSetter,
|
|
2978
|
+
t as attachEmptyTracking,
|
|
2979
|
+
b as backfillInstanceDefaults,
|
|
2772
2980
|
w as computed,
|
|
2773
2981
|
createApiCustomerAdapter,
|
|
2774
2982
|
createApiLoginAdapter,
|
|
@@ -2776,9 +2984,9 @@ export {
|
|
|
2776
2984
|
createApiSchedulesAdapter,
|
|
2777
2985
|
createApiSubscriptionAdapter,
|
|
2778
2986
|
createBlockInstance,
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2987
|
+
v as createBlockInstanceFromJSON,
|
|
2988
|
+
f as createBlockInstanceFromObject,
|
|
2989
|
+
x as createCeRenderer,
|
|
2782
2990
|
createContext,
|
|
2783
2991
|
createCustomerService,
|
|
2784
2992
|
createLoginService,
|
|
@@ -2791,41 +2999,42 @@ export {
|
|
|
2791
2999
|
createMockSubscriptionAdapter,
|
|
2792
3000
|
createMockWorkflowApiAdapter,
|
|
2793
3001
|
createOrdersService,
|
|
3002
|
+
createOverlayService,
|
|
2794
3003
|
createProductService,
|
|
2795
3004
|
createRouterService,
|
|
2796
3005
|
createSchedulesService,
|
|
2797
|
-
|
|
3006
|
+
y as createSelectedBlock,
|
|
2798
3007
|
createSettingsService,
|
|
2799
3008
|
createShopService,
|
|
2800
3009
|
createState,
|
|
2801
3010
|
createSubscriptionService,
|
|
2802
3011
|
c as createThemeState,
|
|
2803
|
-
|
|
3012
|
+
b2 as createTranslationService,
|
|
2804
3013
|
d2 as createWorkflowApiAdapter,
|
|
2805
|
-
|
|
3014
|
+
e as createWorkflowService,
|
|
2806
3015
|
defineBlock,
|
|
2807
|
-
|
|
3016
|
+
z as defineBlockRuntime,
|
|
2808
3017
|
defineOverlayWrapper,
|
|
2809
3018
|
E as effect,
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
3019
|
+
g as getDefaultBlockForAction,
|
|
3020
|
+
getDefinedBlocks,
|
|
3021
|
+
A as getDevtoolsBlockState,
|
|
3022
|
+
h as hasDefaultBlockForAction,
|
|
3023
|
+
D as hasRenderedContent,
|
|
2815
3024
|
i2 as indexOverrides,
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
3025
|
+
i as injectContext,
|
|
3026
|
+
F as isEditorPreview,
|
|
3027
|
+
a as isStubDefinition,
|
|
2819
3028
|
loadBlockRegistry,
|
|
2820
3029
|
loginService,
|
|
2821
|
-
|
|
2822
|
-
|
|
3030
|
+
o as onRegisterBlock,
|
|
3031
|
+
G as provideContext,
|
|
2823
3032
|
registerBlock,
|
|
2824
|
-
|
|
2825
|
-
|
|
3033
|
+
j as serializeBlocks,
|
|
3034
|
+
H as setDevtoolsBlockProp,
|
|
2826
3035
|
d as signal,
|
|
2827
|
-
|
|
2828
|
-
|
|
3036
|
+
s as subscribeContext,
|
|
3037
|
+
n as untracked,
|
|
2829
3038
|
waitForDevBlocksUrl,
|
|
2830
|
-
|
|
3039
|
+
w2 as withWrapper
|
|
2831
3040
|
};
|