@primestyleai/tryon 5.6.19 → 5.6.21
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/react/index.js
CHANGED
|
@@ -325,11 +325,23 @@ function getApiUrl(override) {
|
|
|
325
325
|
return override || process.env.NEXT_PUBLIC_PRIMESTYLE_API_URL || "http://localhost:4000";
|
|
326
326
|
}
|
|
327
327
|
async function recommendForProduct(input) {
|
|
328
|
+
const log = (...args) => console.log("[ps-sdk:recommend]", ...args);
|
|
328
329
|
const profile = input.profile ?? getActiveProfile();
|
|
329
|
-
if (!profile)
|
|
330
|
+
if (!profile) {
|
|
331
|
+
log("no active profile — returning null");
|
|
332
|
+
return null;
|
|
333
|
+
}
|
|
334
|
+
log("start", {
|
|
335
|
+
productId: input.productId,
|
|
336
|
+
profileId: profile.id,
|
|
337
|
+
profileName: profile.name,
|
|
338
|
+
hasMeasurements: !!profile.measurements && Object.keys(profile.measurements || {}).length,
|
|
339
|
+
measurementsCount: Object.keys(profile.measurements || {}).length
|
|
340
|
+
});
|
|
330
341
|
if (!input.skipCache) {
|
|
331
342
|
const cached = getCachedSize(profile, input.productId);
|
|
332
343
|
if (cached) {
|
|
344
|
+
log("cache HIT", { recommendedSize: cached.recommendedSize, hasSectionsFull: !!cached.sectionsFull });
|
|
333
345
|
const reconstructedRaw = cached.sectionsFull ? {
|
|
334
346
|
recommendedSize: cached.recommendedSize,
|
|
335
347
|
confidence: cached.confidence || "high",
|
|
@@ -357,14 +369,19 @@ async function recommendForProduct(input) {
|
|
|
357
369
|
};
|
|
358
370
|
}
|
|
359
371
|
}
|
|
372
|
+
log("cache MISS — calling backend");
|
|
360
373
|
let apiKey;
|
|
361
374
|
try {
|
|
362
375
|
apiKey = input.apiKey ?? getApiKey();
|
|
363
|
-
} catch {
|
|
376
|
+
} catch (e) {
|
|
377
|
+
log("no api key — aborting", e);
|
|
364
378
|
return null;
|
|
365
379
|
}
|
|
366
380
|
const apiUrl = (input.apiUrl ?? getApiUrl()).replace(/\/+$/, "");
|
|
367
|
-
if (!apiKey)
|
|
381
|
+
if (!apiKey) {
|
|
382
|
+
log("no api key — aborting");
|
|
383
|
+
return null;
|
|
384
|
+
}
|
|
368
385
|
let sizeGuide = null;
|
|
369
386
|
if (input.sizeGuideData != null) {
|
|
370
387
|
try {
|
|
@@ -376,9 +393,17 @@ async function recommendForProduct(input) {
|
|
|
376
393
|
sizeGuideRaw: input.sizeGuideData
|
|
377
394
|
})
|
|
378
395
|
});
|
|
379
|
-
if (sgRes.ok)
|
|
380
|
-
|
|
396
|
+
if (sgRes.ok) {
|
|
397
|
+
sizeGuide = await sgRes.json();
|
|
398
|
+
log("sizeguide OK", { found: sizeGuide?.found, sectionCount: Object.keys(sizeGuide?.sections || {}).length });
|
|
399
|
+
} else {
|
|
400
|
+
log("sizeguide FAILED", sgRes.status, sgRes.statusText);
|
|
401
|
+
}
|
|
402
|
+
} catch (e) {
|
|
403
|
+
log("sizeguide threw", e);
|
|
381
404
|
}
|
|
405
|
+
} else {
|
|
406
|
+
log("no sizeGuideData provided");
|
|
382
407
|
}
|
|
383
408
|
const measurements = {
|
|
384
409
|
gender: profile.gender,
|
|
@@ -407,6 +432,7 @@ async function recommendForProduct(input) {
|
|
|
407
432
|
if (sizeGuide && sizeGuide.found) {
|
|
408
433
|
payload.sizeGuide = sizeGuide;
|
|
409
434
|
}
|
|
435
|
+
log("calling /sizing/recommend", { measurements: Object.keys(measurements), hasSizeGuide: !!payload.sizeGuide });
|
|
410
436
|
let result = null;
|
|
411
437
|
try {
|
|
412
438
|
const res = await fetch(`${apiUrl}/api/v1/sizing/recommend`, {
|
|
@@ -414,12 +440,24 @@ async function recommendForProduct(input) {
|
|
|
414
440
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` },
|
|
415
441
|
body: JSON.stringify(payload)
|
|
416
442
|
});
|
|
417
|
-
if (!res.ok)
|
|
443
|
+
if (!res.ok) {
|
|
444
|
+
log("recommend FAILED", res.status, res.statusText);
|
|
445
|
+
return null;
|
|
446
|
+
}
|
|
418
447
|
result = await res.json();
|
|
419
|
-
|
|
448
|
+
log("recommend OK", {
|
|
449
|
+
recommendedSize: result?.recommendedSize,
|
|
450
|
+
sectionKeys: result?.sections ? Object.keys(result.sections) : null,
|
|
451
|
+
sections: result?.sections
|
|
452
|
+
});
|
|
453
|
+
} catch (e) {
|
|
454
|
+
log("recommend threw", e);
|
|
455
|
+
return null;
|
|
456
|
+
}
|
|
457
|
+
if (!result || !result.recommendedSize) {
|
|
458
|
+
log("recommend returned no recommendedSize — bailing");
|
|
420
459
|
return null;
|
|
421
460
|
}
|
|
422
|
-
if (!result || !result.recommendedSize) return null;
|
|
423
461
|
const sectionsMap = result.sections ? Object.fromEntries(
|
|
424
462
|
Object.entries(result.sections).map(([name, sec]) => [name, sec.recommendedSize])
|
|
425
463
|
) : void 0;
|
|
@@ -9399,6 +9437,7 @@ function BodyProfileView({
|
|
|
9399
9437
|
onUseActiveProfile,
|
|
9400
9438
|
activeProfileName,
|
|
9401
9439
|
onStartFresh,
|
|
9440
|
+
activeProfile,
|
|
9402
9441
|
onBack,
|
|
9403
9442
|
t
|
|
9404
9443
|
}) {
|
|
@@ -9407,15 +9446,42 @@ function BodyProfileView({
|
|
|
9407
9446
|
step === "photo" ? 0 : steps.indexOf(step);
|
|
9408
9447
|
const isMobile = useIsMobile();
|
|
9409
9448
|
const imperial = isImperial(sizingCountry);
|
|
9410
|
-
const
|
|
9411
|
-
const
|
|
9412
|
-
const
|
|
9413
|
-
const
|
|
9414
|
-
const
|
|
9449
|
+
const profileHeight = activeProfile?.height;
|
|
9450
|
+
const profileWeight = activeProfile?.weight;
|
|
9451
|
+
const profileAge = activeProfile?.age;
|
|
9452
|
+
const profileHUnit = activeProfile?.heightUnit === "ft" ? "in" : activeProfile?.heightUnit;
|
|
9453
|
+
const profileWUnit = activeProfile?.weightUnit;
|
|
9454
|
+
const seedHeightCm = (() => {
|
|
9455
|
+
if (profileHeight != null && profileHUnit === "cm") return String(Math.round(profileHeight));
|
|
9456
|
+
if (profileHeight != null && (profileHUnit === "in" || profileHUnit === "ft"))
|
|
9457
|
+
return String(Math.round(profileHeight * 2.54));
|
|
9458
|
+
return formRef.current.height || "173";
|
|
9459
|
+
})();
|
|
9460
|
+
const seedTotalIn = (() => {
|
|
9461
|
+
if (profileHeight != null && (profileHUnit === "in" || profileHUnit === "ft"))
|
|
9462
|
+
return Math.round(profileHeight);
|
|
9463
|
+
if (profileHeight != null && profileHUnit === "cm")
|
|
9464
|
+
return Math.round(profileHeight / 2.54);
|
|
9465
|
+
return null;
|
|
9466
|
+
})();
|
|
9467
|
+
const seedHeightFeet = seedTotalIn != null ? String(Math.floor(seedTotalIn / 12)) : formRef.current.heightFeet || "5";
|
|
9468
|
+
const seedHeightInches = seedTotalIn != null ? String(seedTotalIn % 12) : formRef.current.heightInches || "8";
|
|
9469
|
+
const seedWeight = (() => {
|
|
9470
|
+
if (profileWeight != null) return String(Math.round(profileWeight));
|
|
9471
|
+
return formRef.current.weight || (imperial ? "154" : "70");
|
|
9472
|
+
})();
|
|
9473
|
+
const seedAge = profileAge != null ? String(profileAge) : formRef.current.age || "30";
|
|
9474
|
+
const [height, setHeight] = useState(seedHeightCm);
|
|
9475
|
+
const [heightFeet, setHeightFeet] = useState(seedHeightFeet);
|
|
9476
|
+
const [heightInches, setHeightInches] = useState(seedHeightInches);
|
|
9477
|
+
const [weight, setWeight] = useState(seedWeight);
|
|
9478
|
+
const [age, setAge] = useState(seedAge);
|
|
9415
9479
|
const [hUnit, setHUnit] = useState(
|
|
9416
|
-
heightUnit === "ft" ? "in" : heightUnit || (imperial ? "in" : "cm")
|
|
9480
|
+
profileHUnit || (heightUnit === "ft" ? "in" : heightUnit || (imperial ? "in" : "cm"))
|
|
9481
|
+
);
|
|
9482
|
+
const [wUnit, setWUnit] = useState(
|
|
9483
|
+
profileWUnit || weightUnit || (imperial ? "lbs" : "kg")
|
|
9417
9484
|
);
|
|
9418
|
-
const [wUnit, setWUnit] = useState(weightUnit || (imperial ? "lbs" : "kg"));
|
|
9419
9485
|
const isImperialMode = hUnit === "in" || wUnit === "lbs";
|
|
9420
9486
|
const [photoFile, setPhotoFile] = useState(null);
|
|
9421
9487
|
const [photoPreview, setPhotoPreview] = useState(null);
|
|
@@ -11220,6 +11286,7 @@ function PrimeStyleTryonInner({
|
|
|
11220
11286
|
const p = profiles.find((x) => x.id === activeProfileId);
|
|
11221
11287
|
return p?.name || null;
|
|
11222
11288
|
})(),
|
|
11289
|
+
activeProfile: profiles.find((x) => x.id === activeProfileId) || null,
|
|
11223
11290
|
onStartFresh: () => {
|
|
11224
11291
|
setActiveProfileId$1(null);
|
|
11225
11292
|
formRef.current = {};
|
|
@@ -11245,7 +11312,8 @@ function PrimeStyleTryonInner({
|
|
|
11245
11312
|
onSnapSubmit: handleSnapSubmit,
|
|
11246
11313
|
onBack: handleClose,
|
|
11247
11314
|
t
|
|
11248
|
-
}
|
|
11315
|
+
},
|
|
11316
|
+
`bp-${activeProfileId || "anon"}`
|
|
11249
11317
|
) }, "v-bodyprofile");
|
|
11250
11318
|
}
|
|
11251
11319
|
case "estimation-review":
|
|
@@ -11476,15 +11544,19 @@ function usePrimeStyleSize(input) {
|
|
|
11476
11544
|
let cancelled = false;
|
|
11477
11545
|
setLoading(true);
|
|
11478
11546
|
setNoProfile(false);
|
|
11547
|
+
console.log("[ps-sdk:hook] usePrimeStyleSize start", { productId: input.productId });
|
|
11479
11548
|
recommendForProduct(input).then((res) => {
|
|
11480
11549
|
if (cancelled) return;
|
|
11481
11550
|
if (res === null) {
|
|
11551
|
+
console.log("[ps-sdk:hook] usePrimeStyleSize → null (no profile or recommendation failed)");
|
|
11482
11552
|
setNoProfile(true);
|
|
11483
11553
|
setResult(null);
|
|
11484
11554
|
} else {
|
|
11555
|
+
console.log("[ps-sdk:hook] usePrimeStyleSize → result", { recommendedSize: res.recommendedSize, hasRaw: !!res.raw });
|
|
11485
11556
|
setResult(res);
|
|
11486
11557
|
}
|
|
11487
|
-
}).catch(() => {
|
|
11558
|
+
}).catch((e) => {
|
|
11559
|
+
console.log("[ps-sdk:hook] usePrimeStyleSize threw", e);
|
|
11488
11560
|
if (!cancelled) setResult(null);
|
|
11489
11561
|
}).finally(() => {
|
|
11490
11562
|
if (!cancelled) setLoading(false);
|
|
@@ -48,8 +48,11 @@ interface BodyProfileViewProps {
|
|
|
48
48
|
/** Deselect the active profile so the user can run a fresh AI sizing flow
|
|
49
49
|
* with full body-shape questions. */
|
|
50
50
|
onStartFresh?: () => void;
|
|
51
|
+
/** Active profile — when set, its height/weight/age/gender seed the basics
|
|
52
|
+
* inputs so the SDK opens with the user's saved values, not the defaults. */
|
|
53
|
+
activeProfile?: import("../types").Profile | null;
|
|
51
54
|
onBack: () => void;
|
|
52
55
|
t: TranslateFn;
|
|
53
56
|
}
|
|
54
|
-
export declare function BodyProfileView({ productImage, productTitle, isWomen, formRef, sizingCountry, heightUnit, setHeightUnit, weightUnit, setWeightUnit, sizingUnit, setSizingUnit, onComplete, onSnapSubmit, hasActiveProfileWithMeasurements, onUseActiveProfile, activeProfileName, onStartFresh, onBack, t, }: BodyProfileViewProps): import("react/jsx-runtime").JSX.Element;
|
|
57
|
+
export declare function BodyProfileView({ productImage, productTitle, isWomen, formRef, sizingCountry, heightUnit, setHeightUnit, weightUnit, setWeightUnit, sizingUnit, setSizingUnit, onComplete, onSnapSubmit, hasActiveProfileWithMeasurements, onUseActiveProfile, activeProfileName, onStartFresh, activeProfile, onBack, t, }: BodyProfileViewProps): import("react/jsx-runtime").JSX.Element;
|
|
55
58
|
export {};
|