@capillarytech/creatives-library 8.0.316 → 8.0.317-alpha.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.
Files changed (172) hide show
  1. package/constants/unified.js +15 -0
  2. package/package.json +1 -1
  3. package/services/api.js +6 -0
  4. package/services/tests/api.test.js +7 -0
  5. package/utils/common.js +6 -1
  6. package/utils/templateVarUtils.js +172 -0
  7. package/utils/tests/tagValidations.test.js +34 -0
  8. package/utils/tests/templateVarUtils.test.js +160 -0
  9. package/v2Components/CapTagList/index.js +25 -22
  10. package/v2Components/CapTagList/style.scss +48 -0
  11. package/v2Components/CapTagListWithInput/__tests__/CapTagListWithInput.test.js +63 -0
  12. package/v2Components/CapTagListWithInput/index.js +4 -0
  13. package/v2Components/CapWhatsappCTA/index.js +2 -0
  14. package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +70 -49
  15. package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +8 -2
  16. package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +207 -21
  17. package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +16 -0
  18. package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +85 -10
  19. package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +30 -0
  20. package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +79 -11
  21. package/v2Components/CommonTestAndPreview/SendTestMessage.js +11 -5
  22. package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +20 -1
  23. package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +133 -4
  24. package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +12 -0
  25. package/v2Components/CommonTestAndPreview/constants.js +38 -0
  26. package/v2Components/CommonTestAndPreview/index.js +693 -155
  27. package/v2Components/CommonTestAndPreview/messages.js +41 -3
  28. package/v2Components/CommonTestAndPreview/previewApiUtils.js +59 -0
  29. package/v2Components/CommonTestAndPreview/sagas.js +15 -6
  30. package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +352 -0
  31. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +269 -1
  32. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +118 -5
  33. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +341 -0
  34. package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +25 -4
  35. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +199 -1
  36. package/v2Components/CommonTestAndPreview/tests/index.test.js +132 -4
  37. package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +67 -0
  38. package/v2Components/CommonTestAndPreview/tests/sagas.test.js +2 -2
  39. package/v2Components/FormBuilder/index.js +14 -1
  40. package/v2Components/HtmlEditor/HTMLEditor.js +6 -1
  41. package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +1 -0
  42. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +927 -2
  43. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +3 -0
  44. package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +87 -0
  45. package/v2Components/SmsFallback/constants.js +73 -0
  46. package/v2Components/SmsFallback/index.js +956 -0
  47. package/v2Components/SmsFallback/index.scss +265 -0
  48. package/v2Components/SmsFallback/messages.js +78 -0
  49. package/v2Components/SmsFallback/smsFallbackUtils.js +107 -0
  50. package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +50 -0
  51. package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +147 -0
  52. package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +304 -0
  53. package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +197 -0
  54. package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +261 -0
  55. package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +422 -0
  56. package/v2Components/SmsFallback/useLocalTemplateList.js +92 -0
  57. package/v2Components/TestAndPreviewSlidebox/index.js +8 -1
  58. package/v2Components/TestAndPreviewSlidebox/sagas.js +11 -4
  59. package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +3 -1
  60. package/v2Components/VarSegmentMessageEditor/constants.js +2 -0
  61. package/v2Components/VarSegmentMessageEditor/index.js +125 -0
  62. package/v2Components/VarSegmentMessageEditor/index.scss +46 -0
  63. package/v2Containers/BeeEditor/index.js +3 -0
  64. package/v2Containers/CommunicationFlow/CommunicationFlow.js +291 -0
  65. package/v2Containers/CommunicationFlow/CommunicationFlow.scss +25 -0
  66. package/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +255 -0
  67. package/v2Containers/CommunicationFlow/constants.js +200 -0
  68. package/v2Containers/CommunicationFlow/index.js +102 -0
  69. package/v2Containers/CommunicationFlow/messages.js +346 -0
  70. package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.js +522 -0
  71. package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.scss +170 -0
  72. package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/Tests/ChannelSelectionStep.test.js +796 -0
  73. package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/index.js +5 -0
  74. package/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/CommunicationStrategyStep.js +95 -0
  75. package/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/Tests/CommunicationStrategyStep.test.js +133 -0
  76. package/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/index.js +5 -0
  77. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.js +289 -0
  78. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.scss +70 -0
  79. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.js +319 -0
  80. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.scss +69 -0
  81. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/DeliverySettingsSection.test.js +616 -0
  82. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +577 -0
  83. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/deliverySettingsConfig.test.js +1111 -0
  84. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/deliverySettingsConfig.js +696 -0
  85. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/index.js +7 -0
  86. package/v2Containers/CommunicationFlow/steps/DynamicControlsStep/DynamicControlsStep.js +102 -0
  87. package/v2Containers/CommunicationFlow/steps/DynamicControlsStep/DynamicControlsStep.scss +36 -0
  88. package/v2Containers/CommunicationFlow/steps/DynamicControlsStep/Tests/DynamicControlsStep.test.js +91 -0
  89. package/v2Containers/CommunicationFlow/steps/DynamicControlsStep/index.js +5 -0
  90. package/v2Containers/CommunicationFlow/steps/MessageTypeStep/MessageTypeStep.js +86 -0
  91. package/v2Containers/CommunicationFlow/steps/MessageTypeStep/Tests/MessageTypeStep.test.js +100 -0
  92. package/v2Containers/CommunicationFlow/steps/MessageTypeStep/index.js +5 -0
  93. package/v2Containers/CommunicationFlow/utils/getEnabledSteps.js +30 -0
  94. package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +43 -0
  95. package/v2Containers/CreativesContainer/SlideBoxContent.js +64 -5
  96. package/v2Containers/CreativesContainer/SlideBoxFooter.js +10 -1
  97. package/v2Containers/CreativesContainer/SlideBoxHeader.js +29 -4
  98. package/v2Containers/CreativesContainer/constants.js +12 -0
  99. package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +67 -0
  100. package/v2Containers/CreativesContainer/index.js +289 -93
  101. package/v2Containers/CreativesContainer/index.scss +51 -1
  102. package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +90 -0
  103. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +104 -0
  104. package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +110 -0
  105. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +8 -0
  106. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +363 -0
  107. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +20 -10
  108. package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +258 -0
  109. package/v2Containers/CreativesContainer/tests/index.test.js +71 -9
  110. package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +125 -0
  111. package/v2Containers/Email/index.js +1 -0
  112. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +7 -1
  113. package/v2Containers/EmailWrapper/components/EmailWrapperView.js +3 -0
  114. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +20 -2
  115. package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +16 -1
  116. package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +3 -0
  117. package/v2Containers/EmailWrapper/index.js +4 -0
  118. package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +1 -0
  119. package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +9 -0
  120. package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +19 -0
  121. package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +3 -0
  122. package/v2Containers/InAppWrapper/index.js +3 -0
  123. package/v2Containers/MobilePush/Create/index.js +2 -0
  124. package/v2Containers/MobilePush/Edit/index.js +2 -0
  125. package/v2Containers/MobilepushWrapper/index.js +3 -1
  126. package/v2Containers/Rcs/constants.js +32 -1
  127. package/v2Containers/Rcs/index.js +951 -873
  128. package/v2Containers/Rcs/index.scss +85 -6
  129. package/v2Containers/Rcs/messages.js +10 -1
  130. package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +205 -0
  131. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +40834 -1963
  132. package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +0 -5
  133. package/v2Containers/Rcs/tests/index.test.js +41 -38
  134. package/v2Containers/Rcs/tests/mockData.js +38 -0
  135. package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +251 -0
  136. package/v2Containers/Rcs/tests/utils.test.js +379 -1
  137. package/v2Containers/Rcs/utils.js +358 -10
  138. package/v2Containers/Sms/Create/index.js +83 -36
  139. package/v2Containers/Sms/Edit/index.js +2 -0
  140. package/v2Containers/Sms/smsFormDataHelpers.js +67 -0
  141. package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +253 -0
  142. package/v2Containers/SmsTrai/Create/index.js +9 -4
  143. package/v2Containers/SmsTrai/Edit/constants.js +2 -0
  144. package/v2Containers/SmsTrai/Edit/index.js +611 -128
  145. package/v2Containers/SmsTrai/Edit/index.scss +121 -0
  146. package/v2Containers/SmsTrai/Edit/messages.js +9 -4
  147. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4327 -2374
  148. package/v2Containers/SmsWrapper/index.js +39 -8
  149. package/v2Containers/TagList/index.js +47 -2
  150. package/v2Containers/TagList/messages.js +4 -0
  151. package/v2Containers/TagList/tests/TagList.test.js +122 -20
  152. package/v2Containers/TagList/tests/mockdata.js +17 -0
  153. package/v2Containers/Templates/TemplatesActionBar.js +101 -0
  154. package/v2Containers/Templates/_templates.scss +61 -2
  155. package/v2Containers/Templates/actions.js +11 -0
  156. package/v2Containers/Templates/constants.js +2 -0
  157. package/v2Containers/Templates/index.js +90 -40
  158. package/v2Containers/Templates/sagas.js +57 -12
  159. package/v2Containers/Templates/tests/TemplatesActionBar.test.js +120 -0
  160. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1043 -1079
  161. package/v2Containers/Templates/tests/sagas.test.js +193 -12
  162. package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +180 -0
  163. package/v2Containers/Templates/utils/smsTemplatesListApi.js +79 -0
  164. package/v2Containers/TemplatesV2/TemplatesV2.style.js +72 -1
  165. package/v2Containers/TemplatesV2/index.js +86 -23
  166. package/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +131 -0
  167. package/v2Containers/Viber/index.js +5 -0
  168. package/v2Containers/WebPush/Create/hooks/useTagManagement.js +0 -2
  169. package/v2Containers/WebPush/Create/index.js +9 -1
  170. package/v2Containers/Whatsapp/index.js +8 -20
  171. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +598 -34
  172. package/v2Containers/Zalo/index.js +2 -0
@@ -0,0 +1,63 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import '@testing-library/jest-dom';
4
+ import { IntlProvider } from 'react-intl';
5
+ import CapTagListWithInput from '../index';
6
+
7
+ const capturedTagListProps = { current: null };
8
+
9
+ jest.mock('../../../v2Containers/TagList', () => {
10
+ const React = require('react');
11
+ const Mock = (props) => {
12
+ capturedTagListProps.current = props;
13
+ return <div data-testid="mock-tag-list">TagList</div>;
14
+ };
15
+ return Mock;
16
+ });
17
+
18
+ jest.mock('@capillarytech/cap-ui-library/CapRow', () => ({ children }) => <div>{children}</div>);
19
+ jest.mock('@capillarytech/cap-ui-library/CapColumn', () => ({ children }) => <div>{children}</div>);
20
+ jest.mock('@capillarytech/cap-ui-library/CapHeading', () => () => null);
21
+ jest.mock('@capillarytech/cap-ui-library/CapInput', () => () => <input data-testid="cap-input" />);
22
+
23
+ const waitMap = {
24
+ b1: { eventName: 'Order Placed', blockName: 'Wait', tags: [] },
25
+ };
26
+
27
+ describe('CapTagListWithInput', () => {
28
+ beforeEach(() => {
29
+ capturedTagListProps.current = null;
30
+ });
31
+
32
+ it('forwards waitEventContextTags to TagList', () => {
33
+ render(
34
+ <IntlProvider locale="en" messages={{}}>
35
+ <CapTagListWithInput
36
+ inputId="test-url"
37
+ inputOnChange={jest.fn()}
38
+ waitEventContextTags={waitMap}
39
+ onTagSelect={jest.fn()}
40
+ onContextChange={jest.fn()}
41
+ />
42
+ </IntlProvider>
43
+ );
44
+
45
+ expect(screen.getByTestId('mock-tag-list')).toBeInTheDocument();
46
+ expect(capturedTagListProps.current.waitEventContextTags).toEqual(waitMap);
47
+ });
48
+
49
+ it('uses default empty object for waitEventContextTags when omitted', () => {
50
+ render(
51
+ <IntlProvider locale="en" messages={{}}>
52
+ <CapTagListWithInput
53
+ inputId="test-url"
54
+ inputOnChange={jest.fn()}
55
+ onTagSelect={jest.fn()}
56
+ onContextChange={jest.fn()}
57
+ />
58
+ </IntlProvider>
59
+ );
60
+
61
+ expect(capturedTagListProps.current.waitEventContextTags).toEqual({});
62
+ });
63
+ });
@@ -27,6 +27,7 @@ export const CapTagListWithInput = (props) => {
27
27
  userLocale = 'en',
28
28
  eventContextTags = [],
29
29
  restrictPersonalization = false,
30
+ waitEventContextTags = {},
30
31
  // CapInput props
31
32
  inputId,
32
33
  inputValue = '',
@@ -77,6 +78,7 @@ export const CapTagListWithInput = (props) => {
77
78
  userLocale={userLocale}
78
79
  selectedOfferDetails={selectedOfferDetails}
79
80
  eventContextTags={eventContextTags}
81
+ waitEventContextTags={waitEventContextTags}
80
82
  style={tagListStyle}
81
83
  popoverPlacement={popoverPlacement}
82
84
  restrictPersonalization={restrictPersonalization}
@@ -116,6 +118,7 @@ CapTagListWithInput.propTypes = {
116
118
  userLocale: PropTypes.string,
117
119
  eventContextTags: PropTypes.array,
118
120
  restrictPersonalization: PropTypes.bool,
121
+ waitEventContextTags: PropTypes.object,
119
122
 
120
123
  // CapInput props
121
124
  inputId: PropTypes.string.isRequired,
@@ -154,6 +157,7 @@ CapTagListWithInput.defaultProps = {
154
157
  userLocale: 'en',
155
158
  eventContextTags: [],
156
159
  restrictPersonalization: false,
160
+ waitEventContextTags: {},
157
161
  inputValue: '',
158
162
  inputSize: 'default',
159
163
  inputRequired: false,
@@ -52,6 +52,7 @@ export const CapWhatsappCTA = (props) => {
52
52
  injectedTags = {},
53
53
  selectedOfferDetails = [],
54
54
  eventContextTags = [],
55
+ waitEventContextTags = {},
55
56
  } = props;
56
57
  const { formatMessage } = intl;
57
58
  const invalidVarRegex = /{{(.*?)}}/g;
@@ -283,6 +284,7 @@ export const CapWhatsappCTA = (props) => {
283
284
  injectedTags={injectedTags}
284
285
  selectedOfferDetails={selectedOfferDetails}
285
286
  eventContextTags={eventContextTags}
287
+ waitEventContextTags={waitEventContextTags}
286
288
  />
287
289
  </CapColumn>
288
290
  )}
@@ -8,6 +8,7 @@ import CapButton from '@capillarytech/cap-ui-library/CapButton';
8
8
  import CapInput from '@capillarytech/cap-ui-library/CapInput';
9
9
  import CapLabel from '@capillarytech/cap-ui-library/CapLabel';
10
10
  import messages from './messages';
11
+ import { CUSTOM_VALUES_EDITOR_SECTION_FALLBACK_KEY } from './constants';
11
12
 
12
13
  const CustomValuesEditor = ({
13
14
  isExtractingTags,
@@ -16,15 +17,16 @@ const CustomValuesEditor = ({
16
17
  setShowJSON,
17
18
  customValues,
18
19
  handleJSONTextChange,
19
- extractedTags,
20
- requiredTags,
21
- optionalTags,
20
+ sections,
22
21
  handleCustomValueChange,
23
22
  handleDiscardCustomValues,
24
23
  handleUpdatePreview,
25
24
  isUpdatingPreview,
26
25
  formatMessage,
27
26
  }) => {
27
+ /** Same as SMS Test & Preview: show token path from extract-tags (fullPath or name). */
28
+ const getPersonalizationTagColumnLabel = (tagNode) => tagNode?.fullPath ?? tagNode?.name ?? '';
29
+
28
30
  if (isExtractingTags) {
29
31
  return (
30
32
  <CapRow className="loading-container">
@@ -77,52 +79,68 @@ const CustomValuesEditor = ({
77
79
  </CapRow>
78
80
  ) : (
79
81
  <>
80
- {extractedTags?.length > 0 && (
81
- <CapRow className="values-table">
82
- <CapRow className="table-header">
83
- <CapLabel type="label31" className="header-cell">
84
- <FormattedMessage {...messages.personalizationTags} />
85
- </CapLabel>
86
- <CapLabel type="label31" className="header-cell">
87
- <FormattedMessage {...messages.customValues} />
82
+ {(sections || []).filter((tagsSection) =>
83
+ (tagsSection?.requiredTags?.length || 0) + (tagsSection?.optionalTags?.length || 0) > 0).map((section) => (
84
+ <React.Fragment key={section.key || section.title?.id || section.title || CUSTOM_VALUES_EDITOR_SECTION_FALLBACK_KEY}>
85
+ {section.title ? (
86
+ <CapLabel type="label2" className="tags-section-title">
87
+ {typeof section.title === 'string' ? section.title : <FormattedMessage {...section.title} />}
88
88
  </CapLabel>
89
- </CapRow>
90
- {requiredTags.map((tag) => (
91
- <CapRow key={tag.fullPath} className="value-row">
92
- <CapRow className="tag-name">
93
- {tag.fullPath}
94
- <span className="required-tag-indicator">*</span>
95
- </CapRow>
96
- <CapRow className="tag-input">
97
- <CapInput
98
- type="text"
99
- isRequired
100
- className="tag-input-field"
101
- value={customValues[tag.fullPath] || ''}
102
- onChange={(e) => handleCustomValueChange(tag.fullPath, e.target.value)}
103
- placeholder={formatMessage(messages.enterValue)}
104
- size="small"
105
- />
106
- </CapRow>
89
+ ) : null}
90
+ <CapRow className="values-table">
91
+ <CapRow className="table-header">
92
+ <CapLabel type="label31" className="header-cell">
93
+ <FormattedMessage {...messages.personalizationTags} />
94
+ </CapLabel>
95
+ <CapLabel type="label31" className="header-cell">
96
+ <FormattedMessage {...messages.customValues} />
97
+ </CapLabel>
107
98
  </CapRow>
108
- ))}
109
- {optionalTags?.map((tag) => (
110
- <CapRow key={tag.fullPath} className="value-row">
111
- <CapRow className="tag-name">{tag.fullPath}</CapRow>
112
- <CapRow className="tag-input">
113
- <CapInput
114
- type="text"
115
- className="tag-input-field"
116
- value={customValues[tag.fullPath] || ''}
117
- onChange={(e) => handleCustomValueChange(tag.fullPath, e.target.value)}
118
- placeholder={formatMessage(messages.enterValue)}
119
- size="small"
120
- />
99
+ {(section?.requiredTags || []).map((tag, tagIndex) => {
100
+ const personalizationTagColumnText = getPersonalizationTagColumnLabel(tag);
101
+ return (
102
+ <CapRow key={tag?.fullPath ?? `required-${tagIndex}`} className="value-row">
103
+ <CapRow className="tag-name">
104
+ {personalizationTagColumnText}
105
+ <span className="required-tag-indicator">*</span>
106
+ </CapRow>
107
+ <CapRow className="tag-input">
108
+ <CapInput
109
+ type="text"
110
+ isRequired
111
+ className="tag-input-field"
112
+ value={customValues?.[tag?.fullPath] ?? ''}
113
+ onChange={(e) => handleCustomValueChange(tag?.fullPath, e.target.value)}
114
+ placeholder={formatMessage(messages.enterValue)}
115
+ size="small"
116
+ />
117
+ </CapRow>
121
118
  </CapRow>
122
- </CapRow>
123
- ))}
124
- </CapRow>
125
- )}
119
+ );
120
+ })}
121
+ {(section?.optionalTags || []).map((tag, tagIndex) => {
122
+ const personalizationTagColumnText = getPersonalizationTagColumnLabel(tag);
123
+ return (
124
+ <CapRow key={tag?.fullPath ?? `optional-${tagIndex}`} className="value-row">
125
+ <CapRow className="tag-name">
126
+ {personalizationTagColumnText}
127
+ </CapRow>
128
+ <CapRow className="tag-input">
129
+ <CapInput
130
+ type="text"
131
+ className="tag-input-field"
132
+ value={customValues?.[tag?.fullPath] ?? ''}
133
+ onChange={(e) => handleCustomValueChange(tag?.fullPath, e.target.value)}
134
+ placeholder={formatMessage(messages.enterValue)}
135
+ size="small"
136
+ />
137
+ </CapRow>
138
+ </CapRow>
139
+ );
140
+ })}
141
+ </CapRow>
142
+ </React.Fragment>
143
+ ))}
126
144
  </>
127
145
  )}
128
146
  <CapRow className="editor-actions">
@@ -156,9 +174,12 @@ CustomValuesEditor.propTypes = {
156
174
  setShowJSON: PropTypes.func.isRequired,
157
175
  customValues: PropTypes.object.isRequired,
158
176
  handleJSONTextChange: PropTypes.func.isRequired,
159
- extractedTags: PropTypes.array.isRequired,
160
- requiredTags: PropTypes.array.isRequired,
161
- optionalTags: PropTypes.array.isRequired,
177
+ sections: PropTypes.arrayOf(PropTypes.shape({
178
+ key: PropTypes.string,
179
+ title: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
180
+ requiredTags: PropTypes.array,
181
+ optionalTags: PropTypes.array,
182
+ })).isRequired,
162
183
  handleCustomValueChange: PropTypes.func.isRequired,
163
184
  handleDiscardCustomValues: PropTypes.func.isRequired,
164
185
  handleUpdatePreview: PropTypes.func.isRequired,
@@ -18,11 +18,17 @@
18
18
  }
19
19
 
20
20
  &__summary-entry {
21
+ display: flex;
22
+ align-items: baseline;
23
+ gap: 0;
21
24
  margin-right: $CAP_SPACE_18;
22
25
  }
23
26
 
24
- &__summary-key {
25
- line-height: $CAP_SPACE_16;
27
+ &__summary-key,
28
+ &__summary-value {
29
+ line-height: 1.4;
30
+ margin-top: 0;
31
+ margin-bottom: 0;
26
32
  }
27
33
 
28
34
  &__edit-icon {
@@ -32,16 +32,37 @@ import {
32
32
  DELIVERY_SETTING_KEY_SENDER_REPLY_TO,
33
33
  DELIVERY_SETTING_KEY_SOURCE_ACCOUNT_IDENTIFIER,
34
34
  DELIVERY_SETTING_KEY_SENDER_MOB_NUM,
35
+ DELIVERY_SETTING_KEY_SMS_FALLBACK_DOMAIN_ID,
35
36
  } from './constants';
36
37
  import './ModifyDeliverySettings.scss';
37
38
 
38
39
  const findDefault = (array) => find(array, { default: true }) || (array && array[0]) || {};
39
40
 
41
+ /**
42
+ * Drop empty GSM rows. Optionally drop rows whose value equals domain name — some APIs duplicate
43
+ * domain label as a bogus sender row; RCS/DLT often legitimately use the same string (e.g. DetailsForGW1).
44
+ */
45
+ const filterUsableGsmSendersForDomain = (domain, gsmSenders, { skipDomainNameEchoFilter = false } = {}) => {
46
+ const normalizedDomainName =
47
+ domain?.domainName != null ? String(domain.domainName).trim().toLowerCase() : '';
48
+ return (gsmSenders || []).filter((gsmSenderRow) => {
49
+ const rawValue = gsmSenderRow?.value;
50
+ if (rawValue == null) return false;
51
+ const trimmedSenderValue = String(rawValue).trim();
52
+ if (!trimmedSenderValue) return false;
53
+ const senderMatchesDomainLabel =
54
+ normalizedDomainName && trimmedSenderValue.toLowerCase() === normalizedDomainName;
55
+ if (!skipDomainNameEchoFilter && senderMatchesDomainLabel) return false;
56
+ return true;
57
+ });
58
+ };
59
+
40
60
  const ModifyDeliverySettings = (props) => {
41
61
  const {
42
62
  channel,
43
63
  deliverySettings: initialSettings = {},
44
64
  senderDetailsOptions = [],
65
+ smsFallbackSenderDetailsOptions = [],
45
66
  wecrmAccounts = [],
46
67
  onSaveDeliverySettings,
47
68
  onClose,
@@ -102,17 +123,21 @@ const ModifyDeliverySettings = (props) => {
102
123
  if (!(channel === CHANNELS.SMS && smsTraiDltEnabled)) {
103
124
  return allDomainOptions;
104
125
  }
126
+ // Without template registered sender IDs, strict DLT filter removes every domain — keep full list.
127
+ if (!registeredSenderIds?.length) {
128
+ return allDomainOptions;
129
+ }
105
130
 
106
- return allDomainOptions.filter((domain) => (domain.gsmSenders || []).some(
107
- (gsmId) => registeredSenderIds.includes(gsmId.value),
131
+ return allDomainOptions.filter((domain) => (domain?.gsmSenders || []).some(
132
+ (gsmSenderOption) => registeredSenderIds?.includes(gsmSenderOption?.value),
108
133
  ));
109
134
  }, [allDomainOptions, channel, registeredSenderIds, smsTraiDltEnabled]);
110
135
 
111
136
  const selectedDomain = useMemo(
112
137
  () => (senderDetailsOptions || []).find(
113
- (d) => d.domainId === get(localSettings, DELIVERY_SETTING_KEY_DOMAIN_ID),
138
+ (senderDomain) => senderDomain.domainId === get(localSettings, DELIVERY_SETTING_KEY_DOMAIN_ID),
114
139
  ) || {},
115
- [senderDetailsOptions, localSettings.domainId],
140
+ [senderDetailsOptions, get(localSettings, DELIVERY_SETTING_KEY_DOMAIN_ID)],
116
141
  );
117
142
  const {
118
143
  gsmSenders: selectedDomainGsmSenders = [],
@@ -120,25 +145,103 @@ const ModifyDeliverySettings = (props) => {
120
145
  emailRepliers: selectedDomainEmailRepliers = [],
121
146
  } = selectedDomain;
122
147
 
148
+ const rcsSenderOptions = useMemo(
149
+ () => {
150
+ if (channel !== CHANNELS.RCS) return [];
151
+ const rcsDomainRows = senderDetailsOptions || [];
152
+ const selectedRcsDomainId = get(localSettings, DELIVERY_SETTING_KEY_DOMAIN_ID);
153
+ const rcsDomainsForDropdown =
154
+ selectedRcsDomainId != null && selectedRcsDomainId !== ''
155
+ ? rcsDomainRows.filter((senderDomain) => senderDomain?.domainId === selectedRcsDomainId)
156
+ : rcsDomainRows;
157
+ return rcsDomainsForDropdown.flatMap((senderDomain) =>
158
+ filterUsableGsmSendersForDomain(senderDomain, senderDomain?.gsmSenders, {
159
+ skipDomainNameEchoFilter: true,
160
+ }).map((gsmSenderRow) => ({
161
+ value: senderDomain?.domainId != null && gsmSenderRow?.value != null
162
+ ? `${senderDomain.domainId}|${gsmSenderRow.value}`
163
+ : gsmSenderRow?.value,
164
+ label: String(gsmSenderRow?.value ?? ''),
165
+ })));
166
+ },
167
+ [channel, senderDetailsOptions, localSettings],
168
+ );
169
+
170
+ const rcsGsmSenderIdForSelect = useMemo(() => {
171
+ const raw = get(localSettings, DELIVERY_SETTING_KEY_GSM_SENDER_ID);
172
+ if (raw == null || raw === '') return undefined;
173
+ const allowed = new Set((rcsSenderOptions || []).map((senderOption) => senderOption.value));
174
+ return allowed.has(raw) ? raw : undefined;
175
+ }, [localSettings, rcsSenderOptions]);
176
+
177
+ const smsFallbackDomainOptions = useMemo(
178
+ () => {
179
+ const raw = (smsFallbackSenderDetailsOptions || []).map((senderDetails) => ({
180
+ label: senderDetails.domainName || senderDetails.domainId,
181
+ value: senderDetails.domainId,
182
+ ...senderDetails,
183
+ }));
184
+ if (!(channel === CHANNELS.RCS && smsTraiDltEnabled && registeredSenderIds?.length)) {
185
+ return raw;
186
+ }
187
+ return raw.filter((domain) => (domain?.gsmSenders || []).some(
188
+ (gsmSenderOption) => registeredSenderIds?.includes(gsmSenderOption?.value),
189
+ ));
190
+ },
191
+ [channel, smsFallbackSenderDetailsOptions, smsTraiDltEnabled, registeredSenderIds],
192
+ );
193
+
194
+ const smsSenderOptions = useMemo(
195
+ () => {
196
+ if (channel !== CHANNELS.RCS) return [];
197
+ const smsFallbackDomainRows = smsFallbackSenderDetailsOptions || [];
198
+ const selectedSmsFallbackDomainId = get(localSettings, DELIVERY_SETTING_KEY_SMS_FALLBACK_DOMAIN_ID);
199
+ const smsFallbackDomainsForDropdown =
200
+ selectedSmsFallbackDomainId != null && selectedSmsFallbackDomainId !== ''
201
+ ? smsFallbackDomainRows.filter((senderDomain) => senderDomain?.domainId === selectedSmsFallbackDomainId)
202
+ : smsFallbackDomainRows;
203
+ const shouldFilterSmsSendersByDltRegistration = smsTraiDltEnabled && registeredSenderIds?.length;
204
+ return smsFallbackDomainsForDropdown.flatMap((senderDomain) =>
205
+ filterUsableGsmSendersForDomain(senderDomain, senderDomain?.gsmSenders)
206
+ .filter((smsGsmSenderRow) =>
207
+ !shouldFilterSmsSendersByDltRegistration || registeredSenderIds?.includes(smsGsmSenderRow?.value))
208
+ .map((gsmSenderRow) => ({
209
+ value: senderDomain?.domainId != null && gsmSenderRow?.value != null
210
+ ? `${senderDomain.domainId}|${gsmSenderRow.value}`
211
+ : gsmSenderRow?.value,
212
+ label: String(gsmSenderRow?.value ?? ''),
213
+ })));
214
+ },
215
+ [channel, smsFallbackSenderDetailsOptions, localSettings, smsTraiDltEnabled, registeredSenderIds],
216
+ );
217
+
218
+ const smsFallbackGsmIdForSelect = useMemo(() => {
219
+ const raw = get(localSettings, DELIVERY_SETTING_KEY_CDMA_SENDER_ID);
220
+ if (raw == null || raw === '') return undefined;
221
+ const allowed = new Set((smsSenderOptions || []).map((senderOption) => senderOption.value));
222
+ return allowed.has(raw) ? raw : undefined;
223
+ }, [localSettings, smsSenderOptions]);
224
+
123
225
  const gsmOptions = useMemo(
124
226
  () => {
125
- const smsGsmSenders = channel === CHANNELS.SMS && smsTraiDltEnabled
126
- ? selectedDomainGsmSenders.filter((gsmId) => registeredSenderIds.includes(gsmId.value))
227
+ const smsGsmSendersForSelect = channel === CHANNELS.SMS && smsTraiDltEnabled && registeredSenderIds?.length
228
+ ? selectedDomainGsmSenders.filter((gsmSenderOption) =>
229
+ registeredSenderIds?.includes(gsmSenderOption?.value))
127
230
  : selectedDomainGsmSenders;
128
231
 
129
- return smsGsmSenders.map((o) => ({
130
- label: o.value || o.label,
131
- value: o.value,
232
+ return smsGsmSendersForSelect.map((gsmSenderRow) => ({
233
+ label: gsmSenderRow?.value || gsmSenderRow?.label,
234
+ value: gsmSenderRow?.value,
132
235
  }));
133
236
  },
134
237
  [channel, registeredSenderIds, selectedDomainGsmSenders, smsTraiDltEnabled],
135
238
  );
136
239
 
137
240
  const emailSenderOptions = useMemo(
138
- () => selectedDomainEmailSenders.map((o) => ({
139
- label: o.value || o.label,
140
- value: o.value,
141
- senderLabel: o.label,
241
+ () => selectedDomainEmailSenders.map((emailSenderRow) => ({
242
+ label: emailSenderRow.value || emailSenderRow.label,
243
+ value: emailSenderRow.value,
244
+ senderLabel: emailSenderRow.label,
142
245
  })),
143
246
  [selectedDomainEmailSenders],
144
247
  );
@@ -204,13 +307,47 @@ const ModifyDeliverySettings = (props) => {
204
307
  });
205
308
  }, []);
206
309
 
310
+ const onSmsFallbackDomainChange = useCallback(
311
+ (value) => {
312
+ setLocalSettings((prev) => {
313
+ const next = cloneDeep(prev);
314
+ next[DELIVERY_SETTING_KEY_SMS_FALLBACK_DOMAIN_ID] = value;
315
+ const selectedSmsFallbackDomain = (smsFallbackSenderDetailsOptions || []).find(
316
+ (senderDomain) => senderDomain?.domainId === value,
317
+ );
318
+ const usableSmsFallbackGsmSenders = filterUsableGsmSendersForDomain(
319
+ selectedSmsFallbackDomain,
320
+ selectedSmsFallbackDomain?.gsmSenders,
321
+ );
322
+ const firstSmsFallbackGsmSender = usableSmsFallbackGsmSenders[0];
323
+ const composite = selectedSmsFallbackDomain?.domainId != null && firstSmsFallbackGsmSender?.value != null
324
+ ? `${selectedSmsFallbackDomain.domainId}|${firstSmsFallbackGsmSender.value}`
325
+ : (firstSmsFallbackGsmSender?.value || '');
326
+ next[DELIVERY_SETTING_KEY_CDMA_SENDER_ID] = composite;
327
+ return next;
328
+ });
329
+ },
330
+ [smsFallbackSenderDetailsOptions],
331
+ );
332
+
207
333
  const onDomainChange = useCallback(
208
334
  (value) => {
209
- const domain = domainOptions.find((d) => d.value === value);
335
+ const domain = domainOptions.find((domainOption) => domainOption.value === value);
210
336
  updateSetting(DELIVERY_SETTING_KEY_DOMAIN_ID, value);
211
337
  if (domain?.dgmId != null) updateSetting(DELIVERY_SETTING_KEY_DOMAIN_GATEWAY_MAP_ID, domain.dgmId);
338
+ if (channel === CHANNELS.RCS && domain) {
339
+ const usableRcsGsmSenders = filterUsableGsmSendersForDomain(domain, domain?.gsmSenders, {
340
+ skipDomainNameEchoFilter: true,
341
+ });
342
+ const firstRcsGsmSender = usableRcsGsmSenders[0];
343
+ const composite = domain?.domainId != null && firstRcsGsmSender?.value != null
344
+ ? `${domain.domainId}|${firstRcsGsmSender.value}`
345
+ : (firstRcsGsmSender?.value || '');
346
+ updateSetting(DELIVERY_SETTING_KEY_GSM_SENDER_ID, composite);
347
+ return;
348
+ }
212
349
  if (channel === CHANNELS.SMS && domain) {
213
- const smsGsmSenders = smsTraiDltEnabled
350
+ const smsGsmSenders = smsTraiDltEnabled && registeredSenderIds?.length
214
351
  ? (domain.gsmSenders || []).filter((gsmId) => registeredSenderIds.includes(gsmId.value))
215
352
  : domain.gsmSenders;
216
353
  const def = findDefault(smsGsmSenders);
@@ -230,9 +367,20 @@ const ModifyDeliverySettings = (props) => {
230
367
  );
231
368
 
232
369
  const handleDone = useCallback(() => {
233
- onSaveDeliverySettings(localSettings);
370
+ const next = cloneDeep(localSettings);
371
+ if (channel === CHANNELS.RCS) {
372
+ const rawRcs = get(next, DELIVERY_SETTING_KEY_GSM_SENDER_ID);
373
+ if (rawRcs && !(rcsSenderOptions || []).some((senderOption) => senderOption.value === rawRcs)) {
374
+ next[DELIVERY_SETTING_KEY_GSM_SENDER_ID] = '';
375
+ }
376
+ const rawSms = get(next, DELIVERY_SETTING_KEY_CDMA_SENDER_ID);
377
+ if (rawSms && !(smsSenderOptions || []).some((senderOption) => senderOption.value === rawSms)) {
378
+ next[DELIVERY_SETTING_KEY_CDMA_SENDER_ID] = '';
379
+ }
380
+ }
381
+ onSaveDeliverySettings(next);
234
382
  if (onClose) onClose();
235
- }, [localSettings, onSaveDeliverySettings, onClose]);
383
+ }, [channel, localSettings, onSaveDeliverySettings, onClose, rcsSenderOptions, smsSenderOptions]);
236
384
 
237
385
  const renderSelectRow = useCallback(
238
386
  ({
@@ -286,7 +434,7 @@ const ModifyDeliverySettings = (props) => {
286
434
  value: get(localSettings, DELIVERY_SETTING_KEY_SENDER_EMAIL),
287
435
  onChange: (val) => {
288
436
  const sender = selectedDomainEmailSenders.find(
289
- (s) => s.value === val,
437
+ (emailSenderRow) => emailSenderRow.value === val,
290
438
  );
291
439
  updateSetting(DELIVERY_SETTING_KEY_SENDER_EMAIL, val);
292
440
  updateSetting(DELIVERY_SETTING_KEY_SENDER_LABEL, sender?.label || val);
@@ -298,7 +446,7 @@ const ModifyDeliverySettings = (props) => {
298
446
  value: get(localSettings, DELIVERY_SETTING_KEY_SENDER_LABEL) || '',
299
447
  onChange: (val) => {
300
448
  const sender = selectedDomainEmailSenders.find(
301
- (s) => (s.label || s.value) === val,
449
+ (emailSenderRow) => (emailSenderRow.label || emailSenderRow.value) === val,
302
450
  );
303
451
  if (sender) {
304
452
  updateSetting(DELIVERY_SETTING_KEY_SENDER_EMAIL, sender.value);
@@ -326,7 +474,7 @@ const ModifyDeliverySettings = (props) => {
326
474
  onChange: (val) => {
327
475
  updateSetting(DELIVERY_SETTING_KEY_SOURCE_ACCOUNT_IDENTIFIER, val);
328
476
  const domain = (senderDetailsOptions || []).find(
329
- (d) => d.sourceAccountIdentifier === val,
477
+ (whatsappAccountRow) => whatsappAccountRow.sourceAccountIdentifier === val,
330
478
  );
331
479
  const first = domain?.gsmSenders?.[0];
332
480
  updateSetting(DELIVERY_SETTING_KEY_SENDER_MOB_NUM, first?.value || '');
@@ -340,10 +488,39 @@ const ModifyDeliverySettings = (props) => {
340
488
  onChange: (val) => updateSetting(DELIVERY_SETTING_KEY_SENDER_MOB_NUM, val),
341
489
  },
342
490
  ];
491
+ const rcsFields = [
492
+ {
493
+ titleMessage: messages.rcsDomainLabel,
494
+ options: domainOptions,
495
+ value: get(localSettings, DELIVERY_SETTING_KEY_DOMAIN_ID),
496
+ onChange: (val) => onDomainChange(val),
497
+ },
498
+ {
499
+ titleMessage: messages.rcsSenderIdLabel,
500
+ options: rcsSenderOptions,
501
+ value: rcsGsmSenderIdForSelect,
502
+ onChange: (val) => updateSetting(DELIVERY_SETTING_KEY_GSM_SENDER_ID, val),
503
+ },
504
+ ...((smsFallbackSenderDetailsOptions || []).length > 0 ? [
505
+ {
506
+ titleMessage: messages.fallbackSmsDomainLabel,
507
+ options: smsFallbackDomainOptions,
508
+ value: get(localSettings, DELIVERY_SETTING_KEY_SMS_FALLBACK_DOMAIN_ID),
509
+ onChange: onSmsFallbackDomainChange,
510
+ },
511
+ {
512
+ titleMessage: messages.fallbackSmsSenderIdLabel,
513
+ options: smsSenderOptions,
514
+ value: smsFallbackGsmIdForSelect,
515
+ onChange: (val) => updateSetting(DELIVERY_SETTING_KEY_CDMA_SENDER_ID, val),
516
+ },
517
+ ] : []),
518
+ ];
343
519
  const byChannel = {
344
520
  [CHANNELS.SMS]: smsFields,
345
521
  [CHANNELS.EMAIL]: emailFields,
346
522
  [CHANNELS.WHATSAPP]: whatsappFields,
523
+ [CHANNELS.RCS]: rcsFields,
347
524
  };
348
525
  return byChannel[channel] || [];
349
526
  }, [
@@ -356,6 +533,13 @@ const ModifyDeliverySettings = (props) => {
356
533
  wecrmAccountOptions,
357
534
  whatsappAccountOptionsForDisplay,
358
535
  whatsappSenderOptions,
536
+ rcsSenderOptions,
537
+ rcsGsmSenderIdForSelect,
538
+ smsSenderOptions,
539
+ smsFallbackGsmIdForSelect,
540
+ smsFallbackDomainOptions,
541
+ smsFallbackSenderDetailsOptions,
542
+ onSmsFallbackDomainChange,
359
543
  localSettings,
360
544
  selectedDomainEmailSenders,
361
545
  senderDetailsOptions,
@@ -390,9 +574,10 @@ const ModifyDeliverySettings = (props) => {
390
574
  };
391
575
 
392
576
  ModifyDeliverySettings.propTypes = {
393
- channel: PropTypes.oneOf([CHANNELS.SMS, CHANNELS.EMAIL, CHANNELS.WHATSAPP]).isRequired,
577
+ channel: PropTypes.oneOf([CHANNELS.SMS, CHANNELS.EMAIL, CHANNELS.WHATSAPP, CHANNELS.RCS]).isRequired,
394
578
  deliverySettings: PropTypes.object,
395
579
  senderDetailsOptions: PropTypes.array,
580
+ smsFallbackSenderDetailsOptions: PropTypes.array,
396
581
  wecrmAccounts: PropTypes.array,
397
582
  onSaveDeliverySettings: PropTypes.func.isRequired,
398
583
  onClose: PropTypes.func,
@@ -408,6 +593,7 @@ ModifyDeliverySettings.propTypes = {
408
593
  ModifyDeliverySettings.defaultProps = {
409
594
  deliverySettings: {},
410
595
  senderDetailsOptions: [],
596
+ smsFallbackSenderDetailsOptions: [],
411
597
  wecrmAccounts: [],
412
598
  onClose: undefined,
413
599
  isLoading: false,
@@ -21,6 +21,8 @@ export const DELIVERY_SETTING_KEY_SENDER_LABEL = 'senderLabel';
21
21
  export const DELIVERY_SETTING_KEY_SENDER_REPLY_TO = 'senderReplyTo';
22
22
  export const DELIVERY_SETTING_KEY_SOURCE_ACCOUNT_IDENTIFIER = 'sourceAccountIdentifier';
23
23
  export const DELIVERY_SETTING_KEY_SENDER_MOB_NUM = 'senderMobNum';
24
+ /** RCS: SMS fallback domain (separate from primary RCS domainId) */
25
+ export const DELIVERY_SETTING_KEY_SMS_FALLBACK_DOMAIN_ID = 'smsFallbackDomainId';
24
26
 
25
27
  /** data-testid for delivery settings edit icon */
26
28
  export const TEST_ID_DELIVERY_SETTINGS_EDIT = 'delivery-settings-edit';
@@ -32,6 +34,7 @@ export const CHANNELS_WITH_DELIVERY_SETTINGS = [
32
34
  CHANNELS.SMS,
33
35
  CHANNELS.EMAIL,
34
36
  CHANNELS.WHATSAPP,
37
+ CHANNELS.RCS,
35
38
  ];
36
39
 
37
40
  /** Default empty delivery setting per channel (campaigns-style shape) */
@@ -56,8 +59,21 @@ export const DEFAULT_DELIVERY_SETTING_WHATSAPP = {
56
59
  sourceAccountIdentifier: '',
57
60
  };
58
61
 
62
+ /** RCS: gsmSenderId = RCS sender, cdmaSenderId = SMS fallback sender (reuse same keys) */
63
+ export const DEFAULT_DELIVERY_SETTING_RCS = {
64
+ domainId: null,
65
+ domainGatewayMapId: null,
66
+ gsmSenderId: '',
67
+ smsFallbackDomainId: null,
68
+ cdmaSenderId: '',
69
+ };
70
+
59
71
  export const DEFAULT_DELIVERY_SETTINGS_BY_CHANNEL = {
60
72
  [CHANNELS.SMS]: DEFAULT_DELIVERY_SETTING_SMS,
61
73
  [CHANNELS.EMAIL]: DEFAULT_DELIVERY_SETTING_EMAIL,
62
74
  [CHANNELS.WHATSAPP]: DEFAULT_DELIVERY_SETTING_WHATSAPP,
75
+ [CHANNELS.RCS]: DEFAULT_DELIVERY_SETTING_RCS,
63
76
  };
77
+
78
+ /** API `contactInfo.type` keys that map to RCS-style GSM sender rows (env-specific naming). */
79
+ export const RCS_CONTACT_INFO_GSM_TYPE_KEYS = ['gsm_sender_id', 'rcs_sender_id', 'rcs_sender'];