The repo for Purrform's main BigCommerce store.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: update Diet Builder error handling and add error step styles

+66 -28
+50 -27
assets/js/theme/custom/diet-builder.js
··· 1127 1127 })), 1128 1128 }; 1129 1129 1130 - this.renderLoadingStep(); 1131 - 1132 1130 const success = await this.runKlaviyoSequence(this.state.payload); 1133 1131 1134 1132 if (success) { ··· 1139 1137 } 1140 1138 1141 1139 async runKlaviyoSequence(payload) { 1142 - const publicKey = this.context.klaviyoPublicKey; 1140 + const publicKey = this.context.klaviyoPublicKey || 'WL59HL'; 1143 1141 1144 1142 if (!publicKey) { 1145 1143 // eslint-disable-next-line no-console 1146 - console.warn('[DietBuilder] Klaviyo public key not configured — skipping Klaviyo sequence.'); 1144 + console.warn( 1145 + '[DietBuilder] Klaviyo public key not configured — skipping Klaviyo sequence.', 1146 + ); 1147 1147 return false; 1148 1148 } 1149 1149 1150 - const profileId = await this.createKlaviyoProfile(payload.email, publicKey); 1151 - if (!profileId) return false; 1150 + const profileId = await this.createKlaviyoProfile( 1151 + payload.email, 1152 + publicKey, 1153 + ); 1154 + if (!profileId) { 1155 + // eslint-disable-next-line no-console 1156 + console.warn( 1157 + '[DietBuilder] Could not retrieve profile ID — proceeding by email only.', 1158 + ); 1159 + } 1152 1160 1153 - const subscribed = await this.subscribeToMarketing(profileId, payload.email, publicKey); 1161 + const subscribed = await this.subscribeToMarketing( 1162 + profileId, 1163 + payload.email, 1164 + publicKey, 1165 + ); 1154 1166 if (!subscribed) return false; 1155 1167 1156 1168 return this.sendKlaviyoEvent(payload, publicKey); ··· 1179 1191 ); 1180 1192 1181 1193 if (!response.ok) { 1182 - const errors = await response.json(); 1194 + const errorText = await response.text(); 1195 + const errors = errorText ? JSON.parse(errorText) : {}; 1183 1196 const errorMsg = (errors.errors || []) 1184 1197 .map((e) => `[${e.status} - ${e.title} - ${e.detail}]`) 1185 1198 .join(', '); 1186 1199 // eslint-disable-next-line no-console 1187 - console.error(`[DietBuilder] Error creating Klaviyo profile: ${errorMsg}`); 1200 + console.error( 1201 + `[DietBuilder] Error creating Klaviyo profile: ${errorMsg || response.status}`, 1202 + ); 1188 1203 return null; 1189 1204 } 1190 1205 1191 - const data = await response.json(); 1206 + const text = await response.text(); 1207 + const data = text ? JSON.parse(text) : null; 1192 1208 // eslint-disable-next-line no-console 1193 1209 console.log('[DietBuilder] Klaviyo profile created/found.'); 1194 - return data.data.id; 1210 + return data?.data?.id ?? null; 1195 1211 } catch (err) { 1196 1212 // eslint-disable-next-line no-console 1197 1213 console.error('[DietBuilder] Klaviyo createProfile error:', err); ··· 1207 1223 profile: { 1208 1224 data: { 1209 1225 type: 'profile', 1210 - id: profileId, 1226 + ...(profileId && { id: profileId }), 1211 1227 attributes: { 1212 1228 email, 1213 1229 subscriptions: { ··· 1218 1234 }, 1219 1235 }, 1220 1236 }, 1237 + }, 1238 + }, 1239 + }, 1240 + relationships: { 1241 + list: { 1242 + data: { 1243 + type: 'list', 1244 + id: 'YmRGYj', 1221 1245 }, 1222 1246 }, 1223 1247 }, ··· 1239 1263 ); 1240 1264 1241 1265 if (!response.ok) { 1242 - const errors = await response.json(); 1266 + const errorText = await response.text(); 1267 + const errors = errorText ? JSON.parse(errorText) : {}; 1243 1268 const errorMsg = (errors.errors || []) 1244 1269 .map((e) => `[${e.status} - ${e.title} - ${e.detail}]`) 1245 1270 .join(', '); 1246 1271 // eslint-disable-next-line no-console 1247 - console.error(`[DietBuilder] Error subscribing profile to marketing: ${errorMsg}`); 1272 + console.error( 1273 + `[DietBuilder] Error subscribing profile to marketing: ${errorMsg || response.status}`, 1274 + ); 1248 1275 return false; 1249 1276 } 1250 1277 ··· 1253 1280 return true; 1254 1281 } catch (err) { 1255 1282 // eslint-disable-next-line no-console 1256 - console.error('[DietBuilder] Klaviyo subscribeToMarketing error:', err); 1283 + console.error( 1284 + '[DietBuilder] Klaviyo subscribeToMarketing error:', 1285 + err, 1286 + ); 1257 1287 return false; 1258 1288 } 1259 1289 } ··· 1303 1333 1304 1334 if (!response.ok) { 1305 1335 // eslint-disable-next-line no-console 1306 - console.error('[DietBuilder] Klaviyo event failed:', response.status, await response.text()); 1336 + console.error( 1337 + '[DietBuilder] Klaviyo event failed:', 1338 + response.status, 1339 + await response.text(), 1340 + ); 1307 1341 return false; 1308 1342 } 1309 1343 ··· 1317 1351 } 1318 1352 } 1319 1353 1320 - renderLoadingStep() { 1321 - const content = el( 1322 - 'div', 1323 - { className: 'diet-builder-loading' }, 1324 - el('p', { className: 'diet-builder-loading__message' }, 'Sending your results\u2026'), 1325 - ); 1326 - 1327 - this.renderStep('Almost there!', content); 1328 - } 1329 - 1330 1354 renderErrorStep() { 1331 1355 const retry = async () => { 1332 - this.renderLoadingStep(); 1333 1356 const success = await this.runKlaviyoSequence(this.state.payload); 1334 1357 if (success) { 1335 1358 this.renderSuccessStep();
+15
assets/scss/custom/pages/_diet-builder.scss
··· 899 899 } 900 900 } 901 901 902 + // ── Error step ─────────────────────────────────────────────── 903 + .diet-builder-error { 904 + display: flex; 905 + flex-direction: column; 906 + align-items: center; 907 + margin-top: 2rem; 908 + text-align: center; 909 + } 910 + 911 + .diet-builder-error__message { 912 + font-size: 18px; 913 + max-width: 480px; 914 + margin-bottom: 2rem; 915 + } 916 + 902 917 // ── Loading spinner ────────────────────────────────────────── 903 918 .diet-builder-spinner::after { 904 919 content: '';
+1 -1
config.json
··· 1 1 { 2 - "name": "diet-builder - backend", 2 + "name": "diet-builder - backend v2", 3 3 "version": "6.10.0", 4 4 "template_engine": "handlebars_v4", 5 5 "meta": {