diff --git a/bun.lock b/bun.lock
index e1e980f..65002b4 100644
--- a/bun.lock
+++ b/bun.lock
@@ -146,7 +146,7 @@
"@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.6", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-4awhxtMh4cx9blePWl10HRHj8Iivtqj+2QdDCSMDzxG+XKa9+VCNupQuCuvzEhYPzZSrX+0gC+0lHA/0fFKKQQ=="],
- "@sveltejs/kit": ["@sveltejs/kit@2.46.5", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/cookie": "^0.6.0", "acorn": "^8.14.1", "cookie": "^0.6.0", "devalue": "^5.3.2", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", "sirv": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["@opentelemetry/api"], "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-7TSvMrCdmig5TMyYDW876C5FljhA0wlGixtvASCiqUqtLfmyEEpaysXjC7GhR5mWcGRrCGF+L2Bl1eEaW1wTCA=="],
+ "@sveltejs/kit": ["@sveltejs/kit@2.47.1", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/cookie": "^0.6.0", "acorn": "^8.14.1", "cookie": "^0.6.0", "devalue": "^5.3.2", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", "sirv": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["@opentelemetry/api"], "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-1v+MbMHxTi6ctQyxmz3owLKqZGaBHyx4EQqTdq/PvDswPFzw3WlqhrOKOh2ZzH23+XpQGEF9G+KDIgYJE+byvg=="],
"@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@6.2.1", "", { "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", "debug": "^4.4.1", "deepmerge": "^4.3.1", "magic-string": "^0.30.17", "vitefu": "^1.1.1" }, "peerDependencies": { "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ=="],
@@ -214,7 +214,7 @@
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
- "daisyui": ["daisyui@5.3.2", "", {}, "sha512-hw6NmQvFHdZI1Zb94EX+vA0DhuXGfqwQInDQ6XNZ5dgkoDy+e01P4OkJ8umAQAAzVSKGwm6QDMXOw6eJV63OEQ=="],
+ "daisyui": ["daisyui@5.3.7", "", {}, "sha512-0+8PaSGift0HlIQABCeZzWOBV5Nx/vsI2TihB9hbaEyZENPlZZz+se2JnAH5rz9gBYTyDLB7NJup8hkREr6WBw=="],
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
@@ -322,7 +322,7 @@
"strtok3": ["strtok3@10.3.4", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg=="],
- "svelte": ["svelte@5.40.0", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "esm-env": "^1.2.1", "esrap": "^2.1.0", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-EdA6LIo1vZVQOvlGfM18lhYM1k5Dkk/e93IlpzK4OVM6c11sUMHPgCtGFKmdy1WT4XqbpAvicq9JH5MTNoGaKw=="],
+ "svelte": ["svelte@5.40.2", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "esm-env": "^1.2.1", "esrap": "^2.1.0", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-wr/SwBVCVfeHU8FZr48vRrzSpWdBBzGo5mlErjGzeW4reJhK/CWutLZbk/eHwhKqO17ccjeTcvsqjrT4aK3wZA=="],
"svelte-adapter-bun": ["svelte-adapter-bun@0.5.2", "", { "dependencies": { "tiny-glob": "^0.2.9" } }, "sha512-xEtFgaal6UgrCwwkSIcapO9kopoFNUYCYqyKCikdqxX9bz2TDYnrWQZ7qBnkunMxi1HOIERUCvTcebYGiarZLA=="],
diff --git a/package.json b/package.json
index ca68f20..4413fa1 100644
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
{
"type": "module",
"devDependencies": {
- "@sveltejs/kit": "^2.46.5",
+ "@sveltejs/kit": "^2.47.1",
"@sveltejs/vite-plugin-svelte": "^6.2.1",
"@types/bun": "^1.3.0",
- "svelte": "^5.40.0",
+ "svelte": "^5.40.2",
"svelte-adapter-bun": "^0.5.2",
"svelte-check": "^4.3.3",
"typescript": "^5.9.3",
@@ -22,7 +22,7 @@
"@elysiajs/cors": "^1.4.0",
"@elysiajs/eden": "^1.4.4",
"@tailwindcss/vite": "^4.1.14",
- "daisyui": "^5.3.2",
+ "daisyui": "^5.3.7",
"elysia": "^1.4.12",
"memoirist": "^0.4.0",
"tailwindcss": "^4.1.14"
diff --git a/src/lib/components/StandardsTable.svelte b/src/lib/components/StandardsTable.svelte
index 03e1253..87b9616 100644
--- a/src/lib/components/StandardsTable.svelte
+++ b/src/lib/components/StandardsTable.svelte
@@ -52,7 +52,7 @@
- {#if !selected.cfg.disableGeneration && allStandards
+ {#if !selected.cfg.activity[selected.activity].disableGeneration && allStandards
.byActivity(selected.activity)
.getMetadata().generators.length}
(Generated data: {allStandards
@@ -87,7 +87,7 @@
? parseFloat(kgToLb(standard.metrics.weight).toFixed(2))
: "None"}
- {#each range(selected.cfg.maxLevel) as lvl}
+ {#each range(selected.cfg.global.maxLevel) as lvl}
{getLvlValue(activity, standard, lvl)} |
{/each}
@@ -99,7 +99,7 @@
| Body weight |
- {#each range(selected.cfg.maxLevel) as lvl}
+ {#each range(selected.cfg.global.maxLevel) as lvl}
{lvl} |
{/each}
diff --git a/src/lib/server/app.ts b/src/lib/server/app.ts
index 744a9d6..5c12a22 100644
--- a/src/lib/server/app.ts
+++ b/src/lib/server/app.ts
@@ -82,7 +82,14 @@ export const app = new Elysia({ prefix: "/api" })
}
case Printful.Webhook.Event.PackageShipped: {
const webflowOrderId = payload.data.order.external_id;
- await WebflowService.Orders.update(webflowOrderId, { status: "fulfilled" });
+ const shipInfo = payload.data.shipment;
+
+ await WebflowService.Orders.update(webflowOrderId, {
+ shippingTrackingURL: shipInfo.tracking_url,
+ shippingTracking: shipInfo.tracking_number,
+ shippingProvider: shipInfo.carrier
+ });
+ await WebflowService.Orders.fulfill(webflowOrderId, { sendOrderFulfilledEmail: true });
break;
}
}
@@ -118,10 +125,6 @@ export const app = new Elysia({ prefix: "/api" })
}))
});
- // set webflow order to pending
- webflowOrder.status = "pending";
- await WebflowService.Orders.update(webflowOrder.orderId, webflowOrder);
-
console.log("Complete");
break;
diff --git a/src/lib/services/commerce/util/types.ts b/src/lib/services/commerce/util/types.ts
index c9adcd1..3d94fa6 100644
--- a/src/lib/services/commerce/util/types.ts
+++ b/src/lib/services/commerce/util/types.ts
@@ -148,24 +148,19 @@ export namespace Printful {
export interface PackageShipped extends MetaData { }
diff --git a/src/lib/services/commerce/webflow.ts b/src/lib/services/commerce/webflow.ts
index f03e5c4..49f3a84 100644
--- a/src/lib/services/commerce/webflow.ts
+++ b/src/lib/services/commerce/webflow.ts
@@ -125,20 +125,55 @@ export default class WebflowService {
}
static Orders = class {
- static async update(webflowOrderId: string, webflowOrder: DeepPartial) {
+ static async getAll(opt: { status?: Webflow.Orders.Order["status"] } = {}): Promise {
+ // TODO: pagination
+ const params = new URLSearchParams();
+ if (opt.status !== undefined) {
+ params.set("status", opt.status);
+ }
+
+ const res = await fetch(`${env().API_SITES_URL}/orders?${params.toString()}`, {
+ method: "GET",
+ headers: { ...env().AUTH_HEADER },
+ });
+
+ if (!res.ok) {
+ throw new FetchError("Failed to get all Webflow orders", res);
+ }
+
+ const payload = await res.json();
+ return payload.orders as Webflow.Orders.Order[];
+ }
+
+ static async update(webflowOrderId: string, webflowOrderUpdate: { comment?: string, shippingProvider?: string, shippingTracking?: string, shippingTrackingURL: string }) {
const res = await fetch(`${env().API_SITES_URL}/orders/${webflowOrderId}`, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
...env().AUTH_HEADER
},
- body: JSON.stringify(webflowOrder)
+ body: JSON.stringify(webflowOrderUpdate)
});
if (!res.ok) {
throw new FetchError("Failed to update Webflow order", res);
}
}
+
+ static async fulfill(webflowOrderId: string, opt: { sendOrderFulfilledEmail?: boolean } = {}) {
+ const res = await fetch(`${env().API_SITES_URL}/orders/${webflowOrderId}/fulfill`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ ...env().AUTH_HEADER
+ },
+ body: JSON.stringify(opt)
+ });
+
+ if (!res.ok) {
+ throw new FetchError("Failed to fulfill Webflow order", res);
+ }
+ }
}
static Util = class {
diff --git a/src/lib/test/scratch.ts b/src/lib/test/scratch.ts
index 867ea16..85b44a3 100644
--- a/src/lib/test/scratch.ts
+++ b/src/lib/test/scratch.ts
@@ -46,71 +46,75 @@ const computedPerformances: ActivityPerformance[] = [
},
];
+const wOrders = await WebflowService.Orders.getAll();
+
+console.log(wOrders);
+
// wProduct.product.fieldData.name = "Rogue Title Hoodie [White] / XS";
//
// WebflowService.Products.update("68e66dc4633e577c91eda727",);
-const printfulProducts = await PrintfulService.Products.getAll();
-const webflowProducts = await WebflowService.Products.getAll();
-
-for (const printfulProduct of printfulProducts) {
- if (!printfulProduct.name.includes("T-Shirt") || printfulProduct.name.includes("[White]") || printfulProduct.name.includes("[Black]")) {
- continue;
- }
-
- console.log(printfulProduct.name);
-
- const fullPrintfulProduct = await PrintfulService.Products.get(printfulProduct.id);
- if (!fullPrintfulProduct) {
- console.log("Could not get full product, skipped");
- continue;
- }
-
- const existingWebflowProduct = webflowProducts.find(p => fullPrintfulProduct.sync_product.name.includes(p.product.fieldData.name))
- if (!existingWebflowProduct) {
- console.log("Could not get associated webflow product, skipped");
- continue;
- }
-
- const newPrintfulVariants: DeepPartial[] = [];
- for (const printfulVariant of fullPrintfulProduct.sync_variants) {
- console.log(printfulVariant.name);
- const associatedWebflowSku = existingWebflowProduct.skus
- .find(sku => sku.fieldData["sku-values"]?.["color"] === SyncService.findColorInProductName(printfulVariant.name) &&
- sku.fieldData["sku-values"]?.["size"] === printfulVariant.size);
- if (associatedWebflowSku) {
- console.log('Found associated webflow sku: ' + associatedWebflowSku.fieldData.name);
- newPrintfulVariants.push({
- "id": printfulVariant.id, // printful variant id
- "external_id": String(associatedWebflowSku.id), // webflow variant id
- });
- }
- else {
- console.log("Could not get associated webflow sku");
- }
- }
-
- if (!newPrintfulVariants.length) {
- console.log("No new printful variants, skipped");
- continue;
- }
-
- await sleep(3000);
- try {
- await PrintfulService.Products.update(printfulProduct.id, {
- "sync_product": {
- "id": printfulProduct.id,
- "external_id": existingWebflowProduct.product.id + "-" + SyncService.findColorInProductName(printfulProduct.name)
- },
- "sync_variants": newPrintfulVariants
- });
- } catch (err) {
- if (err instanceof FetchError) {
- console.error(err.message, err.payload);
- }
- }
-}
-console.log("DONE");
+// const printfulProducts = await PrintfulService.Products.getAll();
+// const webflowProducts = await WebflowService.Products.getAll();
+//
+// for (const printfulProduct of printfulProducts) {
+// if (!printfulProduct.name.includes("T-Shirt") || printfulProduct.name.includes("[White]") || printfulProduct.name.includes("[Black]")) {
+// continue;
+// }
+//
+// console.log(printfulProduct.name);
+//
+// const fullPrintfulProduct = await PrintfulService.Products.get(printfulProduct.id);
+// if (!fullPrintfulProduct) {
+// console.log("Could not get full product, skipped");
+// continue;
+// }
+//
+// const existingWebflowProduct = webflowProducts.find(p => fullPrintfulProduct.sync_product.name.includes(p.product.fieldData.name))
+// if (!existingWebflowProduct) {
+// console.log("Could not get associated webflow product, skipped");
+// continue;
+// }
+//
+// const newPrintfulVariants: DeepPartial[] = [];
+// for (const printfulVariant of fullPrintfulProduct.sync_variants) {
+// console.log(printfulVariant.name);
+// const associatedWebflowSku = existingWebflowProduct.skus
+// .find(sku => sku.fieldData["sku-values"]?.["color"] === SyncService.findColorInProductName(printfulVariant.name) &&
+// sku.fieldData["sku-values"]?.["size"] === printfulVariant.size);
+// if (associatedWebflowSku) {
+// console.log('Found associated webflow sku: ' + associatedWebflowSku.fieldData.name);
+// newPrintfulVariants.push({
+// "id": printfulVariant.id, // printful variant id
+// "external_id": String(associatedWebflowSku.id), // webflow variant id
+// });
+// }
+// else {
+// console.log("Could not get associated webflow sku");
+// }
+// }
+//
+// if (!newPrintfulVariants.length) {
+// console.log("No new printful variants, skipped");
+// continue;
+// }
+//
+// await sleep(3000);
+// try {
+// await PrintfulService.Products.update(printfulProduct.id, {
+// "sync_product": {
+// "id": printfulProduct.id,
+// "external_id": existingWebflowProduct.product.id + "-" + SyncService.findColorInProductName(printfulProduct.name)
+// },
+// "sync_variants": newPrintfulVariants
+// });
+// } catch (err) {
+// if (err instanceof FetchError) {
+// console.error(err.message, err.payload);
+// }
+// }
+// }
+// console.log("DONE");
// await WebflowService.Products.update(wProduct?.product.id!, wProduct!);
diff --git a/src/routes/calculator/+page.svelte b/src/routes/calculator/+page.svelte
index da69665..b8a3c79 100644
--- a/src/routes/calculator/+page.svelte
+++ b/src/routes/calculator/+page.svelte
@@ -12,7 +12,7 @@
let activeTab = $state("standards");
- let input = $state({
+ let inputSelected = $state({
activity: Activity.BenchPress,
metrics: {
gender: Gender.Male,
@@ -28,7 +28,7 @@
activity,
{
enableGeneration: true,
- weightModfier: ".1",
+ weightModifier: ".1",
weightSkew: "0",
ageModifier: ".1",
},
@@ -38,26 +38,30 @@
});
const selected = $derived({
- activity: input.activity,
+ activity: inputSelected.activity,
metrics: {
- gender: input.metrics.gender,
- age: +input.metrics.age,
- weight: lbToKg(+input.metrics.weight),
+ gender: inputSelected.metrics.gender,
+ age: +inputSelected.metrics.age,
+ weight: lbToKg(+inputSelected.metrics.weight),
} as Metrics,
cfg: {
global: {
- maxLevel: +input.cfg.global.maxLevel,
+ maxLevel: +inputSelected.cfg.global.maxLevel,
},
activity: Object.fromEntries(
Object.values(Activity).map((activity) => [
activity,
{
weightModifier:
- +input.cfg.activity[activity].weightModfier,
- weightSkew: +input.cfg.activity[activity].weightSkew,
- ageModifier: +input.cfg.activity[activity].ageModifier,
+ +inputSelected.cfg.activity[activity]
+ .weightModifier,
+ weightSkew:
+ +inputSelected.cfg.activity[activity].weightSkew,
+ ageModifier:
+ +inputSelected.cfg.activity[activity].ageModifier,
disableGeneration:
- !input.cfg.activity[activity].enableGeneration,
+ !inputSelected.cfg.activity[activity]
+ .enableGeneration,
},
]),
),
@@ -70,16 +74,16 @@
$effect(() => {
console.log(selected);
- if (!input.metrics.age) input.metrics.weight = "";
+ if (!inputSelected.metrics.age) inputSelected.metrics.weight = "";
});
$effect(() => {
const savedParameters = localStorage.getItem("parameters");
- if (savedParameters) input = JSON.parse(savedParameters);
+ if (savedParameters) inputSelected = JSON.parse(savedParameters);
});
$effect(() => {
- localStorage.setItem("parameters", JSON.stringify(input));
+ localStorage.setItem("parameters", JSON.stringify(inputSelected));
});
@@ -102,7 +106,7 @@
min="1"
max="100"
placeholder="5"
- bind:value={input.cfg.global.maxLevel}
+ bind:value={inputSelected.cfg.global.maxLevel}
/>
@@ -118,7 +122,7 @@
{#each Object.values(Activity) as activity}