@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,295 @@
1
+ import React, { useEffect, useState } from 'react';
2
+
3
+ // Import Polotno and third-party libraries
4
+ import { PolotnoContainer, WorkspaceWrap } from 'polotno';
5
+ import { setUploadFunc } from 'polotno/config';
6
+ import { Toolbar } from 'polotno/toolbar/toolbar';
7
+ import { ZoomButtons } from 'polotno/toolbar/zoom-buttons';
8
+ import { Workspace } from 'polotno/canvas/workspace';
9
+ import { setGoogleFonts } from 'polotno/config';
10
+ import merge from 'deepmerge';
11
+
12
+ // Hooks
13
+ import { useDispatch, useSelector } from 'react-redux';
14
+ import { useParams, useNavigate } from 'react-router-dom';
15
+ import { RootState } from '../../redux/reducers';
16
+ import { AppDispatch } from '../../redux/store';
17
+ import { StoreType } from 'polotno/model/store';
18
+
19
+ // Actions
20
+ import {
21
+ getAllCustomFields,
22
+ getOneTemplate,
23
+ uploadFile,
24
+ } from '../../redux/actions/templateActions';
25
+ import { TEMPLATE_LOADING } from '../../redux/actions/action-types';
26
+
27
+
28
+ // Utils
29
+ import { drawRestrictedAreaOnPage, getFileAsBlob } from '../../utils/template-builder';
30
+ import { addElementsforRealPennedLetters } from '../../utils/templateRestrictedArea/realPenned';
31
+ import { DPI, multiPageLetters } from '../../utils/constants';
32
+ // @ts-ignore
33
+ import fonts from "../../utils/fonts.json";
34
+ // @ts-ignore
35
+ import LexiRegularFont from "../../assets/Fonts/Lexi-Regular.ttf";
36
+
37
+ // Components
38
+ import TopNavigation from '../TopNavigation';
39
+ import SidePanel from '../SidePanel';
40
+
41
+ import './styles.scss';
42
+
43
+ setUploadFunc(uploadFile)
44
+ /**
45
+ * This code defines a React functional component called `TemplateBuilder` that is responsible for rendering a template builder interface.
46
+ * It includes various useEffect hooks to handle component lifecycle events and state updates.
47
+ * The component uses the `polotno` library to create a canvas workspace where users can design templates.
48
+ * It also includes a side panel with different sections for adding and customizing elements on the canvas.
49
+ *
50
+ * @param {Object} props - The component props.
51
+ * @param {Object} props.store - The store object passed as a prop to the `TemplateBuilder` component.
52
+ * @param {Object} props.styles - The styles contain CSS Properties passed as a prop to the `TemplateBuilder` component.
53
+ * @returns {JSX.Element} The rendered template builder interface.
54
+ */
55
+
56
+ // styles
57
+ import './styles.scss'
58
+
59
+ interface TemplateBuilderProps {
60
+ store: StoreType,
61
+ returnRoute?: string | null,
62
+ styles?: React.CSSProperties;
63
+ }
64
+
65
+ const TemplateBuilder: React.FC<TemplateBuilderProps> = ({ store, styles, returnRoute }) => {
66
+ const [isStoreUpdated, setIsStoreUpdated] = useState(false);
67
+ const [switchTabCount, setSwitchTabCount] = useState(1);
68
+
69
+ const { id } = useParams();
70
+ const dispatch: AppDispatch = useDispatch();
71
+ const navigate = useNavigate();
72
+
73
+
74
+ const template = useSelector((state: RootState) => state.templates.template) as Record<string, any>;
75
+ const product = useSelector((state: RootState) => state.templates.product) as Record<string, any>;
76
+ const envelopeType = useSelector(
77
+ (state: RootState) => state.templates.envelopeType
78
+ );
79
+
80
+ const currentTemplateType = product?.productType;
81
+
82
+ const containerStyle = merge(
83
+ {
84
+ width: '100vw',
85
+ height: '90vh',
86
+ position: 'relative',
87
+ backgroundColor: 'var(--mainBackgroundColor) !important',
88
+ },
89
+ styles || {}
90
+ );
91
+
92
+ useEffect(() => {
93
+ handleLoadTemplate();
94
+ }, [template]);
95
+
96
+ // Event listener for visibility change
97
+ useEffect(() => {
98
+ const handleVisibilityChange = () => {
99
+ if (document.hidden) {
100
+ setSwitchTabCount((prev) => prev + 1);
101
+ }
102
+ };
103
+
104
+ document.addEventListener("visibilitychange", handleVisibilityChange);
105
+
106
+ return () => {
107
+ document.removeEventListener("visibilitychange", handleVisibilityChange);
108
+ };
109
+ }, []);
110
+
111
+ useEffect(() => {
112
+ if (!product) {
113
+ navigate('/create-template');
114
+ }
115
+
116
+ setGoogleFonts(fonts);
117
+ // remove this component from the history stack
118
+
119
+ if (id) {
120
+ // @ts-ignore
121
+ dispatch(getOneTemplate(id));
122
+ } else if (store.pages.length === 0) {
123
+ createInitialPage();
124
+
125
+ }
126
+ dispatch(getAllCustomFields());
127
+ const handleChange = () => {
128
+ if (!isStoreUpdated) {
129
+ setIsStoreUpdated(true);
130
+ }
131
+ };
132
+
133
+ const off = store.on("change", handleChange);
134
+
135
+ return () => {
136
+ store.history.clear();
137
+ store.clear();
138
+ off();
139
+ };
140
+ }, []);
141
+
142
+ useEffect(() => {
143
+ if (!id && product && store.pages.length === 0) {
144
+ createInitialPage();
145
+ }
146
+ }, [product]);
147
+
148
+ useEffect(() => {
149
+ const handleBeforeUnload = (event: { returnValue: string; }) => {
150
+ const message = "Are you sure you want to leave?";
151
+ event.returnValue = message;
152
+ return message;
153
+ };
154
+
155
+ const addBeforeUnloadListener = () => {
156
+ window.removeEventListener("beforeunload", handleBeforeUnload);
157
+ window.addEventListener("beforeunload", handleBeforeUnload);
158
+ };
159
+
160
+ const removeBeforeUnloadListener = () => {
161
+ window.removeEventListener("beforeunload", handleBeforeUnload);
162
+ };
163
+
164
+ if (isStoreUpdated) {
165
+ addBeforeUnloadListener();
166
+ }
167
+
168
+ return () => {
169
+ removeBeforeUnloadListener();
170
+ };
171
+ }, [isStoreUpdated]);
172
+
173
+ const createInitialPage = async () => {
174
+ if (product) {
175
+
176
+ store.addPage();
177
+ const paperSize = product?.selectedSize?.split("x");
178
+ store.setUnit({
179
+ unit: "in",
180
+ dpi: DPI,
181
+ });
182
+ store.setSize(+paperSize[1] * DPI, +paperSize[0] * DPI);
183
+ if (multiPageLetters.includes(product.productType)) {
184
+ store.addPage();
185
+ store.selectPage(store.pages[0].id);
186
+ }
187
+ //@ts-ignore
188
+ drawRestrictedAreaOnPage(store, product, envelopeType);
189
+
190
+ if (currentTemplateType === "Real Penned Letter") {
191
+ handleRealPennedLetters();
192
+ }
193
+
194
+ store.history.clear();
195
+ }
196
+
197
+ setIsStoreUpdated(false);
198
+ };
199
+
200
+ const handleRealPennedLetters = async () => {
201
+ try {
202
+ // Load Lexi Regular Fonts Into Store
203
+ store.addFont({
204
+ fontFamily: "lexi Regular",
205
+ url: LexiRegularFont,
206
+ });
207
+ addElementsforRealPennedLetters(store);
208
+
209
+ const response = await fetch(LexiRegularFont);
210
+ const blob = await response.blob();
211
+
212
+ const reader = new FileReader();
213
+ // Load Lexi Regular Base64 into JSON
214
+ reader.onloadend = () => {
215
+ store.addFont({
216
+ fontFamily: "lexi Regular",
217
+ url: reader.result,
218
+ } as any);
219
+ };
220
+ reader.readAsDataURL(blob);
221
+ } catch (error) {
222
+ console.error("Error loading the font file:", error);
223
+ }
224
+ };
225
+
226
+ const handleLoadTemplate = async () => {
227
+ if (template) {
228
+ const workspaceElement = document.querySelector(
229
+ ".polotno-workspace-container"
230
+ );
231
+ if (workspaceElement) {
232
+ workspaceElement.classList.add("show-loader");
233
+ }
234
+ // @ts-ignore
235
+ const paperDimensions = template?.product?.paperSize.split('x');
236
+ store.setUnit({
237
+ unit: "in",
238
+ dpi: 96,
239
+ });
240
+ store.setSize(+paperDimensions[1] * DPI, +paperDimensions[0] * DPI);
241
+ const jsonData = await getFileAsBlob(template?.templateUrl);
242
+ store.loadJSON(jsonData);
243
+ await store.waitLoading();
244
+ setIsStoreUpdated(false);
245
+ dispatch({ type: TEMPLATE_LOADING, payload: false });
246
+ if (workspaceElement) {
247
+ workspaceElement.classList.add("hide-loader");
248
+ }
249
+ }
250
+ };
251
+
252
+ // Incase of Real Penned Letters hide tooltip
253
+ const Tooltip = () => null;
254
+
255
+ return (
256
+ <div className="polotno-container">
257
+ {switchTabCount > 0 && (
258
+ <div className='builder-wrapper'>
259
+ <TopNavigation
260
+ store={store}
261
+ isStoreUpdated={isStoreUpdated}
262
+ returnRoute={returnRoute}
263
+ />
264
+
265
+ <PolotnoContainer
266
+ style={containerStyle}
267
+ >
268
+ {currentTemplateType !== "Real Penned Letter" &&
269
+ <SidePanel store={store} />
270
+ }
271
+ <WorkspaceWrap>
272
+ {currentTemplateType !== "Real Penned Letter" && (
273
+ <Toolbar store={store} downloadButtonEnabled={false} />
274
+ )}
275
+ {currentTemplateType !== "Real Penned Letter" ? (
276
+ <Workspace store={store} pageControlsEnabled={false} />
277
+ ) : (
278
+ <Workspace
279
+ store={store}
280
+ pageControlsEnabled={false}
281
+ components={{ Tooltip }}
282
+ />
283
+ )}
284
+ <ZoomButtons store={store} />
285
+ </WorkspaceWrap>
286
+ </PolotnoContainer>
287
+ </div>
288
+ )}
289
+ </div>
290
+ );
291
+ };
292
+
293
+ export default TemplateBuilder;
294
+
295
+
@@ -0,0 +1,66 @@
1
+ .polotno-container {
2
+ .builder-wrapper {
3
+ @media (max-width: 600px) {
4
+ display: none;
5
+ }
6
+ .polotno-side-panel {
7
+ & .polotno-side-tabs-container {
8
+ background-color: var(--sidepanelBgColor);
9
+ & .polotno-side-tabs-inner {
10
+ & .polotno-side-panel-tab {
11
+ color: var(--sidepanelTextColor);
12
+ &.active,
13
+ &:hover {
14
+ background-color: var(--sidepanelOptionHoverColor);
15
+ opacity: 0.8;
16
+ color: var(--sidepanelTextColorHover);
17
+ svg {
18
+ color: var(--primaryColor);
19
+ path {
20
+ stroke: var(--primaryColor) !important;
21
+ }
22
+ line {
23
+ stroke: var(--primaryColor) !important;
24
+ }
25
+ }
26
+ }
27
+ }
28
+ }
29
+ }
30
+ & .polotno-panel-container {
31
+ background-color: var(--mainBackgroundColor);
32
+ & > div > p {
33
+ display: none;
34
+ }
35
+ .bp5-tabs {
36
+ .bp5-tab-list {
37
+ .bp5-tab-indicator-wrapper {
38
+ .bp5-tab-indicator {
39
+ background-color: var(--primaryColor);
40
+ }
41
+ }
42
+ .bp5-tab[aria-selected='true'] {
43
+ color: var(--primaryColor);
44
+ &:focus {
45
+ outline: none;
46
+ }
47
+ }
48
+ .bp5-tab[aria-selected='false'] {
49
+ color: var(--textColor);
50
+ &:focus {
51
+ outline: none;
52
+ }
53
+ }
54
+ }
55
+ }
56
+ }
57
+ }
58
+ .polotno-workspace-container {
59
+ background-color: transparent !important;
60
+ }
61
+ }
62
+ }
63
+
64
+ .bp5-popover-transition-container {
65
+ z-index: 2200 !important;
66
+ }
@@ -0,0 +1,58 @@
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
+ // images
10
+ import ModalCross from '../../../assets/images/modal-icons/modal-cross';
11
+
12
+ // Styles
13
+ import "./styles.scss";
14
+
15
+
16
+ /**
17
+ * ConfirmNavigateDialog Component
18
+ * A modal for duplicating a template.
19
+ *
20
+ * @param {boolean} open - Boolean indicating whether the modal is open.
21
+ * @param {Function} handleClose - Function to handle the closing of the modal.
22
+ * @returns {JSX.Element} The duplicate template modal component.
23
+ *
24
+ */
25
+
26
+ const cancelDialogStyles = {
27
+ maxWidth: '450px',
28
+ minHeight: '260px',
29
+ };
30
+
31
+ // Define the props type
32
+ interface ConfirmNavigateDialogProps {
33
+ open: boolean;
34
+ handleClose: () => void;
35
+ handleNavigateAction: () => void;
36
+ }
37
+
38
+
39
+ const ConfirmNavigateDialog: React.FC<ConfirmNavigateDialogProps> = ({ open, handleClose, handleNavigateAction }) => {
40
+
41
+ return (
42
+ <Dialog
43
+ icon={<ModalCross fill="var(--primaryColor)" />}
44
+ customStyles={cancelDialogStyles}
45
+ open={open}
46
+ handleClose={handleClose}
47
+ title={MESSAGES.TEMPLATE.CANCEL.TITLE}
48
+ subHeading={MESSAGES.TEMPLATE.CANCEL.HEADING}
49
+ description={MESSAGES.TEMPLATE.CANCEL.PARAGRAPH}
50
+ onSubmit={handleNavigateAction}
51
+ onCancel={handleClose}
52
+ cancelText={MESSAGES.TEMPLATE.CANCEL.BACK_BUTTON}
53
+ submitText={MESSAGES.TEMPLATE.CANCEL.CANCEL_BUTTON}
54
+ />
55
+ );
56
+ };
57
+
58
+ export default ConfirmNavigateDialog;
@@ -0,0 +1,123 @@
1
+ .confirmCancelTemplateLeaveModal {
2
+ .MuiPaper-root {
3
+ width: 100% !important;
4
+ max-width: 407px !important;
5
+ height: 100% !important;
6
+ max-height: 258px !important;
7
+ margin: 0 auto !important;
8
+ border-radius: 11px;
9
+ background: #fff8ee;
10
+ }
11
+
12
+ .confirmTemplateLeaveModalTitle {
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
+ .confirmTemplateLeaveModalContent {
22
+ display: flex;
23
+ flex-direction: column;
24
+ gap: 10px;
25
+ padding: 16px 16px 0px 16px !important;
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: 12px;
38
+ }
39
+ }
40
+
41
+ .confirmTemplateLeaveText {
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: 13px;
93
+ gap: 11px;
94
+
95
+ button {
96
+ border-radius: 3px !important;
97
+ text-transform: capitalize;
98
+
99
+ &:first-child {
100
+ border: 0.5px solid rgba(48, 48, 48, 0.5);
101
+ background: #fff;
102
+ color: #000;
103
+ font-size: 14px;
104
+ font-style: normal;
105
+ font-weight: 600;
106
+ line-height: normal;
107
+ min-width: 100px !important;
108
+ min-height: 40px !important;
109
+ }
110
+
111
+ &:last-child {
112
+ color: #fff;
113
+ font-size: 14px;
114
+ font-style: normal;
115
+ font-weight: 600;
116
+ line-height: normal;
117
+ background: #ed5c2f;
118
+ max-width: 146px !important;
119
+ min-height: 40px !important;
120
+ }
121
+ }
122
+ }
123
+ }
@@ -0,0 +1,98 @@
1
+ import React, { useEffect, useState } from 'react';
2
+
3
+ // Hooks
4
+ import { useDispatch, useSelector } from 'react-redux';
5
+ import { RootState, AppDispatch } from '../../../redux/store';
6
+
7
+ // Actions
8
+ import { searchAndAdvanceChange } from '../../../redux/actions/templateActions';
9
+ import { failure } from '../../../redux/actions/snackbarActions';
10
+
11
+ // Utils
12
+ import { MESSAGES } from '../../../utils/message';
13
+
14
+ // UI Components
15
+ import Dialog from '../../../components/GenericUIBlocks/Dialog';
16
+ import Input from '../../../components/GenericUIBlocks/Input';
17
+
18
+ // Styles
19
+ import './styles.scss';
20
+
21
+
22
+ /**
23
+ * EditTemplateNameModel Component
24
+ * A modal for duplicating a template.
25
+ *
26
+ * @param {boolean} open - Boolean indicating whether the modal is open.
27
+ * @param {Function} handleClose - Function to handle the closing of the modal.
28
+ * @returns {JSX.Element} The duplicate template modal component.
29
+ *
30
+ */
31
+
32
+ interface EditTemplateNameModelProps {
33
+ open: boolean;
34
+ handleClose: () => void;
35
+ }
36
+
37
+ const editDialogStyles = {
38
+ maxWidth: '630px',
39
+ minHeight: '210px',
40
+ };
41
+
42
+ const EditTemplateNameModel: React.FC<EditTemplateNameModelProps> = ({
43
+ open,
44
+ handleClose,
45
+ }) => {
46
+ const [title, setTitle] = useState('');
47
+
48
+ const dispatch: AppDispatch = useDispatch();
49
+
50
+ const templateTitle =
51
+ useSelector((state: RootState) => state.templates.title) || '';
52
+
53
+ useEffect(() => {
54
+ setTitle(templateTitle);
55
+ }, []);
56
+
57
+ // Handle the duplication of the template
58
+ const handleEditName = async () => {
59
+ let errorText = '';
60
+ if (!title) {
61
+ errorText = MESSAGES.TEMPLATE.NAME_REQUIRED;
62
+ } else if (title.length > 50) {
63
+ errorText = MESSAGES.TEMPLATE.NAME_LESS_50;
64
+ }
65
+ if (errorText) {
66
+ dispatch(failure(errorText));
67
+ return;
68
+ }
69
+ dispatch(searchAndAdvanceChange('title', title.trim()));
70
+ handleClose();
71
+ };
72
+
73
+ return (
74
+ <Dialog
75
+ open={open}
76
+ loading={false}
77
+ handleClose={handleClose}
78
+ title="Edit Template Name"
79
+ cancelText={MESSAGES.TEMPLATE.SAVE.CANCEL_BUTTON}
80
+ submitText="Save"
81
+ customStyles={editDialogStyles}
82
+ onSubmit={handleEditName}
83
+ onCancel={handleClose}
84
+ >
85
+ <Input
86
+ variant="input"
87
+ type="text"
88
+ label="Template Name"
89
+ placeholder="Holidays"
90
+ value={title}
91
+ onChange={e => setTitle(e.target.value)}
92
+ />
93
+ </Dialog>
94
+ );
95
+ };
96
+
97
+ export default EditTemplateNameModel;
98
+