@thefittingroom/shop-ui 4.1.0 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +123 -51
- package/dist/index.umd.cjs +123 -51
- package/package.json +4 -1
- package/.env.development +0 -13
- package/.env.example +0 -23
- package/.env.production +0 -14
- package/AGENTS.md +0 -8
- package/index.html +0 -274
- package/vite.config.js +0 -39
package/dist/index.js
CHANGED
|
@@ -16,45 +16,111 @@ if (typeof document !== "undefined") {
|
|
|
16
16
|
styleElement.textContent = allCSS;
|
|
17
17
|
document.head.appendChild(styleElement);
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
19
|
+
const TheFittingRoom = "The Fitting Room";
|
|
20
|
+
const VirtualTryOnWith = "Virtual try on with";
|
|
21
|
+
const EmailAddress = "Email address";
|
|
22
|
+
const Password = "Password";
|
|
23
|
+
const PhoneNumber = "Phone number";
|
|
24
|
+
const SignBackIn = "Sign back in";
|
|
25
|
+
const SignUp = "Sign up";
|
|
26
|
+
const SignOut = "Sign out";
|
|
27
|
+
const SignIn = "Sign in";
|
|
28
|
+
const ForgotPassword = "Forgot password";
|
|
29
|
+
const BackToSignIn = "Back to sign in";
|
|
30
|
+
const Send = "Send";
|
|
31
|
+
const ReturnToSignIn = "Return to sign in";
|
|
32
|
+
const ForgotPasswordWithSymbol = "Forgot password?";
|
|
33
|
+
const DontHaveAcc = "Don't have an account?";
|
|
34
|
+
const HaveAcc = "Have an account? Sign in";
|
|
35
|
+
const HowItWorks = "How it works";
|
|
36
|
+
const HowItWorksText = "The Fitting Room has partnered with your favourite designers to enable you to virtually try on garments, so you will know exactly how it will look before purchasing. Say good-bye to the days of dealing with returns!";
|
|
37
|
+
const SimplyScan = "Simply scan,";
|
|
38
|
+
const SimplyScanText = "Download The Fitting Room app, create an account, follow the easy set up steps, and then scan yourself using just your smartphone to create your personal lifelike avatar.";
|
|
39
|
+
const TryOn = "and try on.";
|
|
40
|
+
const TryOnText = "After creating your avatar, return here and sign in. We will use the measurements from your avatar to tell you which size will fit you best, as well as let you try the garment on - all without leaving your house!";
|
|
41
|
+
const Or = "Or";
|
|
42
|
+
const DontHaveAvatar = "Whoops! Looks like you don't have an avatar yet.";
|
|
43
|
+
const LoadingAvatar = "Your avatar is loading...";
|
|
44
|
+
const ReturnToTFR = "Please return to The Fitting Room app to create your avatar.";
|
|
45
|
+
const SuccessfullyLoggedOut = "You have successfully logged out!";
|
|
46
|
+
const ReturnToSite = "Return to site";
|
|
47
|
+
const ModalTitle = "Enter your email address to be notified when The Fitting Room try on is offered on Google Play:";
|
|
48
|
+
const EnterEmailAddress = "Enter your email address, we will send you a link to reset your password.";
|
|
49
|
+
const EnterPhoneNumber = "Enter your phone number to be texted a link to download The Fitting Room app.";
|
|
50
|
+
const StyleNotReadyForVTO = "This style is not ready for virtual try on yet. Please check back later.";
|
|
51
|
+
const NoSizeAvailable = "Unfortunately, that size is not available for try on.";
|
|
52
|
+
const TrySize = "You can try on a size";
|
|
53
|
+
const OrSize = "or";
|
|
54
|
+
const WeRecommendSize = "We recommend a size";
|
|
55
|
+
const AssociatedEmail = "If there is an account associated with that email, We have sent a link to reset your password.";
|
|
56
|
+
const CreateAvatarSc = "Scan the QR code/click link to download our app and create an avatar:";
|
|
57
|
+
const SomethingWentWrong = "Something went wrong. Try again!";
|
|
58
|
+
const SignOutErrorText = "Something went wrong while logging out. Try again!";
|
|
59
|
+
const GetVirtualTryOnFramesErrorText = "The try-on request timed out. Please try again!";
|
|
60
|
+
const GetRecommendedSizesErrorText = "Something went wrong while fetching sizes. Try again!";
|
|
61
|
+
const SendPasswordResetEmailErrorText = "Something went wrong while sending password reset email. Try again!";
|
|
62
|
+
const ReturnToCatalogPage = "Return to Catalog Page";
|
|
63
|
+
const ReturnToProductPage = "Return to Product Page";
|
|
64
|
+
const Loading = "Loading...";
|
|
65
|
+
const SomethingIsWrongWithThisUser = "Something is wrong with this user. Try to re-authenticate again!";
|
|
66
|
+
const FailedToLoadLocale = "Something went wrong when fetching another language.";
|
|
67
|
+
const UsernameOrPasswordIncorrect = "Username or password is incorrect.";
|
|
68
|
+
const UsernameOrPasswordEmpty = "Username or password is empty.";
|
|
69
|
+
const StyleNotFound = "style sku was not found";
|
|
70
|
+
const en$1 = {
|
|
71
|
+
TheFittingRoom,
|
|
72
|
+
VirtualTryOnWith,
|
|
73
|
+
EmailAddress,
|
|
74
|
+
Password,
|
|
75
|
+
PhoneNumber,
|
|
76
|
+
SignBackIn,
|
|
77
|
+
SignUp,
|
|
78
|
+
SignOut,
|
|
79
|
+
SignIn,
|
|
80
|
+
ForgotPassword,
|
|
81
|
+
BackToSignIn,
|
|
82
|
+
Send,
|
|
83
|
+
ReturnToSignIn,
|
|
84
|
+
ForgotPasswordWithSymbol,
|
|
85
|
+
DontHaveAcc,
|
|
86
|
+
HaveAcc,
|
|
87
|
+
HowItWorks,
|
|
88
|
+
HowItWorksText,
|
|
89
|
+
SimplyScan,
|
|
90
|
+
SimplyScanText,
|
|
91
|
+
TryOn,
|
|
92
|
+
TryOnText,
|
|
93
|
+
Or,
|
|
94
|
+
DontHaveAvatar,
|
|
95
|
+
LoadingAvatar,
|
|
96
|
+
ReturnToTFR,
|
|
97
|
+
SuccessfullyLoggedOut,
|
|
98
|
+
ReturnToSite,
|
|
99
|
+
ModalTitle,
|
|
100
|
+
EnterEmailAddress,
|
|
101
|
+
EnterPhoneNumber,
|
|
102
|
+
StyleNotReadyForVTO,
|
|
103
|
+
NoSizeAvailable,
|
|
104
|
+
TrySize,
|
|
105
|
+
OrSize,
|
|
106
|
+
WeRecommendSize,
|
|
107
|
+
AssociatedEmail,
|
|
108
|
+
CreateAvatarSc,
|
|
109
|
+
SomethingWentWrong,
|
|
110
|
+
SignOutErrorText,
|
|
111
|
+
GetVirtualTryOnFramesErrorText,
|
|
112
|
+
GetRecommendedSizesErrorText,
|
|
113
|
+
SendPasswordResetEmailErrorText,
|
|
114
|
+
ReturnToCatalogPage,
|
|
115
|
+
ReturnToProductPage,
|
|
116
|
+
Loading,
|
|
117
|
+
SomethingIsWrongWithThisUser,
|
|
118
|
+
FailedToLoadLocale,
|
|
119
|
+
UsernameOrPasswordIncorrect,
|
|
120
|
+
UsernameOrPasswordEmpty,
|
|
121
|
+
StyleNotFound
|
|
57
122
|
};
|
|
123
|
+
var L$1 = en$1;
|
|
58
124
|
const ErrorModal = (props) => {
|
|
59
125
|
const { error } = props;
|
|
60
126
|
const onNavBack = () => {
|
|
@@ -20399,21 +20465,27 @@ class FittingRoomAPI {
|
|
|
20399
20465
|
});
|
|
20400
20466
|
return colorwaySizeAssets;
|
|
20401
20467
|
}
|
|
20402
|
-
|
|
20403
|
-
|
|
20404
|
-
|
|
20405
|
-
if (!styleSKU) throw new Error("styleSKU is required for GetStyleByBrandStyleID");
|
|
20406
|
-
const isLoggedIn = await this.IsLoggedIn();
|
|
20407
|
-
console.debug("isLoggedIn", isLoggedIn, "BrandID:", this.BrandID);
|
|
20468
|
+
async GetStyleByExernalID(externalID) {
|
|
20469
|
+
if (!externalID) throw new Error("externalID is required for GetStyleByExernalID");
|
|
20470
|
+
await this.IsLoggedIn();
|
|
20408
20471
|
try {
|
|
20409
20472
|
const constraints = [where("brand_id", "==", this.BrandID)];
|
|
20410
|
-
constraints.push(where("
|
|
20473
|
+
constraints.push(where("external_id", "==", externalID));
|
|
20474
|
+
console.debug("Debug: Executing Firestore query with constraints:", {
|
|
20475
|
+
brand_id: this.BrandID,
|
|
20476
|
+
external_id: externalID
|
|
20477
|
+
});
|
|
20411
20478
|
const querySnapshot = await this.firebase.getDocs("styles", constraints);
|
|
20479
|
+
console.debug("Debug: Firestore query result:", {
|
|
20480
|
+
size: querySnapshot.size,
|
|
20481
|
+
empty: querySnapshot.empty,
|
|
20482
|
+
externalID
|
|
20483
|
+
});
|
|
20412
20484
|
const style = querySnapshot.docs?.[0]?.data();
|
|
20413
20485
|
console.debug("style fetched by brand id:", style);
|
|
20414
20486
|
return style;
|
|
20415
20487
|
} catch (error) {
|
|
20416
|
-
console.debug("
|
|
20488
|
+
console.debug("GetStyleByExernalID error:", externalID, error);
|
|
20417
20489
|
return getFirebaseError(error);
|
|
20418
20490
|
}
|
|
20419
20491
|
}
|
|
@@ -21879,9 +21951,9 @@ const validatePassword = (password) => {
|
|
|
21879
21951
|
return false;
|
|
21880
21952
|
};
|
|
21881
21953
|
class FittingRoomController {
|
|
21882
|
-
constructor(env, shopID,
|
|
21954
|
+
constructor(env, shopID, externalID, noCacheOnRetry = false, modalDivId, sizeRecMainDivId, vtoMainDivId, cssVariables, hooks = {}) {
|
|
21883
21955
|
this.shopID = shopID;
|
|
21884
|
-
this.
|
|
21956
|
+
this.externalID = externalID;
|
|
21885
21957
|
this.noCacheOnRetry = noCacheOnRetry;
|
|
21886
21958
|
this.hooks = hooks;
|
|
21887
21959
|
this.hasInitializedTryOn = false;
|
|
@@ -21929,7 +22001,7 @@ class FittingRoomController {
|
|
|
21929
22001
|
console.debug("init");
|
|
21930
22002
|
try {
|
|
21931
22003
|
const authUserPromise = this.firebaseAuthUserController.GetUserOrNotLoggedIn();
|
|
21932
|
-
const stylePromise = this.API.
|
|
22004
|
+
const stylePromise = this.API.GetStyleByExernalID(this.externalID);
|
|
21933
22005
|
await Promise.all([authUserPromise, stylePromise]);
|
|
21934
22006
|
console.debug("promise all ready");
|
|
21935
22007
|
const style = await stylePromise;
|
|
@@ -22137,7 +22209,7 @@ class FittingRoomController {
|
|
|
22137
22209
|
const initFittingRoom = async ({
|
|
22138
22210
|
env,
|
|
22139
22211
|
shopId,
|
|
22140
|
-
|
|
22212
|
+
externalID,
|
|
22141
22213
|
modalDivId,
|
|
22142
22214
|
sizeRecMainDivId,
|
|
22143
22215
|
vtoMainDivId,
|
|
@@ -22149,7 +22221,7 @@ const initFittingRoom = async ({
|
|
|
22149
22221
|
const tfr = new FittingRoomController(
|
|
22150
22222
|
env,
|
|
22151
22223
|
shopId,
|
|
22152
|
-
|
|
22224
|
+
externalID,
|
|
22153
22225
|
noCacheOnRetry,
|
|
22154
22226
|
modalDivId,
|
|
22155
22227
|
sizeRecMainDivId,
|
package/dist/index.umd.cjs
CHANGED
|
@@ -20,45 +20,111 @@
|
|
|
20
20
|
styleElement.textContent = allCSS;
|
|
21
21
|
document.head.appendChild(styleElement);
|
|
22
22
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
23
|
+
const TheFittingRoom = "The Fitting Room";
|
|
24
|
+
const VirtualTryOnWith = "Virtual try on with";
|
|
25
|
+
const EmailAddress = "Email address";
|
|
26
|
+
const Password = "Password";
|
|
27
|
+
const PhoneNumber = "Phone number";
|
|
28
|
+
const SignBackIn = "Sign back in";
|
|
29
|
+
const SignUp = "Sign up";
|
|
30
|
+
const SignOut = "Sign out";
|
|
31
|
+
const SignIn = "Sign in";
|
|
32
|
+
const ForgotPassword = "Forgot password";
|
|
33
|
+
const BackToSignIn = "Back to sign in";
|
|
34
|
+
const Send = "Send";
|
|
35
|
+
const ReturnToSignIn = "Return to sign in";
|
|
36
|
+
const ForgotPasswordWithSymbol = "Forgot password?";
|
|
37
|
+
const DontHaveAcc = "Don't have an account?";
|
|
38
|
+
const HaveAcc = "Have an account? Sign in";
|
|
39
|
+
const HowItWorks = "How it works";
|
|
40
|
+
const HowItWorksText = "The Fitting Room has partnered with your favourite designers to enable you to virtually try on garments, so you will know exactly how it will look before purchasing. Say good-bye to the days of dealing with returns!";
|
|
41
|
+
const SimplyScan = "Simply scan,";
|
|
42
|
+
const SimplyScanText = "Download The Fitting Room app, create an account, follow the easy set up steps, and then scan yourself using just your smartphone to create your personal lifelike avatar.";
|
|
43
|
+
const TryOn = "and try on.";
|
|
44
|
+
const TryOnText = "After creating your avatar, return here and sign in. We will use the measurements from your avatar to tell you which size will fit you best, as well as let you try the garment on - all without leaving your house!";
|
|
45
|
+
const Or = "Or";
|
|
46
|
+
const DontHaveAvatar = "Whoops! Looks like you don't have an avatar yet.";
|
|
47
|
+
const LoadingAvatar = "Your avatar is loading...";
|
|
48
|
+
const ReturnToTFR = "Please return to The Fitting Room app to create your avatar.";
|
|
49
|
+
const SuccessfullyLoggedOut = "You have successfully logged out!";
|
|
50
|
+
const ReturnToSite = "Return to site";
|
|
51
|
+
const ModalTitle = "Enter your email address to be notified when The Fitting Room try on is offered on Google Play:";
|
|
52
|
+
const EnterEmailAddress = "Enter your email address, we will send you a link to reset your password.";
|
|
53
|
+
const EnterPhoneNumber = "Enter your phone number to be texted a link to download The Fitting Room app.";
|
|
54
|
+
const StyleNotReadyForVTO = "This style is not ready for virtual try on yet. Please check back later.";
|
|
55
|
+
const NoSizeAvailable = "Unfortunately, that size is not available for try on.";
|
|
56
|
+
const TrySize = "You can try on a size";
|
|
57
|
+
const OrSize = "or";
|
|
58
|
+
const WeRecommendSize = "We recommend a size";
|
|
59
|
+
const AssociatedEmail = "If there is an account associated with that email, We have sent a link to reset your password.";
|
|
60
|
+
const CreateAvatarSc = "Scan the QR code/click link to download our app and create an avatar:";
|
|
61
|
+
const SomethingWentWrong = "Something went wrong. Try again!";
|
|
62
|
+
const SignOutErrorText = "Something went wrong while logging out. Try again!";
|
|
63
|
+
const GetVirtualTryOnFramesErrorText = "The try-on request timed out. Please try again!";
|
|
64
|
+
const GetRecommendedSizesErrorText = "Something went wrong while fetching sizes. Try again!";
|
|
65
|
+
const SendPasswordResetEmailErrorText = "Something went wrong while sending password reset email. Try again!";
|
|
66
|
+
const ReturnToCatalogPage = "Return to Catalog Page";
|
|
67
|
+
const ReturnToProductPage = "Return to Product Page";
|
|
68
|
+
const Loading = "Loading...";
|
|
69
|
+
const SomethingIsWrongWithThisUser = "Something is wrong with this user. Try to re-authenticate again!";
|
|
70
|
+
const FailedToLoadLocale = "Something went wrong when fetching another language.";
|
|
71
|
+
const UsernameOrPasswordIncorrect = "Username or password is incorrect.";
|
|
72
|
+
const UsernameOrPasswordEmpty = "Username or password is empty.";
|
|
73
|
+
const StyleNotFound = "style sku was not found";
|
|
74
|
+
const en$1 = {
|
|
75
|
+
TheFittingRoom,
|
|
76
|
+
VirtualTryOnWith,
|
|
77
|
+
EmailAddress,
|
|
78
|
+
Password,
|
|
79
|
+
PhoneNumber,
|
|
80
|
+
SignBackIn,
|
|
81
|
+
SignUp,
|
|
82
|
+
SignOut,
|
|
83
|
+
SignIn,
|
|
84
|
+
ForgotPassword,
|
|
85
|
+
BackToSignIn,
|
|
86
|
+
Send,
|
|
87
|
+
ReturnToSignIn,
|
|
88
|
+
ForgotPasswordWithSymbol,
|
|
89
|
+
DontHaveAcc,
|
|
90
|
+
HaveAcc,
|
|
91
|
+
HowItWorks,
|
|
92
|
+
HowItWorksText,
|
|
93
|
+
SimplyScan,
|
|
94
|
+
SimplyScanText,
|
|
95
|
+
TryOn,
|
|
96
|
+
TryOnText,
|
|
97
|
+
Or,
|
|
98
|
+
DontHaveAvatar,
|
|
99
|
+
LoadingAvatar,
|
|
100
|
+
ReturnToTFR,
|
|
101
|
+
SuccessfullyLoggedOut,
|
|
102
|
+
ReturnToSite,
|
|
103
|
+
ModalTitle,
|
|
104
|
+
EnterEmailAddress,
|
|
105
|
+
EnterPhoneNumber,
|
|
106
|
+
StyleNotReadyForVTO,
|
|
107
|
+
NoSizeAvailable,
|
|
108
|
+
TrySize,
|
|
109
|
+
OrSize,
|
|
110
|
+
WeRecommendSize,
|
|
111
|
+
AssociatedEmail,
|
|
112
|
+
CreateAvatarSc,
|
|
113
|
+
SomethingWentWrong,
|
|
114
|
+
SignOutErrorText,
|
|
115
|
+
GetVirtualTryOnFramesErrorText,
|
|
116
|
+
GetRecommendedSizesErrorText,
|
|
117
|
+
SendPasswordResetEmailErrorText,
|
|
118
|
+
ReturnToCatalogPage,
|
|
119
|
+
ReturnToProductPage,
|
|
120
|
+
Loading,
|
|
121
|
+
SomethingIsWrongWithThisUser,
|
|
122
|
+
FailedToLoadLocale,
|
|
123
|
+
UsernameOrPasswordIncorrect,
|
|
124
|
+
UsernameOrPasswordEmpty,
|
|
125
|
+
StyleNotFound
|
|
61
126
|
};
|
|
127
|
+
var L$1 = en$1;
|
|
62
128
|
const ErrorModal = (props) => {
|
|
63
129
|
const { error } = props;
|
|
64
130
|
const onNavBack = () => {
|
|
@@ -20403,21 +20469,27 @@ This typically indicates that your device does not have a healthy Internet conne
|
|
|
20403
20469
|
});
|
|
20404
20470
|
return colorwaySizeAssets;
|
|
20405
20471
|
}
|
|
20406
|
-
|
|
20407
|
-
|
|
20408
|
-
|
|
20409
|
-
if (!styleSKU) throw new Error("styleSKU is required for GetStyleByBrandStyleID");
|
|
20410
|
-
const isLoggedIn = await this.IsLoggedIn();
|
|
20411
|
-
console.debug("isLoggedIn", isLoggedIn, "BrandID:", this.BrandID);
|
|
20472
|
+
async GetStyleByExernalID(externalID) {
|
|
20473
|
+
if (!externalID) throw new Error("externalID is required for GetStyleByExernalID");
|
|
20474
|
+
await this.IsLoggedIn();
|
|
20412
20475
|
try {
|
|
20413
20476
|
const constraints = [where("brand_id", "==", this.BrandID)];
|
|
20414
|
-
constraints.push(where("
|
|
20477
|
+
constraints.push(where("external_id", "==", externalID));
|
|
20478
|
+
console.debug("Debug: Executing Firestore query with constraints:", {
|
|
20479
|
+
brand_id: this.BrandID,
|
|
20480
|
+
external_id: externalID
|
|
20481
|
+
});
|
|
20415
20482
|
const querySnapshot = await this.firebase.getDocs("styles", constraints);
|
|
20483
|
+
console.debug("Debug: Firestore query result:", {
|
|
20484
|
+
size: querySnapshot.size,
|
|
20485
|
+
empty: querySnapshot.empty,
|
|
20486
|
+
externalID
|
|
20487
|
+
});
|
|
20416
20488
|
const style = querySnapshot.docs?.[0]?.data();
|
|
20417
20489
|
console.debug("style fetched by brand id:", style);
|
|
20418
20490
|
return style;
|
|
20419
20491
|
} catch (error) {
|
|
20420
|
-
console.debug("
|
|
20492
|
+
console.debug("GetStyleByExernalID error:", externalID, error);
|
|
20421
20493
|
return getFirebaseError(error);
|
|
20422
20494
|
}
|
|
20423
20495
|
}
|
|
@@ -21883,9 +21955,9 @@ This typically indicates that your device does not have a healthy Internet conne
|
|
|
21883
21955
|
return false;
|
|
21884
21956
|
};
|
|
21885
21957
|
class FittingRoomController {
|
|
21886
|
-
constructor(env, shopID,
|
|
21958
|
+
constructor(env, shopID, externalID, noCacheOnRetry = false, modalDivId, sizeRecMainDivId, vtoMainDivId, cssVariables, hooks = {}) {
|
|
21887
21959
|
this.shopID = shopID;
|
|
21888
|
-
this.
|
|
21960
|
+
this.externalID = externalID;
|
|
21889
21961
|
this.noCacheOnRetry = noCacheOnRetry;
|
|
21890
21962
|
this.hooks = hooks;
|
|
21891
21963
|
this.hasInitializedTryOn = false;
|
|
@@ -21933,7 +22005,7 @@ This typically indicates that your device does not have a healthy Internet conne
|
|
|
21933
22005
|
console.debug("init");
|
|
21934
22006
|
try {
|
|
21935
22007
|
const authUserPromise = this.firebaseAuthUserController.GetUserOrNotLoggedIn();
|
|
21936
|
-
const stylePromise = this.API.
|
|
22008
|
+
const stylePromise = this.API.GetStyleByExernalID(this.externalID);
|
|
21937
22009
|
await Promise.all([authUserPromise, stylePromise]);
|
|
21938
22010
|
console.debug("promise all ready");
|
|
21939
22011
|
const style = await stylePromise;
|
|
@@ -22141,7 +22213,7 @@ This typically indicates that your device does not have a healthy Internet conne
|
|
|
22141
22213
|
const initFittingRoom = async ({
|
|
22142
22214
|
env,
|
|
22143
22215
|
shopId,
|
|
22144
|
-
|
|
22216
|
+
externalID,
|
|
22145
22217
|
modalDivId,
|
|
22146
22218
|
sizeRecMainDivId,
|
|
22147
22219
|
vtoMainDivId,
|
|
@@ -22153,7 +22225,7 @@ This typically indicates that your device does not have a healthy Internet conne
|
|
|
22153
22225
|
const tfr = new FittingRoomController(
|
|
22154
22226
|
env,
|
|
22155
22227
|
shopId,
|
|
22156
|
-
|
|
22228
|
+
externalID,
|
|
22157
22229
|
noCacheOnRetry,
|
|
22158
22230
|
modalDivId,
|
|
22159
22231
|
sizeRecMainDivId,
|
package/package.json
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thefittingroom/shop-ui",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"description": "the fitting room UI library",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
7
10
|
"scripts": {
|
|
8
11
|
"clean": "rm -rf dist",
|
|
9
12
|
"clean:all": "rm -rf dist build",
|
package/.env.development
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
VITE_LANGUAGE_URL=https://assets.dev.thefittingroom.xyz/shop-sdk/${VERSION}/languages
|
|
2
|
-
VITE_ASSETS_URL=https://assets.dev.thefittingroom.xyz/shop-sdk/assets
|
|
3
|
-
|
|
4
|
-
VITE_DEV_FIREBASE_API_KEY=AIzaSyDfjBWzpmzb-mhGN8VSURxzLg6nkzmKUD8
|
|
5
|
-
VITE_DEV_FIREBASE_AUTH_DOMAIN=fittingroom-dev-5d248.firebaseapp.com
|
|
6
|
-
VITE_DEV_FIREBASE_PROJECT_ID=fittingroom-dev-5d248
|
|
7
|
-
VITE_DEV_FIREBASE_STORAGE_BUCKET=fittingroom-dev-5d248.appspot.com
|
|
8
|
-
VITE_DEV_FIREBASE_MESSAGING_SENDER_ID=2298664147
|
|
9
|
-
VITE_DEV_FIREBASE_APP_ID=1:2298664147:web:340bda75cd5d25f3997026
|
|
10
|
-
VITE_DEV_FIREBASE_MEASUREMENT_ID=G-B7GDQ1Y9LL
|
|
11
|
-
VITE_DEV_API_ENDPOINT=https://tfr.dev.thefittingroom.xyz
|
|
12
|
-
VITE_DEV_API_VTO_TIMEOUT_MS=120000
|
|
13
|
-
VITE_DEV_API_AVATAR_TIMEOUT_MS=120000
|
package/.env.example
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
NODE_ENV
|
|
2
|
-
LANGUAGE_URL
|
|
3
|
-
ASSETS_URL
|
|
4
|
-
DEV_FIREBASE_API_KEY
|
|
5
|
-
DEV_FIREBASE_AUTH_DOMAIN
|
|
6
|
-
DEV_FIREBASE_PROJECT_ID
|
|
7
|
-
DEV_FIREBASE_STORAGE_BUCKET
|
|
8
|
-
DEV_FIREBASE_MESSAGING_SENDER_ID
|
|
9
|
-
DEV_FIREBASE_APP_ID
|
|
10
|
-
DEV_FIREBASE_MEASUREMENT_ID
|
|
11
|
-
DEV_API_ENDPOINT
|
|
12
|
-
DEV_VTO_TIMEOUT_MS
|
|
13
|
-
DEV_AVATAR_TIMEOUT_MS
|
|
14
|
-
PROD_FIREBASE_API_KEY
|
|
15
|
-
PROD_FIREBASE_AUTH_DOMAIN
|
|
16
|
-
PROD_FIREBASE_PROJECT_ID
|
|
17
|
-
PROD_FIREBASE_STORAGE_BUCKET
|
|
18
|
-
PROD_FIREBASE_MESSAGING_SENDER_ID
|
|
19
|
-
PROD_FIREBASE_APP_ID
|
|
20
|
-
PROD_FIREBASE_MEASUREMENT_ID
|
|
21
|
-
PROD_API_ENDPOINT
|
|
22
|
-
PROD_API_VTO_TIMEOUT_MS
|
|
23
|
-
PROD_API_AVATAR_TIMEOUT_MS
|
package/.env.production
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
VITE_LANGUAGE_URL=https://assets.p.thefittingroom.xyz/shop-sdk/${VERSION}/languages
|
|
2
|
-
VITE_ASSETS_URL=https://assets.p.thefittingroom.xyz/shop-sdk/assets
|
|
3
|
-
|
|
4
|
-
VITE_FIREBASE_API_KEY=AIzaSyA3kQ6w1vkA9l9lgY0nNACVPXe-QmP5T1Y
|
|
5
|
-
VITE_FIREBASE_AUTH_DOMAIN=fittingroom-prod.firebaseapp.com
|
|
6
|
-
VITE_FIREBASE_PROJECT_ID=fittingroom-prod
|
|
7
|
-
VITE_FIREBASE_STORAGE_BUCKET=fittingroom-prod.appspot.com
|
|
8
|
-
VITE_FIREBASE_MESSAGING_SENDER_ID=965656825574
|
|
9
|
-
VITE_FIREBASE_APP_ID=1:965656825574:web:933493cddc73213bd43527
|
|
10
|
-
VITE_FIREBASE_MEASUREMENT_ID=G-XH9VV5N6EW
|
|
11
|
-
|
|
12
|
-
VITE_API_ENDPOINT=https://tfr.p.thefittingroom.xyz
|
|
13
|
-
VITE_API_VTO_TIMEOUT_MS=120000
|
|
14
|
-
VITE_API_AVATAR_TIMEOUT_MS=120000
|
package/AGENTS.md
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
You are a typescript developer working on an open-source ecmascript module that connects to firestore and a REST http server.
|
|
2
|
-
The API endpoint payloads are generated in src/api/gen.
|
|
3
|
-
The source code is deployed to github releases and served via jsdelivr.
|
|
4
|
-
You may use playwright or chrome-devtools for debugging.
|
|
5
|
-
Always include a simple lowercase console.debug statement in each function you define.
|
|
6
|
-
Never add line comments.
|
|
7
|
-
Always add function comments if the functions are complicated (more than 3 lines of code).
|
|
8
|
-
|
package/index.html
DELETED
|
@@ -1,274 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
|
|
4
|
-
<head>
|
|
5
|
-
<title>TheFittingRoom Widget Demo</title>
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
-
|
|
8
|
-
<link href="https://fonts.googleapis.com" rel="preconnect" />
|
|
9
|
-
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin />
|
|
10
|
-
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500&family=Roboto&display=swap"
|
|
11
|
-
rel="stylesheet" />
|
|
12
|
-
<!-- CSS is generated during build to dist/ directory -->
|
|
13
|
-
<!-- <link href="/dist/index.css" rel="stylesheet" /> -->
|
|
14
|
-
|
|
15
|
-
<style>
|
|
16
|
-
body {
|
|
17
|
-
font-family: 'Roboto', sans-serif;
|
|
18
|
-
margin: 0;
|
|
19
|
-
padding: 20px;
|
|
20
|
-
background-color: #f5f5f5;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
.demo-container {
|
|
24
|
-
max-width: 800px;
|
|
25
|
-
margin: 0 auto;
|
|
26
|
-
background: white;
|
|
27
|
-
padding: 20px;
|
|
28
|
-
border-radius: 8px;
|
|
29
|
-
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
.product-selector {
|
|
33
|
-
margin-bottom: 20px;
|
|
34
|
-
padding: 15px;
|
|
35
|
-
border: 1px solid #ddd;
|
|
36
|
-
border-radius: 5px;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
.product-selector h3 {
|
|
40
|
-
margin-top: 0;
|
|
41
|
-
color: #333;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
select {
|
|
45
|
-
width: 100%;
|
|
46
|
-
padding: 8px;
|
|
47
|
-
margin: 10px 0;
|
|
48
|
-
border: 1px solid #ccc;
|
|
49
|
-
border-radius: 4px;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
.tfr-widget-container {
|
|
53
|
-
margin-top: 20px;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
.tfr-home-button-container {
|
|
57
|
-
margin-top: 20px;
|
|
58
|
-
text-align: center;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
.tfr-home-button-container button {
|
|
62
|
-
margin: 5px;
|
|
63
|
-
padding: 10px 15px;
|
|
64
|
-
background-color: #007bff;
|
|
65
|
-
color: white;
|
|
66
|
-
border: none;
|
|
67
|
-
border-radius: 4px;
|
|
68
|
-
cursor: pointer;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
.tfr-home-button-container button:hover {
|
|
72
|
-
background-color: #0056b3;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
#tfr-tryon-image {
|
|
76
|
-
max-width: 100%;
|
|
77
|
-
height: auto;
|
|
78
|
-
margin: 20px 0;
|
|
79
|
-
border: 1px solid #ddd;
|
|
80
|
-
border-radius: 4px;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
#tfr-slider {
|
|
84
|
-
width: 100%;
|
|
85
|
-
margin: 10px 0;
|
|
86
|
-
}
|
|
87
|
-
</style>
|
|
88
|
-
|
|
89
|
-
<script type="module">
|
|
90
|
-
import { comps, initFittingRoom } from '/src/index.js'
|
|
91
|
-
|
|
92
|
-
const ENV = 'development'
|
|
93
|
-
|
|
94
|
-
const brandID = 1
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const productSKU = 'TFR_FITTED-DRESS_178cm_BlackBa'
|
|
98
|
-
const variantSKUs = [
|
|
99
|
-
'TFR_Fitted-Dress_178_BlackBandana_2',
|
|
100
|
-
'TFR_Fitted-Dress_178_BlackBandana_4',
|
|
101
|
-
'TFR_Fitted-Dress_178_BlackBandana_6',
|
|
102
|
-
'TFR_Fitted-Dress_178_BlackBandana_8',
|
|
103
|
-
'TFR_Fitted-Dress_178_BlackBandana_10',
|
|
104
|
-
]
|
|
105
|
-
|
|
106
|
-
// Mock product variants for demonstration
|
|
107
|
-
const productVariants = [
|
|
108
|
-
{ option1: '2', option2: 'BlackBandana', sku: 'TFR_Fitted-Dress_178_BlackBandana_2' },
|
|
109
|
-
{ option1: '4', option2: 'BlackBandana', sku: 'TFR_Fitted-Dress_178_BlackBandana_4' },
|
|
110
|
-
{ option1: '6', option2: 'BlackBandana', sku: 'TFR_Fitted-Dress_178_BlackBandana_6' },
|
|
111
|
-
{ option1: '8', option2: 'BlackBandana', sku: 'TFR_Fitted-Dress_178_BlackBandana_8' },
|
|
112
|
-
{ option1: '10', option2: 'BlackBandana', sku: 'TFR_Fitted-Dress_178_BlackBandana_10' },
|
|
113
|
-
]
|
|
114
|
-
|
|
115
|
-
const getSku = () => {
|
|
116
|
-
try {
|
|
117
|
-
if (typeof productVariants === 'undefined' || !Array.isArray(productVariants)) {
|
|
118
|
-
throw new Error(
|
|
119
|
-
'productVariants is not defined or is not an array. The Fitting Room cannot determine product SKUs without this data.',
|
|
120
|
-
)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const colorInput = document.getElementsByName(`options[Color]`)?.[0]
|
|
124
|
-
const sizeInput = document.getElementsByName(`options[Size]`)?.[0]
|
|
125
|
-
|
|
126
|
-
const color = colorInput ? colorInput.value : undefined
|
|
127
|
-
const size = sizeInput ? sizeInput.value : undefined
|
|
128
|
-
|
|
129
|
-
if (!colorInput) {
|
|
130
|
-
console.error('Error in getSku: Color input element (options[Color]) not found on the page.')
|
|
131
|
-
}
|
|
132
|
-
if (!sizeInput) {
|
|
133
|
-
console.error('Error in getSku: Size input element (options[Size]) not found on the page.')
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const activeVariant = productVariants.find((item) => {
|
|
137
|
-
const hasSizeMatch = !size || item.option1 === size || item.option2 === size
|
|
138
|
-
const hasColorMatch = !color || item.option1 === color || item.option2 === color
|
|
139
|
-
return hasSizeMatch && hasColorMatch
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
if (!activeVariant) {
|
|
143
|
-
throw new Error(
|
|
144
|
-
'No product variant found for the selected color and size combination. Please check product data.',
|
|
145
|
-
)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return activeVariant?.sku
|
|
149
|
-
} catch (error) {
|
|
150
|
-
console.error(`Error in getSku: ${error.message}. SKU retrieval failed.`)
|
|
151
|
-
return null
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
window.addEventListener('DOMContentLoaded', async (e) => {
|
|
156
|
-
let tfr = null
|
|
157
|
-
|
|
158
|
-
try {
|
|
159
|
-
|
|
160
|
-
const config = {
|
|
161
|
-
shopId: brandID,
|
|
162
|
-
styleSKU: productSKU,
|
|
163
|
-
modalDivId: 'thefittingroom-modal',
|
|
164
|
-
sizeRecMainDivId: 'tfr-size-recommendation-main',
|
|
165
|
-
vtoMainDivId: 'tfr-vto',
|
|
166
|
-
noCacheOnRetry: true,
|
|
167
|
-
env: typeof ENV !== 'undefined' ? ENV : 'development',
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const sku = getSku()
|
|
171
|
-
if (!sku) {
|
|
172
|
-
console.warn('SKU not retrieved. The Fitting Room will initialize but may not function optimally without a specific SKU.')
|
|
173
|
-
}
|
|
174
|
-
const tfr = await initFittingRoom(config)
|
|
175
|
-
|
|
176
|
-
if (sku) {
|
|
177
|
-
tfr.SetColorwaySizeAssetBySKU(sku, variantSKUs, true)
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Add event listeners for product selection changes
|
|
181
|
-
const sizeSelect = document.querySelector('select[name="options[Size]"]')
|
|
182
|
-
const colorSelect = document.querySelector('select[name="options[Color]"]')
|
|
183
|
-
|
|
184
|
-
if (sizeSelect) {
|
|
185
|
-
sizeSelect.addEventListener('change', () => {
|
|
186
|
-
const newSku = getSku()
|
|
187
|
-
if (newSku && tfr) {
|
|
188
|
-
tfr.SetColorwaySizeAssetBySKU(newSku, false)
|
|
189
|
-
console.debug('SKU updated to:', newSku)
|
|
190
|
-
}
|
|
191
|
-
})
|
|
192
|
-
}
|
|
193
|
-
if (colorSelect) {
|
|
194
|
-
colorSelect.addEventListener('change', () => {
|
|
195
|
-
const newSku = getSku()
|
|
196
|
-
if (newSku && tfr) {
|
|
197
|
-
tfr.SetColorwaySizeAssetBySKU(newSku, false)
|
|
198
|
-
console.debug('SKU updated to:', newSku)
|
|
199
|
-
}
|
|
200
|
-
})
|
|
201
|
-
}
|
|
202
|
-
} catch (error) {
|
|
203
|
-
console.error(
|
|
204
|
-
`Error during window load event for The Fitting Room: ${error.message}. The functionality might be impacted or disabled.`,
|
|
205
|
-
)
|
|
206
|
-
}
|
|
207
|
-
})
|
|
208
|
-
</script>
|
|
209
|
-
</head>
|
|
210
|
-
|
|
211
|
-
<body>
|
|
212
|
-
<div class="demo-container">
|
|
213
|
-
<h1>TheFittingRoom Widget Demo</h1>
|
|
214
|
-
<p>This demo showcases a fully functioning widget with brand_id 1 and hardcoded SKUs.</p>
|
|
215
|
-
|
|
216
|
-
<div class="product-selector">
|
|
217
|
-
<h3>Product Options</h3>
|
|
218
|
-
<label for="size-select">Size:</label>
|
|
219
|
-
<select name="options[Size]" id="size-select">
|
|
220
|
-
<option value="">Select Size</option>
|
|
221
|
-
<option value="2">Size 2</option>
|
|
222
|
-
<option value="4">Size 4</option>
|
|
223
|
-
<option value="6">Size 6</option>
|
|
224
|
-
<option value="8">Size 8</option>
|
|
225
|
-
<option value="10">Size 10</option>
|
|
226
|
-
</select>
|
|
227
|
-
|
|
228
|
-
<label for="color-select">Color:</label>
|
|
229
|
-
<select name="options[Color]" id="color-select">
|
|
230
|
-
<option value="">Select Color</option>
|
|
231
|
-
<option value="BlackBandana">Black Bandana</option>
|
|
232
|
-
</select>
|
|
233
|
-
</div>
|
|
234
|
-
|
|
235
|
-
<div class="tfr-widget-container">
|
|
236
|
-
<h3>TheFittingRoom Widget</h3>
|
|
237
|
-
<div id="thefittingroom-modal"></div>
|
|
238
|
-
<div id="tfr-size-recommendation-main"></div>
|
|
239
|
-
<div id="tfr-vto"></div>
|
|
240
|
-
</div>
|
|
241
|
-
|
|
242
|
-
<!-- Hidden modal container for manual modal triggers -->
|
|
243
|
-
<div id="tfr-manual-modal" style="display: none"></div>
|
|
244
|
-
|
|
245
|
-
<div class="tfr-home-button-container">
|
|
246
|
-
<button
|
|
247
|
-
onclick="window.mm.open(window.comps.ErrorModal({error: 'custom error message', onNavBack: window.onNavBack, onClose: window.onClose}))">
|
|
248
|
-
Error Modal
|
|
249
|
-
</button>
|
|
250
|
-
<button onclick="window.mm.open(window.comps.ScanCodeModal())">Scan Code Modal</button>
|
|
251
|
-
<button
|
|
252
|
-
onclick="window.mm.open(window.comps.SignInModal({email:'email@mail.com', onSignIn: window.onSignIn('abc'), onNavForgotPassword: window.onNavForgotPassword('123'), onNavScanCode: window.onNavScanCode}))">
|
|
253
|
-
Sign In Modal
|
|
254
|
-
</button>
|
|
255
|
-
<button
|
|
256
|
-
onclick="window.mm.open(window.comps.ForgotPasswordModal({email: 'email@mail.com', onNavSignIn: window.onNavSignIn('123'), onPasswordReset: window.onPasswordReset('123')}))">
|
|
257
|
-
Forgot Password Modal
|
|
258
|
-
</button>
|
|
259
|
-
<button onclick="window.mm.open(window.comps.NoAvatarModal({}))">No Avatar Modal</button>
|
|
260
|
-
<button onclick="window.mm.open(window.comps.LoadingAvatarModal({timeoutMS: 12000}))">
|
|
261
|
-
Loading Avatar Modal
|
|
262
|
-
</button>
|
|
263
|
-
<button
|
|
264
|
-
onclick="window.mm.open(window.comps.SizeErrorModal({onNavBack: window.onNavBack, onClose: window.onClose, sizes: {recommended: 'large', avaliable: ['small', 'medium', 'large']}}))">
|
|
265
|
-
Size Error Modal
|
|
266
|
-
</button>
|
|
267
|
-
<button onclick="window.mm.open(window.comps.ResetLinkModal({onNavSignIn: window.onNavSignIn('abc')}))">
|
|
268
|
-
Reset Link Modal
|
|
269
|
-
</button>
|
|
270
|
-
</div>
|
|
271
|
-
</div>
|
|
272
|
-
</body>
|
|
273
|
-
|
|
274
|
-
</html>
|
package/vite.config.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { resolve } from 'path'
|
|
2
|
-
import { defineConfig } from 'vite'
|
|
3
|
-
|
|
4
|
-
const server = {
|
|
5
|
-
port: 5173,
|
|
6
|
-
host: true,
|
|
7
|
-
cors: true,
|
|
8
|
-
headers: {
|
|
9
|
-
'Access-Control-Allow-Origin': '*',
|
|
10
|
-
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
|
|
11
|
-
'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization',
|
|
12
|
-
},
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const lib = {
|
|
16
|
-
lib: {
|
|
17
|
-
entry: resolve('src/index.ts'),
|
|
18
|
-
name: 'TheFittingRoom',
|
|
19
|
-
fileName: 'index',
|
|
20
|
-
},
|
|
21
|
-
minify: false,
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export default defineConfig(({ mode, command }) => {
|
|
25
|
-
if (command === 'serve') {
|
|
26
|
-
return {
|
|
27
|
-
server: {
|
|
28
|
-
...server,
|
|
29
|
-
watch: { usePolling: true },
|
|
30
|
-
},
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (mode === 'production' || process.env.CI) {
|
|
35
|
-
return { build: lib, server }
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return { build: { minify: false }, server }
|
|
39
|
-
})
|