@openlettermarketing/olc-react-sdk 0.0.8 → 0.0.10

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 (135) hide show
  1. package/.eslintignore +1 -0
  2. package/.eslintrc.cjs +18 -0
  3. package/.eslintrc.yml +47 -0
  4. package/.prettierignore +3 -0
  5. package/.prettierrc.yml +5 -0
  6. package/CHANGELOG.md +4 -0
  7. package/babel.config.json +10 -0
  8. package/build/index.js +2 -2
  9. package/build/index.js.map +1 -1
  10. package/examples/.eslintrc.yml +4 -0
  11. package/index.html +18 -0
  12. package/package.json +6 -6
  13. package/public/vite.svg +1 -0
  14. package/src/App.tsx +76 -0
  15. package/src/assets/Fonts/Lexi-Regular.ttf +0 -0
  16. package/src/assets/images/input/cancel.tsx +20 -0
  17. package/src/assets/images/input/search.tsx +20 -0
  18. package/src/assets/images/modal-icons/cancelIcon.png +0 -0
  19. package/src/assets/images/modal-icons/del.tsx +19 -0
  20. package/src/assets/images/modal-icons/delete.svg +3 -0
  21. package/src/assets/images/modal-icons/modal-cross.tsx +23 -0
  22. package/src/assets/images/modal-icons/save.tsx +23 -0
  23. package/src/assets/images/templates/add-icon.svg +5 -0
  24. package/src/assets/images/templates/back-arrow.tsx +19 -0
  25. package/src/assets/images/templates/back-dialog-icon.png +0 -0
  26. package/src/assets/images/templates/back-dialog-icon.svg +3 -0
  27. package/src/assets/images/templates/barcode.png +0 -0
  28. package/src/assets/images/templates/bi-fold-self-mailers.tsx +28 -0
  29. package/src/assets/images/templates/black-trash-icon.svg +3 -0
  30. package/src/assets/images/templates/cancel.svg +4 -0
  31. package/src/assets/images/templates/cancelIcon.png +0 -0
  32. package/src/assets/images/templates/clipboard.svg +3 -0
  33. package/src/assets/images/templates/contact-search.svg +3 -0
  34. package/src/assets/images/templates/content-copy-icon.tsx +24 -0
  35. package/src/assets/images/templates/cross.svg +3 -0
  36. package/src/assets/images/templates/custom-template-icon-black.svg +3 -0
  37. package/src/assets/images/templates/custom-template-icon.svg +3 -0
  38. package/src/assets/images/templates/custom-template.tsx +23 -0
  39. package/src/assets/images/templates/dummy-template.svg +21 -0
  40. package/src/assets/images/templates/dynamic-field.tsx +119 -0
  41. package/src/assets/images/templates/edit-pencil-icon.tsx +21 -0
  42. package/src/assets/images/templates/filter-2.svg +13 -0
  43. package/src/assets/images/templates/info-icon.svg +12 -0
  44. package/src/assets/images/templates/info-icon.tsx +37 -0
  45. package/src/assets/images/templates/one-barcode.png +0 -0
  46. package/src/assets/images/templates/personal-letter.tsx +53 -0
  47. package/src/assets/images/templates/plus-icon.svg +5 -0
  48. package/src/assets/images/templates/postcard.tsx +32 -0
  49. package/src/assets/images/templates/professional-letter.tsx +53 -0
  50. package/src/assets/images/templates/real-penned-letters.tsx +57 -0
  51. package/src/assets/images/templates/search.svg +3 -0
  52. package/src/assets/images/templates/size-image-lg.tsx +20 -0
  53. package/src/assets/images/templates/size-image-mid.tsx +20 -0
  54. package/src/assets/images/templates/size-image.tsx +20 -0
  55. package/src/assets/images/templates/template-copy.svg +3 -0
  56. package/src/assets/images/templates/template-default-design.tsx +21 -0
  57. package/src/assets/images/templates/template-delete.svg +3 -0
  58. package/src/assets/images/templates/template-edit.svg +4 -0
  59. package/src/assets/images/templates/template-save-icon.svg +3 -0
  60. package/src/assets/images/templates/template-search-2.svg +9 -0
  61. package/src/assets/images/templates/template-search.svg +4 -0
  62. package/src/assets/images/templates/thumbnail.svg +10 -0
  63. package/src/assets/images/templates/trash-icon.svg +13 -0
  64. package/src/assets/images/templates/tri-fold-self-mailers.tsx +93 -0
  65. package/src/components/CreateTemplate/index.tsx +377 -0
  66. package/src/components/CreateTemplate/styles.scss +363 -0
  67. package/src/components/GenericUIBlocks/Button/index.tsx +21 -0
  68. package/src/components/GenericUIBlocks/Button/styles.scss +15 -0
  69. package/src/components/GenericUIBlocks/CircularProgress/index.tsx +18 -0
  70. package/src/components/GenericUIBlocks/CircularProgress/styles.scss +98 -0
  71. package/src/components/GenericUIBlocks/Dialog/index.tsx +127 -0
  72. package/src/components/GenericUIBlocks/Dialog/styles.scss +106 -0
  73. package/src/components/GenericUIBlocks/Divider/index.tsx +12 -0
  74. package/src/components/GenericUIBlocks/Divider/styles.scss +7 -0
  75. package/src/components/GenericUIBlocks/GeneralSelect/index.tsx +86 -0
  76. package/src/components/GenericUIBlocks/GeneralSelect/styles.scss +77 -0
  77. package/src/components/GenericUIBlocks/GeneralTooltip/index.tsx +24 -0
  78. package/src/components/GenericUIBlocks/GeneralTooltip/styles.scss +9 -0
  79. package/src/components/GenericUIBlocks/GenericSnackbar/index.tsx +53 -0
  80. package/src/components/GenericUIBlocks/GenericSnackbar/styles.scss +34 -0
  81. package/src/components/GenericUIBlocks/Grid/index.tsx +82 -0
  82. package/src/components/GenericUIBlocks/Input/index.tsx +89 -0
  83. package/src/components/GenericUIBlocks/Input/styles.scss +80 -0
  84. package/src/components/GenericUIBlocks/Snackbar/index.tsx +66 -0
  85. package/src/components/GenericUIBlocks/Typography/index.tsx +18 -0
  86. package/src/components/GenericUIBlocks/Typography/styles.scss +27 -0
  87. package/src/components/SidePanel/customFields/customFieldSection.tsx +162 -0
  88. package/src/components/SidePanel/customFields/styles.scss +47 -0
  89. package/src/components/SidePanel/index.tsx +30 -0
  90. package/src/components/SidePanel/templates/customTemplateSection.tsx +505 -0
  91. package/src/components/SidePanel/templates/styles.scss +151 -0
  92. package/src/components/TemplateBuilder/index.tsx +295 -0
  93. package/src/components/TemplateBuilder/styles.scss +66 -0
  94. package/src/components/TopNavigation/ConfirmNavigateDialog/index.tsx +58 -0
  95. package/src/components/TopNavigation/ConfirmNavigateDialog/styles.scss +123 -0
  96. package/src/components/TopNavigation/EditTemplateNameModel/index.tsx +98 -0
  97. package/src/components/TopNavigation/EditTemplateNameModel/styles.scss +88 -0
  98. package/src/components/TopNavigation/SaveTemplateModel/index.tsx +60 -0
  99. package/src/components/TopNavigation/SaveTemplateModel/styles.scss +128 -0
  100. package/src/components/TopNavigation/index.tsx +388 -0
  101. package/src/components/TopNavigation/styles.scss +83 -0
  102. package/src/importMeta.d.ts +9 -0
  103. package/src/index.scss +130 -0
  104. package/src/index.tsx +82 -0
  105. package/src/libs/test.ts +7 -0
  106. package/src/redux/actions/action-types.ts +42 -0
  107. package/src/redux/actions/customFieldAction.ts +28 -0
  108. package/src/redux/actions/snackbarActions.ts +16 -0
  109. package/src/redux/actions/templateActions.ts +456 -0
  110. package/src/redux/reducers/customFieldReducer.ts +97 -0
  111. package/src/redux/reducers/index.ts +14 -0
  112. package/src/redux/reducers/snackbarReducer.ts +41 -0
  113. package/src/redux/reducers/templateReducer.ts +353 -0
  114. package/src/redux/store.ts +18 -0
  115. package/src/styles/colors.scss +61 -0
  116. package/src/test/mocks.js +89 -0
  117. package/src/test/setupJest.js +1 -0
  118. package/src/utils/api.ts +36 -0
  119. package/src/utils/constants.ts +40 -0
  120. package/src/utils/customStyles.ts +135 -0
  121. package/src/utils/fetchWrapper.ts +68 -0
  122. package/src/utils/fonts.json +1597 -0
  123. package/src/utils/helper.ts +19 -0
  124. package/src/utils/local-storage.ts +15 -0
  125. package/src/utils/message.ts +71 -0
  126. package/src/utils/template-builder.ts +147 -0
  127. package/src/utils/templateRestrictedArea/biFold.ts +433 -0
  128. package/src/utils/templateRestrictedArea/postCard.ts +439 -0
  129. package/src/utils/templateRestrictedArea/professional.ts +422 -0
  130. package/src/utils/templateRestrictedArea/realPenned.ts +283 -0
  131. package/src/utils/templateRestrictedArea/triFold.ts +434 -0
  132. package/tsconfig.json +29 -0
  133. package/tsconfig.node.json +12 -0
  134. package/vite.config.ts +8 -0
  135. package/webpack.config.js +80 -0
@@ -0,0 +1,88 @@
1
+ .editTemplateNameModal {
2
+ .MuiPaper-root {
3
+ width: 100% !important;
4
+ max-width: 623px !important;
5
+ height: 100% !important;
6
+ max-height: 230px !important;
7
+ margin: 0 auto !important;
8
+ border-radius: 11px;
9
+ background: #fff8ee;
10
+ }
11
+
12
+ .editTemplateNameModalTitle {
13
+ color: #ed5c2f;
14
+ text-align: center;
15
+ font-size: 22px;
16
+ font-style: normal;
17
+ font-weight: 700;
18
+ line-height: normal;
19
+ padding: 16px 16px 0px !important;
20
+ }
21
+
22
+ .editTemplateNameModalContent {
23
+ padding: 0px 30px !important;
24
+
25
+ p {
26
+ color: #303030;
27
+ font-size: 14px;
28
+ font-style: normal;
29
+ font-weight: 400;
30
+ line-height: normal;
31
+ margin: 10px 0px 10px 0px;
32
+ }
33
+
34
+ .MuiInputBase-root {
35
+ border-radius: 7px;
36
+ border: 0.5px solid #303030;
37
+ background: #fff;
38
+ width: 100%;
39
+ padding: 9.8px 22px;
40
+
41
+ &:focus,
42
+ &:focus-visible {
43
+ outline: none !important;
44
+ }
45
+
46
+ &::after,
47
+ &::before {
48
+ display: none !important;
49
+ }
50
+ }
51
+ }
52
+
53
+ .actionBtns {
54
+ justify-content: center;
55
+ align-items: center;
56
+ margin: 20px 0px;
57
+ gap: 20px;
58
+
59
+ button {
60
+ border-radius: 5px;
61
+ text-transform: capitalize;
62
+ width: 100%;
63
+ max-width: 107px;
64
+ height: 100%;
65
+ min-height: 41px;
66
+
67
+ &:first-child {
68
+ border: 0.5px solid rgba(48, 48, 48, 0.5);
69
+ background: #fff;
70
+ color: #000;
71
+ font-size: 16px;
72
+ font-style: normal;
73
+ font-weight: 600;
74
+ line-height: normal;
75
+ }
76
+
77
+ &:last-child {
78
+ color: #fff;
79
+ font-size: 16px;
80
+ font-style: normal;
81
+ font-weight: 600;
82
+ line-height: normal;
83
+ background: #ed5c2f;
84
+ margin: 0;
85
+ }
86
+ }
87
+ }
88
+ }
@@ -0,0 +1,60 @@
1
+ import React from 'react';
2
+
3
+ // Utils
4
+ import { MESSAGES } from '../../../utils/message';
5
+
6
+ // Components
7
+ import Dialog from '../../GenericUIBlocks/Dialog';
8
+
9
+ // Icons
10
+ import Save from '../../../assets/images/modal-icons/save';
11
+
12
+ // Styles
13
+ import './styles.scss';
14
+
15
+ /**
16
+ * Renders a modal dialog for deleting a template.
17
+ *
18
+ * @param {function} handleSave - Callback function to handle the save action.
19
+ * @param {function} handleClose - Callback function to handle the close action.
20
+ * @param {boolean} open - Boolean value indicating whether the modal is open or not.
21
+ * @returns {JSX.Element} The delete template modal component.
22
+ */
23
+
24
+ const saveDialogStyles = {
25
+ maxWidth: '433px',
26
+ minHeight: '290px',
27
+ };
28
+
29
+ interface SaveTemplateModelProps {
30
+ open: boolean;
31
+ loading: boolean;
32
+ handleClose: () => void;
33
+ handleSave: () => void;
34
+ }
35
+
36
+ const SaveTemplateModel: React.FC<SaveTemplateModelProps> = ({
37
+ handleSave,
38
+ handleClose,
39
+ open,
40
+ loading,
41
+ }) => {
42
+ return (
43
+ <Dialog
44
+ icon={<Save fill="var(--primaryColor)" />}
45
+ open={open}
46
+ loading={loading}
47
+ handleClose={handleClose}
48
+ title={MESSAGES.TEMPLATE.SAVE.TITLE}
49
+ subHeading={MESSAGES.TEMPLATE.SAVE.HEADING}
50
+ description={MESSAGES.TEMPLATE.SAVE.PARAGRAPH}
51
+ cancelText={MESSAGES.TEMPLATE.SAVE.CANCEL_BUTTON}
52
+ submitText={MESSAGES.TEMPLATE.SAVE.SUBMIT_BUTTON}
53
+ customStyles={saveDialogStyles}
54
+ onSubmit={handleSave}
55
+ onCancel={handleClose}
56
+ />
57
+ );
58
+ };
59
+
60
+ export default SaveTemplateModel;
@@ -0,0 +1,128 @@
1
+ .confirmTemplateSaveModal {
2
+ .MuiPaper-root {
3
+ width: 100% !important;
4
+ max-width: 433px !important;
5
+ height: 100% !important;
6
+ max-height: 290px !important;
7
+ margin: 0 auto !important;
8
+ border-radius: 11px;
9
+ background: #fff8ee;
10
+ }
11
+
12
+ .confirmTemplateSaveModalTitle {
13
+ color: #ed5c2f;
14
+ text-align: center;
15
+ font-size: 22px;
16
+ font-style: normal;
17
+ font-weight: 700;
18
+ line-height: normal;
19
+ }
20
+
21
+ .confirmTemplateSaveModalContent {
22
+ display: flex;
23
+ flex-direction: column;
24
+ gap: 20px;
25
+ padding: 16px 16px 0px;
26
+
27
+ .trashIconWrapper {
28
+ text-align: center;
29
+
30
+ p {
31
+ color: #ed5c2f;
32
+ text-align: center;
33
+ font-size: 22px;
34
+ font-style: normal;
35
+ font-weight: 700;
36
+ line-height: normal;
37
+ margin-top: 10px;
38
+ }
39
+ }
40
+
41
+ .confirmTemplateSaveText {
42
+ display: flex;
43
+ flex-direction: column;
44
+ justify-content: center;
45
+ align-items: center;
46
+ gap: 10px;
47
+
48
+ p {
49
+ color: #000;
50
+ text-align: center;
51
+ font-size: 16px;
52
+ font-style: normal;
53
+ font-weight: 600;
54
+ line-height: normal;
55
+
56
+ &:last-child {
57
+ color: #000;
58
+ text-align: center;
59
+ font-size: 14px;
60
+ font-style: normal;
61
+ font-weight: 400;
62
+ line-height: 16px;
63
+ /* 114.286% */
64
+ letter-spacing: 0.28px;
65
+ margin: 0;
66
+ }
67
+ }
68
+ }
69
+
70
+ .MuiInputBase-root {
71
+ border-radius: 7px;
72
+ border: 0.5px solid #303030;
73
+ background: #fff;
74
+ width: 100%;
75
+ padding: 10px 22px;
76
+
77
+ &:focus,
78
+ &:focus-visible {
79
+ outline: none !important;
80
+ }
81
+
82
+ &::after,
83
+ &::before {
84
+ display: none !important;
85
+ }
86
+ }
87
+ }
88
+
89
+ .actionBtns {
90
+ justify-content: center;
91
+ align-items: center;
92
+ margin-bottom: 10px;
93
+ gap: 20px;
94
+
95
+ button {
96
+ border-radius: 5px;
97
+ text-transform: capitalize;
98
+ width: 100%;
99
+ max-width: 107px;
100
+ height: 100%;
101
+ min-height: 41px;
102
+
103
+ &:first-child {
104
+ border: 0.5px solid rgba(48, 48, 48, 0.5);
105
+ background: #fff;
106
+ color: #000;
107
+ font-size: 16px;
108
+ font-style: normal;
109
+ font-weight: 600;
110
+ line-height: normal;
111
+ }
112
+
113
+ &:last-child {
114
+ color: #fff;
115
+ font-size: 16px;
116
+ font-style: normal;
117
+ font-weight: 600;
118
+ line-height: normal;
119
+ background: #ed5c2f;
120
+ margin: 0;
121
+ }
122
+
123
+ &:disabled {
124
+ opacity: 0.5;
125
+ }
126
+ }
127
+ }
128
+ }
@@ -0,0 +1,388 @@
1
+ import React, { useEffect, useState } from 'react';
2
+
3
+ // Hooks
4
+ import { useDispatch, useSelector } from 'react-redux';
5
+ import { useNavigate, useParams } from 'react-router-dom';
6
+ import { AppDispatch, RootState } from '../../redux/store';
7
+
8
+ // Actions
9
+ import {
10
+ uploadTemplate,
11
+ createTemplate,
12
+ updateTemplate,
13
+ clearTemplateFields,
14
+ loadFormDataToStore,
15
+ downloadProof,
16
+ } from '../../redux/actions/templateActions';
17
+ import { failure, success } from '../../redux/actions/snackbarActions';
18
+
19
+ // Components
20
+ import SaveTemplateModel from './SaveTemplateModel';
21
+ import ConfirmNavigateDialog from './ConfirmNavigateDialog';
22
+ import EditTemplateNameModel from './EditTemplateNameModel';
23
+
24
+
25
+ // Utils
26
+ import { downloadPDF, extractFontFamilies, multiPageTemplates } from '../../utils/template-builder';
27
+ import { getItem, setItem } from '../../utils/local-storage';
28
+ import { MESSAGES } from '../../utils/message';
29
+ // @ts-ignore
30
+ import fonts from '../../utils/fonts.json';
31
+
32
+ // UI Components
33
+ import Typography from "../GenericUIBlocks/Typography";
34
+ import Button from "../GenericUIBlocks/Button";
35
+ import CircularProgress from "../GenericUIBlocks/CircularProgress";
36
+ import { GridContainer, GridItem } from '../GenericUIBlocks/Grid';
37
+
38
+
39
+ // Icons
40
+ // @ts-ignore
41
+ import EditIcon from '../../assets/images/templates/edit-pencil-icon.tsx';
42
+
43
+ // Styles
44
+ import './styles.scss';
45
+
46
+
47
+ /**
48
+ * Represents the top navigation bar of a template builder application.
49
+ * Handles saving and navigation logic, as well as displaying a confirmation dialog for unsaved changes.
50
+ *
51
+ * @param {Object} props - The component props.
52
+ * @param {Object} props.store - The store object used for saving the template.
53
+ * @param {boolean} props.isStoreUpdated - Indicates whether the store has been updated.
54
+ * @returns {JSX.Element} The top navigation bar component.
55
+ */
56
+
57
+ const buttonStyles: React.CSSProperties = {
58
+ maxWidth: '120px',
59
+ minHeight: '40px',
60
+ backgroundColor: 'var(--secondaryButtonBgColor)',
61
+ color: 'var(--secondaryButtonTextColor)',
62
+ border: '0.5px solid var(--borderColor)',
63
+ fontSize: '15px',
64
+ };
65
+
66
+ const progressStyles: React.CSSProperties = {
67
+ width: '20px',
68
+ height: '20px',
69
+ border: '2px solid var(--primaryColor)',
70
+ };
71
+
72
+ interface TopNavigationProps {
73
+ store: any;
74
+ returnRoute?: string | null;
75
+ isStoreUpdated: boolean;
76
+ }
77
+
78
+ const TopNavigation: React.FC<TopNavigationProps> = ({
79
+ store,
80
+ returnRoute,
81
+ isStoreUpdated,
82
+ }) => {
83
+
84
+ const [showNavigateDialog, setShowNavigateDialog] = useState<boolean>(false);
85
+ const [isShowModel, setIsShowModel] = useState<{
86
+ open: boolean;
87
+ model: string;
88
+ loading: boolean;
89
+ }>({
90
+ open: false,
91
+ model: '',
92
+ loading: false,
93
+ });
94
+ const [downloadingProof, setDownloaingProof] = useState<boolean>(false);
95
+
96
+ const { id } = useParams<{ id: string }>();
97
+
98
+ const dispatch: AppDispatch = useDispatch();
99
+ const navigate = useNavigate();
100
+
101
+ const title = useSelector((state: RootState) => state.templates.title);
102
+ const product = useSelector((state: RootState) => state.templates.product) as Record<string, any>;
103
+
104
+ const dynamicFields = useSelector(
105
+ (state: RootState) => state.templates.dynamicFields
106
+ );
107
+ const defaultFields = useSelector(
108
+ (state: RootState) => state.templates.defaultDynamicFields
109
+ );
110
+ const templateType = useSelector(
111
+ (state: RootState) => state.templates.templateType
112
+ );
113
+ const envelopeType = useSelector(
114
+ (state: RootState) => state.templates.envelopeType
115
+ );
116
+
117
+ useEffect(() => {
118
+ if (!id) {
119
+ const formData = getItem('formData');
120
+ if (formData && !title) {
121
+ dispatch(loadFormDataToStore(formData));
122
+ } else {
123
+ handleSaveFormData();
124
+ }
125
+ }
126
+ }, [title]);
127
+
128
+ const handleSaveFormData = () => {
129
+ const data = { title, product, templateType, envelopeType };
130
+ setItem('formData', JSON.stringify(data));
131
+ };
132
+
133
+ const handleBackPress = () => {
134
+ if (isStoreUpdated) {
135
+ setShowNavigateDialog(!showNavigateDialog);
136
+ } else {
137
+ handleNavigation(returnRoute ? returnRoute : '/create-template');
138
+ }
139
+ };
140
+
141
+ const handleNavigation = async (route = '/') => {
142
+ handleClearFilters();
143
+ if (templateType === 'json') {
144
+ await store.history.clear();
145
+ }
146
+ navigate(route);
147
+ };
148
+
149
+ const handleClearFilters = () => dispatch(clearTemplateFields());
150
+
151
+ const handleViewProofWithLamda = async () => {
152
+ try {
153
+ setDownloaingProof(true);
154
+ const fields = [...defaultFields, ...Object.values(dynamicFields)];
155
+ const json = store.toJSON();
156
+ let jsonString = JSON.stringify(json);
157
+ fields.forEach(({ key, defaultValue, value }) => {
158
+ const regex = new RegExp(key, 'g');
159
+ jsonString = jsonString.replace(regex, defaultValue || value);
160
+ });
161
+ const jsonWithDummyData = JSON.parse(jsonString);
162
+ const response: any = await downloadProof({
163
+ json: jsonWithDummyData,
164
+ });
165
+ if (response.status === 200) {
166
+ const binaryData = atob(response.data.data.base64);
167
+ // Create a Uint8Array from the binary data
168
+ const uint8Array = new Uint8Array(binaryData.length);
169
+ for (let i = 0; i < binaryData.length; i++) {
170
+ uint8Array[i] = binaryData.charCodeAt(i);
171
+ }
172
+
173
+ // Create a Blob from the Uint8Array
174
+ const blob = new Blob([uint8Array], { type: 'application/pdf' });
175
+
176
+ // Create an Object URL for the Blob
177
+ const url = URL.createObjectURL(blob);
178
+ downloadPDF(title.substring(0, 20), url);
179
+ dispatch(success('Download Proof generated successfully'));
180
+ } else {
181
+ dispatch(failure(response?.data?.message));
182
+ }
183
+ } catch (error: any) {
184
+ dispatch(
185
+ failure(
186
+ error?.response?.data?.message ||
187
+ error?.message ||
188
+ 'Error while downloading proof'
189
+ )
190
+ );
191
+ } finally {
192
+ setDownloaingProof(false);
193
+ }
194
+ };
195
+
196
+ const handleSave = async () => {
197
+ try {
198
+ const formData = new FormData();
199
+ const allFields = [...defaultFields, ...Object.values(dynamicFields)];
200
+ let selectedFields: typeof allFields = [];
201
+ if (templateType === 'json') {
202
+ const blob = await store.toBlob();
203
+ const jsonData = store.toJSON();
204
+
205
+ // get all fonts family from json
206
+ const fontFamilies = extractFontFamilies(jsonData?.pages);
207
+
208
+ // extract custom fonts and remove google fonts from that array
209
+ const customFonts = fontFamilies.filter((item: any) => !fonts.includes(item));
210
+
211
+ const availableBase64inJson = jsonData?.fonts?.map((font: any) => font?.fontFamily);
212
+
213
+ const unAvailableFonts = customFonts.filter((item: any) => !availableBase64inJson?.includes(item));
214
+
215
+ if (unAvailableFonts?.length) {
216
+ dispatch(failure(`Please upload ${unAvailableFonts[0]} font in My Fonts section.`));
217
+ return
218
+ }
219
+
220
+ if (multiPageTemplates.includes(product.productType)) {
221
+ const backJsonData = { ...jsonData, pages: [jsonData.pages[1]] }
222
+ await store.loadJSON(backJsonData);
223
+ await store.waitLoading();
224
+ const backBlob = await store.toBlob();
225
+ formData.append('backThumbnail', backBlob, 'backLogo.png');
226
+ store.loadJSON(jsonData);
227
+ }
228
+ const jsonString = JSON.stringify(jsonData);
229
+ const blobData = new Blob([jsonString], { type: 'application/json' });
230
+ formData.append('json', blobData, 'template.json');
231
+ formData.append('thumbnail', blob, 'logo.png');
232
+ selectedFields = allFields.filter(field => jsonString.includes(field.key));
233
+ }
234
+ setIsShowModel((prev) => ({ ...prev, loading: true }));
235
+
236
+ const response: any = await uploadTemplate(formData);
237
+ if (response?.status === 200) {
238
+ if (!id) {
239
+ setTimeout(async () => await handleCreateTemplate(response?.data?.data, selectedFields), 1000);
240
+ } else {
241
+ setTimeout(async () => await handleUpdateTemplate(response?.data?.data, selectedFields), 1000)
242
+ }
243
+ } else if (response?.status === 418 && response?.data?.message == "You have reached your Templates limit, updgrade you Plan to add more") {
244
+ handleChangeModel('', 'false');
245
+ } else {
246
+ dispatch(
247
+ failure(
248
+ response?.data?.message ||
249
+ MESSAGES.GENERAL_ERROR
250
+ )
251
+ );
252
+ handleChangeModel('', 'false');
253
+ }
254
+ } catch (error) {
255
+ return error;
256
+ }
257
+ };
258
+
259
+ const handleCreateTemplate = async (data: any, selectedFields: any) => {
260
+ try {
261
+ const response: any = await createTemplate({
262
+ title: title,
263
+ productId: product?.id,
264
+ fields: selectedFields,
265
+ thumbnailPath: data.thumbnailPath,
266
+ templatePath: data.templatePath,
267
+ backTemplatePath: data.backTemplatePath || '',
268
+ backThumbnailPath: data.backThumbnailPath || '',
269
+ envelopeType,
270
+ });
271
+ if (response.status === 200) {
272
+ dispatch(success(response.data.message));
273
+ handleNavigation();
274
+ } else if (response.status == 418) {
275
+ // nothing to do
276
+ } else {
277
+ dispatch(failure(response?.data?.message || response?.message));
278
+ }
279
+ } catch (error) {
280
+ handleChangeModel('', 'false');
281
+ } finally {
282
+ setIsShowModel((prev) => ({ ...prev, loading: false }));
283
+ }
284
+ };
285
+
286
+ const handleUpdateTemplate = async (data: any, selectedFields: any) => {
287
+ // @ts-ignore
288
+ const response: any = await updateTemplate(id, {
289
+ title: title,
290
+ fields: selectedFields,
291
+ thumbnailPath: data.thumbnailPath,
292
+ templatePath: data.templatePath,
293
+ backTemplatePath: data.backTemplatePath || '',
294
+ backThumbnailPath: data.backThumbnailPath || '',
295
+ });
296
+ if (response.status === 200) {
297
+ dispatch(success(response.data.message));
298
+ handleNavigation();
299
+ } else {
300
+ dispatch(failure(response.data.message));
301
+ }
302
+ handleChangeModel('', 'false');
303
+ };
304
+
305
+
306
+ const handleChangeModel = (model: string = '', loading: string | null = null) => {
307
+ setIsShowModel((prev) => ({
308
+ ...prev,
309
+ open: !prev.open,
310
+ loading: loading === 'false' ? false : prev.loading,
311
+ model,
312
+ }));
313
+ };
314
+
315
+ return (
316
+ <div className="top-navigation-container">
317
+ {showNavigateDialog && (
318
+ <ConfirmNavigateDialog
319
+ open={showNavigateDialog}
320
+ handleClose={() => setShowNavigateDialog(false)}
321
+ handleNavigateAction={() => handleNavigation(returnRoute ? returnRoute : '/create-template')}
322
+ />
323
+ )}
324
+ {isShowModel?.open && isShowModel?.model === 'edit' && (
325
+ <EditTemplateNameModel
326
+ open={isShowModel?.open}
327
+ handleClose={() => handleChangeModel()}
328
+ />
329
+ )}
330
+ {isShowModel.open && isShowModel.model === 'save' && (
331
+ <SaveTemplateModel
332
+ loading={isShowModel.loading}
333
+ open={isShowModel.open}
334
+ handleClose={() => handleChangeModel()}
335
+ handleSave={handleSave}
336
+ />
337
+ )}
338
+ <GridContainer style={{alignItems: 'center'}}>
339
+ <GridItem lg={4} md={4} sm={2} xs={12}></GridItem>
340
+ <GridItem lg={4} md={2} sm={2} xs={12}>
341
+ <div className="middle">
342
+ <Typography>{title}</Typography>
343
+ <div onClick={() => handleChangeModel('edit')}>
344
+ <EditIcon fill="var(--textColor)" />
345
+ </div>
346
+ </div>
347
+ </GridItem>
348
+ <GridItem lg={4} md={6} sm={8} xs={12}>
349
+ <div className="actionsBtnWrapper right">
350
+ <Button
351
+ style={{...buttonStyles, maxWidth: 'auto', minWidth: '100px'}}
352
+ onClick={handleViewProofWithLamda}
353
+ >
354
+ {downloadingProof ? (
355
+ <CircularProgress style={progressStyles} />
356
+ ) : (
357
+ MESSAGES.TEMPLATE.DOWNLOAD_PROOF_BUTTON
358
+ )}
359
+ </Button>
360
+ <Button
361
+ style={{
362
+ ...buttonStyles,
363
+ border: '0.5px solid var(--primaryColor)',
364
+ color: 'var(--primaryColor)',
365
+ }}
366
+ onClick={() => handleBackPress()}
367
+ >
368
+ {MESSAGES.TEMPLATE.CANCEL_BUTTON}
369
+ </Button>
370
+ <Button
371
+ style={{
372
+ ...buttonStyles,
373
+ border: 'none',
374
+ backgroundColor: 'var(--primaryColor)',
375
+ color: 'var(--primaryButtonTextColor)',
376
+ }}
377
+ onClick={() => handleChangeModel('save')}
378
+ >
379
+ {MESSAGES.TEMPLATE.SUBMIT_BUTTON}
380
+ </Button>
381
+ </div>
382
+ </GridItem>
383
+ </GridContainer>
384
+ </div>
385
+ );
386
+ };
387
+
388
+ export default TopNavigation;