@capillarytech/creatives-library 8.0.312 → 8.0.314
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/package.json
CHANGED
|
@@ -388,93 +388,6 @@ const CommonTestAndPreview = (props) => {
|
|
|
388
388
|
return resolvedText;
|
|
389
389
|
};
|
|
390
390
|
|
|
391
|
-
/**
|
|
392
|
-
* Common handler for saving test customers (both new and existing)
|
|
393
|
-
*/
|
|
394
|
-
const handleSaveTestCustomer = async (validationErrors = {},setIsLoading) => {
|
|
395
|
-
// Check for validation errors before saving (for new customers)
|
|
396
|
-
if (customerModal[1] === CUSTOMER_MODAL_NEW && (validationErrors.email || validationErrors.mobile)) {
|
|
397
|
-
return;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
if (typeof setIsLoading === 'function') {
|
|
401
|
-
setIsLoading(true);
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
try {
|
|
405
|
-
let payload;
|
|
406
|
-
|
|
407
|
-
if (customerModal[1] === CUSTOMER_MODAL_EXISTING) {
|
|
408
|
-
// For existing customers, use customerId
|
|
409
|
-
payload = {
|
|
410
|
-
customerId: customerData.customerId
|
|
411
|
-
};
|
|
412
|
-
} else {
|
|
413
|
-
// For new customers, use customer object
|
|
414
|
-
payload = {
|
|
415
|
-
customer: {
|
|
416
|
-
firstName: customerData.name || "",
|
|
417
|
-
mobile: customerData.mobile || "",
|
|
418
|
-
email: customerData.email || ""
|
|
419
|
-
}
|
|
420
|
-
};
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
const response = await createTestCustomer(payload);
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
// Handle success: add to test customers list and selection (existing and new)
|
|
427
|
-
if (response && response.success) {
|
|
428
|
-
CapNotification.success({
|
|
429
|
-
message: formatMessage(messages.newTestCustomerAddedSuccess),
|
|
430
|
-
});
|
|
431
|
-
// API may return customerId in response.response (e.g. { response: { customerId: 438845651 } })
|
|
432
|
-
const res = response?.response || response;
|
|
433
|
-
const addedId = customerModal[1] === CUSTOMER_MODAL_EXISTING
|
|
434
|
-
? customerData?.customerId
|
|
435
|
-
: res?.customerId;
|
|
436
|
-
if (addedId) {
|
|
437
|
-
actions.addTestCustomer({
|
|
438
|
-
userId: addedId,
|
|
439
|
-
customerId: addedId,
|
|
440
|
-
name: customerData?.name?.trim() || '',
|
|
441
|
-
email: customerData?.email || '',
|
|
442
|
-
mobile: customerData?.mobile || '',
|
|
443
|
-
});
|
|
444
|
-
setSelectedTestEntities((prev) => [...prev, addedId]);
|
|
445
|
-
}
|
|
446
|
-
handleCloseCustomerModal();
|
|
447
|
-
} else {
|
|
448
|
-
// Show error notification for unsuccessful response
|
|
449
|
-
CapNotification.error({
|
|
450
|
-
message: formatMessage(messages.errorTitle),
|
|
451
|
-
description: response?.message || formatMessage(messages.failedToAddTestCustomer),
|
|
452
|
-
});
|
|
453
|
-
}
|
|
454
|
-
} catch (error) {
|
|
455
|
-
if (customerModal[1] === CUSTOMER_MODAL_EXISTING) {
|
|
456
|
-
// Show error notification for caught exceptions (existing customers only)
|
|
457
|
-
CapNotification.error({
|
|
458
|
-
message: formatMessage(messages.errorTitle),
|
|
459
|
-
description: error?.message || formatMessage(messages.errorAddingTestCustomer),
|
|
460
|
-
});
|
|
461
|
-
}
|
|
462
|
-
} finally {
|
|
463
|
-
setIsLoading(false);
|
|
464
|
-
}
|
|
465
|
-
};
|
|
466
|
-
|
|
467
|
-
const handleCloseCustomerModal = () => {
|
|
468
|
-
setCustomerModal([false, ""]);
|
|
469
|
-
setSearchValue('');
|
|
470
|
-
setCustomerData({
|
|
471
|
-
name: '',
|
|
472
|
-
email: '',
|
|
473
|
-
mobile: '',
|
|
474
|
-
customerId: '',
|
|
475
|
-
});
|
|
476
|
-
};
|
|
477
|
-
|
|
478
391
|
/**
|
|
479
392
|
* Prepare payload for preview API based on channel
|
|
480
393
|
*/
|
|
@@ -2599,107 +2512,6 @@ const CommonTestAndPreview = (props) => {
|
|
|
2599
2512
|
setSelectedTestEntities(value);
|
|
2600
2513
|
};
|
|
2601
2514
|
|
|
2602
|
-
/**
|
|
2603
|
-
* Map API customerDetails item to our customerData shape
|
|
2604
|
-
*/
|
|
2605
|
-
const mapCustomerDetailsToCustomerData = (detail, identifierValue) => {
|
|
2606
|
-
const firstName = detail.firstName || '';
|
|
2607
|
-
const lastName = detail.lastName || '';
|
|
2608
|
-
const name = [firstName, lastName].filter(Boolean).join(' ').trim() || '';
|
|
2609
|
-
const getIdentifierValue = (type) => {
|
|
2610
|
-
const fromIdentifiers = detail.identifiers?.find((i) => i.type === type)?.value;
|
|
2611
|
-
if (fromIdentifiers) return fromIdentifiers;
|
|
2612
|
-
const fromCommChannels = detail.commChannels?.find((c) => c.type === type)?.value;
|
|
2613
|
-
return fromCommChannels || (channel === CHANNELS.EMAIL && type === IDENTIFIER_TYPE_EMAIL ? identifierValue : channel === CHANNELS.SMS && type === IDENTIFIER_TYPE_MOBILE ? identifierValue : '');
|
|
2614
|
-
};
|
|
2615
|
-
return {
|
|
2616
|
-
name,
|
|
2617
|
-
email: channel === CHANNELS.EMAIL ? (getIdentifierValue(IDENTIFIER_TYPE_EMAIL) || identifierValue) : (getIdentifierValue(IDENTIFIER_TYPE_EMAIL) || ''),
|
|
2618
|
-
mobile: channel === CHANNELS.SMS ? (getIdentifierValue(IDENTIFIER_TYPE_MOBILE) || getIdentifierValue(IDENTIFIER_TYPE_PHONE) || identifierValue) : (getIdentifierValue(IDENTIFIER_TYPE_MOBILE) || getIdentifierValue(IDENTIFIER_TYPE_PHONE) || ''),
|
|
2619
|
-
customerId: detail.userId != null ? String(detail.userId) : '',
|
|
2620
|
-
};
|
|
2621
|
-
};
|
|
2622
|
-
|
|
2623
|
-
const handleAddTestCustomer = async () => {
|
|
2624
|
-
const identifierType = channel === CHANNELS.EMAIL ? IDENTIFIER_TYPE_EMAIL : IDENTIFIER_TYPE_MOBILE;
|
|
2625
|
-
const searchValueToCheck = searchValue || '';
|
|
2626
|
-
|
|
2627
|
-
// Check if this customer is already in the test customers list
|
|
2628
|
-
const existingTestCustomer = testCustomers?.find(customer => {
|
|
2629
|
-
if (channel === CHANNELS.EMAIL) {
|
|
2630
|
-
return customer.email === searchValueToCheck;
|
|
2631
|
-
} else if (channel === CHANNELS.SMS) {
|
|
2632
|
-
return customer.mobile === searchValueToCheck;
|
|
2633
|
-
}
|
|
2634
|
-
return false;
|
|
2635
|
-
});
|
|
2636
|
-
|
|
2637
|
-
if (existingTestCustomer) {
|
|
2638
|
-
const entityId = existingTestCustomer.userId ?? existingTestCustomer.customerId;
|
|
2639
|
-
if (entityId != null) {
|
|
2640
|
-
const id = String(entityId);
|
|
2641
|
-
setSelectedTestEntities((prev) =>
|
|
2642
|
-
prev.includes(id) ? prev : [...prev, id]
|
|
2643
|
-
);
|
|
2644
|
-
}
|
|
2645
|
-
setSearchValue('');
|
|
2646
|
-
CapNotification.success({
|
|
2647
|
-
message: formatMessage(messages.customerAlreadyInTestList),
|
|
2648
|
-
});
|
|
2649
|
-
return;
|
|
2650
|
-
}
|
|
2651
|
-
|
|
2652
|
-
setIsCustomerDataLoading(true);
|
|
2653
|
-
|
|
2654
|
-
try {
|
|
2655
|
-
const response = await getMembersLookup(identifierType, searchValueToCheck);
|
|
2656
|
-
const success = response?.success && !response?.status?.isError;
|
|
2657
|
-
const res = response?.response || {};
|
|
2658
|
-
const exists = res.exists || false;
|
|
2659
|
-
const details = res.customerDetails || [];
|
|
2660
|
-
|
|
2661
|
-
if (!success) {
|
|
2662
|
-
const errorMessage = response?.message || response?.status?.message || formatMessage(messages.memberLookupError);
|
|
2663
|
-
CapNotification.error({ title: formatMessage(messages.errorTitle), message: errorMessage });
|
|
2664
|
-
return;
|
|
2665
|
-
}
|
|
2666
|
-
|
|
2667
|
-
if (exists && details.length > 0) {
|
|
2668
|
-
const mapped = mapCustomerDetailsToCustomerData(details[0], searchValueToCheck);
|
|
2669
|
-
const customerIdFromLookup = mapped.customerId;
|
|
2670
|
-
const alreadyInTestListByCustomerId = customerIdFromLookup && testCustomers?.some(
|
|
2671
|
-
(c) => String(c?.customerId) === customerIdFromLookup || String(c?.userId) === customerIdFromLookup
|
|
2672
|
-
);
|
|
2673
|
-
if (alreadyInTestListByCustomerId) {
|
|
2674
|
-
setSelectedTestEntities((prev) =>
|
|
2675
|
-
prev.includes(customerIdFromLookup) ? prev : [...prev, customerIdFromLookup]
|
|
2676
|
-
);
|
|
2677
|
-
setSearchValue('');
|
|
2678
|
-
CapNotification.success({
|
|
2679
|
-
message: formatMessage(messages.customerAlreadyInTestList),
|
|
2680
|
-
});
|
|
2681
|
-
return;
|
|
2682
|
-
}
|
|
2683
|
-
setCustomerData(mapped);
|
|
2684
|
-
setCustomerModal([true, CUSTOMER_MODAL_EXISTING]);
|
|
2685
|
-
} else {
|
|
2686
|
-
setCustomerData({
|
|
2687
|
-
name: '',
|
|
2688
|
-
email: channel === CHANNELS.EMAIL ? searchValueToCheck : '',
|
|
2689
|
-
mobile: channel === CHANNELS.SMS ? searchValueToCheck : '',
|
|
2690
|
-
customerId: '',
|
|
2691
|
-
});
|
|
2692
|
-
setCustomerModal([true, CUSTOMER_MODAL_NEW]);
|
|
2693
|
-
}
|
|
2694
|
-
} catch {
|
|
2695
|
-
CapNotification.error({
|
|
2696
|
-
message: formatMessage(messages.memberLookupError),
|
|
2697
|
-
});
|
|
2698
|
-
} finally {
|
|
2699
|
-
setIsCustomerDataLoading(false);
|
|
2700
|
-
}
|
|
2701
|
-
};
|
|
2702
|
-
|
|
2703
2515
|
/**
|
|
2704
2516
|
* Handle send test message
|
|
2705
2517
|
*/
|
|
@@ -212,8 +212,8 @@ export const ErrorInfoNote = (props) => {
|
|
|
212
212
|
Array.isArray(rawStandardWarnings) ? rawStandardWarnings : [],
|
|
213
213
|
), [rawStandardErrors, rawLiquidErrors, rawStandardWarnings]);
|
|
214
214
|
|
|
215
|
-
const errorsCount = errorIssues
|
|
216
|
-
const warningsCount = warningIssues
|
|
215
|
+
const errorsCount = errorIssues?.length;
|
|
216
|
+
const warningsCount = warningIssues?.length;
|
|
217
217
|
const totalCount = errorsCount + warningsCount;
|
|
218
218
|
const hasLiquidErrors = Array.isArray(rawLiquidErrors) && rawLiquidErrors.length > 0;
|
|
219
219
|
|
|
@@ -1218,6 +1218,47 @@ export const InApp = (props) => {
|
|
|
1218
1218
|
// ── Old-flow helpers (used by CapDeviceContent when flag is disabled) ──────
|
|
1219
1219
|
const isAiContentBotDisabled = currentOrgDetails?.accessibleFeatures?.includes(AI_CONTENT_BOT_DISABLED);
|
|
1220
1220
|
|
|
1221
|
+
/**
|
|
1222
|
+
* Clears stored API/liquid errors for a specific device (and GENERIC) so
|
|
1223
|
+
* hasAnyErrors() goes false and Done can be re-clicked after editing.
|
|
1224
|
+
* Does NOT clear errors that belong only to the *other* device.
|
|
1225
|
+
*/
|
|
1226
|
+
const clearDeviceErrors = useCallback((platform) => {
|
|
1227
|
+
const key = platform === IOS ? IOS_CAPITAL : ANDROID;
|
|
1228
|
+
setErrorMessage((prev) => ({
|
|
1229
|
+
STANDARD_ERROR_MSG: {
|
|
1230
|
+
...prev.STANDARD_ERROR_MSG,
|
|
1231
|
+
[key]: [],
|
|
1232
|
+
GENERIC: [],
|
|
1233
|
+
},
|
|
1234
|
+
LIQUID_ERROR_MSG: {
|
|
1235
|
+
...prev.LIQUID_ERROR_MSG,
|
|
1236
|
+
[key]: [],
|
|
1237
|
+
GENERIC: [],
|
|
1238
|
+
},
|
|
1239
|
+
}));
|
|
1240
|
+
}, [IOS_CAPITAL, ANDROID]);
|
|
1241
|
+
|
|
1242
|
+
const setTitleAndroidWithClear = useCallback((value) => {
|
|
1243
|
+
clearDeviceErrors(ANDROID);
|
|
1244
|
+
setTitleAndroid(value);
|
|
1245
|
+
}, [clearDeviceErrors]);
|
|
1246
|
+
|
|
1247
|
+
const setTitleIosWithClear = useCallback((value) => {
|
|
1248
|
+
clearDeviceErrors(IOS);
|
|
1249
|
+
setTitleIos(value);
|
|
1250
|
+
}, [clearDeviceErrors]);
|
|
1251
|
+
|
|
1252
|
+
const setTemplateMessageAndroidWithClear = useCallback((value) => {
|
|
1253
|
+
clearDeviceErrors(ANDROID);
|
|
1254
|
+
setTemplateMessageAndroid(value);
|
|
1255
|
+
}, [clearDeviceErrors]);
|
|
1256
|
+
|
|
1257
|
+
const setTemplateMessageIosWithClear = useCallback((value) => {
|
|
1258
|
+
clearDeviceErrors(IOS);
|
|
1259
|
+
setTemplateMessageIos(value);
|
|
1260
|
+
}, [clearDeviceErrors]);
|
|
1261
|
+
|
|
1221
1262
|
const templateDescErrorHandler = (value) => {
|
|
1222
1263
|
const { unsupportedTags, isBraceError } = validateTags({
|
|
1223
1264
|
content: value,
|
|
@@ -1231,17 +1272,19 @@ export const InApp = (props) => {
|
|
|
1231
1272
|
return formatMessage(globalMessages.unsupportedTagsValidationError, { unsupportedTags });
|
|
1232
1273
|
}
|
|
1233
1274
|
if (isBraceError) {
|
|
1234
|
-
return formatMessage(globalMessages.
|
|
1275
|
+
return formatMessage(globalMessages.unbalanacedCurlyBraces);
|
|
1235
1276
|
}
|
|
1236
1277
|
return '';
|
|
1237
1278
|
};
|
|
1238
1279
|
|
|
1239
1280
|
const onCopyTitleAndContent = () => {
|
|
1240
1281
|
if (panes === ANDROID) {
|
|
1282
|
+
clearDeviceErrors(ANDROID);
|
|
1241
1283
|
setTitleAndroid(titleIos);
|
|
1242
1284
|
setTemplateMessageAndroid(templateMessageIos);
|
|
1243
1285
|
setInAppImageSrcAndroid(inAppImageSrcIos);
|
|
1244
1286
|
} else {
|
|
1287
|
+
clearDeviceErrors(IOS);
|
|
1245
1288
|
setTitleIos(titleAndroid);
|
|
1246
1289
|
setTemplateMessageIos(templateMessageAndroid);
|
|
1247
1290
|
setInAppImageSrcIos(inAppImageSrcAndroid);
|
|
@@ -1251,12 +1294,13 @@ export const InApp = (props) => {
|
|
|
1251
1294
|
const onTagSelect = (value, index) => {
|
|
1252
1295
|
const tag = `{{${value}}}`;
|
|
1253
1296
|
if (panes === ANDROID) {
|
|
1297
|
+
clearDeviceErrors(ANDROID);
|
|
1254
1298
|
if (index === 0) setTitleAndroid((prev) => prev + tag);
|
|
1255
1299
|
else setTemplateMessageAndroid((prev) => prev + tag);
|
|
1256
|
-
} else if (index === 0) {
|
|
1257
|
-
setTitleIos((prev) => prev + tag);
|
|
1258
1300
|
} else {
|
|
1259
|
-
|
|
1301
|
+
clearDeviceErrors(IOS);
|
|
1302
|
+
if (index === 0) setTitleIos((prev) => prev + tag);
|
|
1303
|
+
else setTemplateMessageIos((prev) => prev + tag);
|
|
1260
1304
|
}
|
|
1261
1305
|
};
|
|
1262
1306
|
|
|
@@ -1283,10 +1327,10 @@ export const InApp = (props) => {
|
|
|
1283
1327
|
templateMediaType={templateMediaType}
|
|
1284
1328
|
setTemplateMediaType={setTemplateMediaType}
|
|
1285
1329
|
title={titleAndroid}
|
|
1286
|
-
setTitle={
|
|
1330
|
+
setTitle={setTitleAndroidWithClear}
|
|
1287
1331
|
templateMessageError={templateMessageErrorAndroid}
|
|
1288
1332
|
templateMessage={templateMessageAndroid}
|
|
1289
|
-
setTemplateMessage={
|
|
1333
|
+
setTemplateMessage={setTemplateMessageAndroidWithClear}
|
|
1290
1334
|
setTemplateMessageError={setTemplateMessageErrorAndroid}
|
|
1291
1335
|
addActionLink={addActionLinkAndroid}
|
|
1292
1336
|
setAddActionLink={setAddActionLinkAndroid}
|
|
@@ -1328,10 +1372,10 @@ export const InApp = (props) => {
|
|
|
1328
1372
|
templateMediaType={templateMediaType}
|
|
1329
1373
|
setTemplateMediaType={setTemplateMediaType}
|
|
1330
1374
|
title={titleIos}
|
|
1331
|
-
setTitle={
|
|
1375
|
+
setTitle={setTitleIosWithClear}
|
|
1332
1376
|
templateMessageError={templateMessageErrorIos}
|
|
1333
1377
|
templateMessage={templateMessageIos}
|
|
1334
|
-
setTemplateMessage={
|
|
1378
|
+
setTemplateMessage={setTemplateMessageIosWithClear}
|
|
1335
1379
|
setTemplateMessageError={setTemplateMessageErrorIos}
|
|
1336
1380
|
addActionLink={addActionLinkIos}
|
|
1337
1381
|
setAddActionLink={setAddActionLinkIos}
|
|
@@ -5778,7 +5778,7 @@ FREE GIFTS-
|
|
|
5778
5778
|
</CapRow>
|
|
5779
5779
|
<Edit__SMSTraiFooter>
|
|
5780
5780
|
<div
|
|
5781
|
-
className="Edit__SMSTraiFooter-jwsec7-0
|
|
5781
|
+
className="Edit__SMSTraiFooter-jwsec7-0 cskOAw"
|
|
5782
5782
|
>
|
|
5783
5783
|
<CapButton
|
|
5784
5784
|
className="create-msg create-dlt-msg"
|
|
@@ -16756,7 +16756,7 @@ FREE GIFTS-
|
|
|
16756
16756
|
</CapRow>
|
|
16757
16757
|
<Edit__SMSTraiFooter>
|
|
16758
16758
|
<div
|
|
16759
|
-
className="Edit__SMSTraiFooter-jwsec7-0
|
|
16759
|
+
className="Edit__SMSTraiFooter-jwsec7-0 cskOAw"
|
|
16760
16760
|
>
|
|
16761
16761
|
<CapButton
|
|
16762
16762
|
className="create-msg create-dlt-msg"
|
|
@@ -27824,7 +27824,7 @@ FREE GIFTS-
|
|
|
27824
27824
|
</CapRow>
|
|
27825
27825
|
<Edit__SMSTraiFooter>
|
|
27826
27826
|
<div
|
|
27827
|
-
className="Edit__SMSTraiFooter-jwsec7-0
|
|
27827
|
+
className="Edit__SMSTraiFooter-jwsec7-0 cskOAw"
|
|
27828
27828
|
>
|
|
27829
27829
|
<CapButton
|
|
27830
27830
|
className="create-msg create-dlt-msg"
|