ui-soxo-bootstrap-core 2.6.40-dev.0 → 2.6.40-dev.1

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.
@@ -2,136 +2,92 @@
2
2
  *
3
3
  * Global header component
4
4
  */
5
-
6
5
  import { useContext, useEffect, useRef, useState } from 'react';
7
-
8
6
  import { motion, useAnimation } from 'framer-motion';
9
-
10
7
  import { boxVariants } from './animations';
11
-
12
8
  import { GlobalContext, GlobalProvider } from './../../Store';
13
-
14
9
  import { Link, useLocation } from 'react-router-dom';
15
-
16
10
  import { Avatar, Input, Tooltip, Typography } from 'antd';
17
-
18
11
  import ProgressBar from '../progress-bar/progress-bar'; // Adjust the path as needed
19
-
20
12
  import { Button } from '../../elements';
21
-
22
13
  import GenericHeader from '../header/generic-header';
23
-
24
-
25
14
  import { CustomerServiceOutlined, MenuOutlined, SettingOutlined, UserOutlined } from '@ant-design/icons';
26
-
27
15
  import { Drawer } from 'antd';
28
-
29
16
  import { ReloadOutlined, SearchOutlined } from '@ant-design/icons';
30
-
31
17
  import SideMenu from './../sidemenu/sidemenu';
32
-
33
18
  import './global-header.scss';
34
-
35
19
  import LanguageSwitcher from '../language-switcher/language-switcher';
36
-
37
20
  import { useTranslation } from 'react-i18next';
38
-
39
21
  import SettingsUtil from '../../../utils/settings.utils';
40
22
  import SpotlightSearch from '../spotlight-search/spotlight-search.component';
41
-
23
+ import { LicenseAlert } from '../../../components';
42
24
  const { Title } = Typography;
43
-
44
- function GlobalHeaderContent({ loading, appSettings, children, isConnected, history, modules = [], sidemenu = [], reload, meta = {}, ...props }) {
25
+ function GlobalHeaderContent({ loading, appSettings, children, isConnected, history, modules = [], sidemenu = [], reload, meta = {}, licAlert,
26
+ licenseData ,...props }) {
45
27
  let location = useLocation();
46
28
  // let location = {};
47
-
48
29
  const { isMobile, user = { locations: [] }, kiosk, state, settings } = useContext(GlobalContext);
49
-
50
30
  const [visible, setVisible] = useState(false);
51
31
  const helpDeskSetting = settings?.HELPATR || {};
52
-
53
32
  // Variable to handle toggling of menu
54
33
  const [collapsed, setCollapsed] = useState(false);
55
34
  // varibale handle branch switcher
56
-
57
35
  // const [searchModalVisible, setSearchModalVisible] = useState(false);
58
-
59
36
  const { globalCustomerHeader = () => {} } = appSettings;
60
-
61
37
  const { t, i18n } = useTranslation();
62
-
63
38
  const spotlightRef = useRef();
64
-
65
39
  useEffect(() => {
66
40
  setTimeout(() => {
67
41
  i18n.changeLanguage(localStorage.selectedLanguage);
68
42
  }, 0);
69
43
  }, []);
70
-
71
44
  /**
72
45
  * Function to handle toggling of menu
73
46
  */
74
-
75
47
  const toggleCollapsed = () => {
76
48
  setVisible(true);
77
-
78
49
  collapsed === true ? setCollapsed(false) : setCollapsed(true);
79
50
  };
80
-
81
51
  const openSearchModal = () => {
82
52
  // input to avoid typing
83
53
  SettingsUtil.openSpotlightModal();
84
54
  };
85
-
86
55
  /**
87
56
  * Function to remove toggling on mobile view
88
57
  */
89
58
  const hideToggle = () => {
90
59
  setVisible(true);
91
-
92
60
  setCollapsed(false);
93
61
  };
94
-
95
62
  /**
96
63
  * onClose Function
97
64
  */
98
-
99
65
  const onClose = () => {
100
66
  setVisible(false);
101
67
  };
102
-
103
68
  // const { model = {} } = menu;
104
-
105
69
  const { model: BaseModel = {}, menu = {} } = meta;
106
-
107
70
  const { model = {} } = menu;
108
-
109
71
  //Animations//
110
72
  const boxControls = useAnimation();
111
-
112
73
  async function animate() {
113
74
  await boxControls.start('entered');
114
-
115
75
  //await boxControls.start("show");
116
76
  }
117
-
118
77
  useEffect(() => {
119
78
  animate();
120
79
  }, []);
121
-
122
80
  useEffect(() => {}, [state.theme]);
123
-
124
81
  return (
82
+ <>
125
83
  <div
126
84
  className={`global-header ${process.env.REACT_APP_THEME} ${isConnected && !kiosk ? 'connected' : ''}`}
127
85
  style={{
128
86
  // background: state.theme.colors.bodyBackground,
129
-
130
- height: 10,
87
+ height: 'auto',
131
88
  }}
132
89
  >
133
90
  {/* <MenuOutlined style={{left:'1%',top:'1%', fontSize:18, position:'absolute', zIndex:999}} onClick={showSidebar}/> */}
134
-
135
91
  <div className="layout-content">
136
92
  <div
137
93
  //whileHover="hover"
@@ -174,7 +130,6 @@ function GlobalHeaderContent({ loading, appSettings, children, isConnected, hist
174
130
  </Drawer>
175
131
  )}
176
132
  </div>
177
-
178
133
  {/* Right Section of the Component Loader */}
179
134
  <div
180
135
  className={`right-section ${!collapsed ? 'open' : 'close'} ${kiosk ? 'kioskon' : ''}`}
@@ -189,11 +144,9 @@ function GlobalHeaderContent({ loading, appSettings, children, isConnected, hist
189
144
  {/* */}
190
145
  <div className="page-header-name">
191
146
  <ProgressBar isLoading={loading} />
192
-
193
147
  <span type onClick={!isMobile ? toggleCollapsed : hideToggle} className="toggle-box toggle-menu">
194
148
  <MenuOutlined />
195
149
  </span>
196
-
197
150
  {/* Back Button */}
198
151
  {location.pathname !== '/' ? (
199
152
  <span
@@ -206,39 +159,30 @@ function GlobalHeaderContent({ loading, appSettings, children, isConnected, hist
206
159
  </span>
207
160
  ) : null}
208
161
  {/* Back Button Ends */}
209
-
210
162
  {location.pathname !== '/' ? (
211
163
  <h4 className="menu-caption header-caption" style={{ color: state.theme.colors.headerColor }}>
212
164
  {menu.caption}
213
165
  </h4>
214
166
  ) : null}
215
167
  </div>
216
-
217
168
  {/* Page Menu Actions */}
218
-
219
169
  {user.role || user.id ? (
220
170
  <div className="page-menu">
221
171
  {/* Search Input in header start */}
222
172
  {!isMobile && (
223
173
  <div>
224
174
  <Input placeholder="Search (Shift + F)" prefix={<SearchOutlined />} onClick={openSearchModal} readOnly style={{ width: 250 }} />
225
-
226
175
  <SpotlightSearch ref={(elem) => SettingsUtil.registerModal(elem)} props={props} />
227
176
  </div>
228
177
  )}
229
178
  {/* Search Input in header start */}
230
-
231
179
  {/** branchswitcher Option */}
232
180
  {/* branch switcher controlled with env for matria and nura */}
233
181
  {!process.env.REACT_APP_SHOW_BRANCH_SWITCHER ? <div className="branch-switcher">{globalCustomerHeader()}</div> : null}
234
182
  {/* <div className="branch-switcher">{globalCustomerHeader()}</div> */}
235
-
236
183
  {/* Search Option */}
237
-
238
184
  {/* <ModalSearch /> */}
239
-
240
185
  {/* Search Option Ends */}
241
-
242
186
  {/* Configurator Actions */}
243
187
  {user.isAdmin ? (
244
188
  <>
@@ -252,13 +196,9 @@ function GlobalHeaderContent({ loading, appSettings, children, isConnected, hist
252
196
  </>
253
197
  ) : null}
254
198
  {/* Configurator Actions Ends */}
255
-
256
199
  {/* Reload Button */}
257
-
258
200
  <Button onClick={reload} icon={<ReloadOutlined />} type="default" size={'small'}></Button>
259
-
260
201
  {/* Reload Button Ends */}
261
-
262
202
  {/* Help-desk-btn */}
263
203
  {helpDeskSetting?.showSupportBtn
264
204
  ? (() => {
@@ -277,11 +217,9 @@ function GlobalHeaderContent({ loading, appSettings, children, isConnected, hist
277
217
  );
278
218
  })()
279
219
  : null}
280
-
281
220
  {/** Switch Languages starts */}
282
221
  {process.env.REACT_APP_ENABLE_LANGUAGE_SWITCHER ? <LanguageSwitcher /> : null}
283
222
  {/** Switch Languages ends */}
284
-
285
223
  {/* User Profile */}
286
224
  <div style={{ padding: '10px' }}>
287
225
  <ProfileAvatar />
@@ -290,11 +228,9 @@ function GlobalHeaderContent({ loading, appSettings, children, isConnected, hist
290
228
  {/* User Profile Ends */}
291
229
  </div>
292
230
  ) : null}
293
-
294
231
  {/* Page Menu Actions Ends */}
295
232
  </div>
296
233
  ) : null}
297
-
298
234
  {/* The children is rendered */}
299
235
  {children}
300
236
  {/* The children is rendered */}
@@ -302,32 +238,40 @@ function GlobalHeaderContent({ loading, appSettings, children, isConnected, hist
302
238
  {/* Right Section of the Component Loader Ends */}
303
239
  </div>
304
240
  </div>
241
+ {licAlert && licenseData && (
242
+ <div
243
+ style={{
244
+ top: 0,
245
+ marginTop: '3rem',
246
+ right: '2%',
247
+ position: 'absolute',
248
+ zIndex: 1008,
249
+ }}
250
+ >
251
+ <LicenseAlert data={licenseData} />
252
+ </div>
253
+ )}
254
+ </>
305
255
  );
306
256
  }
307
-
308
257
  export default function GlobalHeader(props) {
309
258
  const context = useContext(GlobalContext);
310
-
311
259
  if (context.dispatch) {
312
260
  return <GlobalHeaderContent {...props} />;
313
261
  }
314
-
315
262
  return (
316
263
  <GlobalProvider {...props} appSettings={props.appSettings}>
317
264
  <GlobalHeaderContent {...props} />
318
265
  </GlobalProvider>
319
266
  );
320
267
  }
321
-
322
268
  /**
323
269
  *
324
270
  * @returns
325
271
  */
326
272
  function ProfileAvatar() {
327
273
  const { user = { locations: [] } } = useContext(GlobalContext);
328
-
329
274
  useEffect(() => {}, []);
330
-
331
275
  return (
332
276
  <Link className="profile-avatar" to="/profile">
333
277
  {user.photograph ? (
@@ -337,8 +281,7 @@ function ProfileAvatar() {
337
281
  ) : (
338
282
  <Avatar shape="square" size="small" icon={<UserOutlined />} />
339
283
  )}
340
-
341
284
  {/* {user.name} */}
342
285
  </Link>
343
286
  );
344
- }
287
+ }
@@ -109,7 +109,7 @@ import ConsentComponent from './consent/consent'
109
109
  import TaskOverviewLegacy from './../models/process/components/task-overview-legacy/task-overview-legacy'
110
110
 
111
111
  import ReportingDashboard from '../../modules/reporting/components/reporting-dashboard/reporting-dashboard';
112
-
112
+ import ReportingTable from '../../modules/reporting/components/reporting-dashboard/reporting-table'
113
113
  import ProcessStepsPage from '../../modules/steps/steps'
114
114
  export {
115
115
 
@@ -198,7 +198,7 @@ export {
198
198
  TaskOverviewLegacy,
199
199
  // WebCamera,
200
200
  ConsentComponent,
201
-
201
+ ReportingTable,
202
202
  ReportingDashboard,
203
203
  ProcessStepsPage
204
204
 
@@ -6,24 +6,62 @@
6
6
  * @param {Array<{ label: string, key: string }>} [headers] - Optional column headers and field mappings.
7
7
  * @param {string} [fileName='Report.xlsx'] - Optional name for the downloaded Excel file.
8
8
  */
9
-
10
- import React from 'react';
9
+
10
+ import React, { useState } from 'react';
11
11
  // Import XLSX library to handle Excel file creation
12
12
  import * as XLSX from 'xlsx';
13
+ import { PDFDocument, StandardFonts, rgb } from 'pdf-lib';
13
14
  // import * as XLSX from 'xlsx-js-style';
14
15
  // import * as XLSX from 'xlsx-js-style';
15
16
  // Import saveAs from file-saver to trigger file download in browser
16
17
  import { saveAs } from 'file-saver';
17
- import { Button } from 'antd';
18
+ import { Button, Dropdown, Form, Input, Menu, Modal, Radio, message } from 'antd';
19
+ import { DownOutlined, FileExcelFilled, FilePdfFilled, MailFilled, DownloadOutlined } from '@ant-design/icons';
18
20
  import { Trans } from 'react-i18next';
21
+ import { CoreScripts } from '../../../../models';
22
+ import './generic-list.scss';
23
+
24
+ const normalizeScriptId = (value) => {
25
+ if (value === undefined || value === null || value === '') return value;
26
+
27
+ const numberValue = Number(value);
28
+ return Number.isNaN(numberValue) ? value : numberValue;
29
+ };
30
+
31
+ const getRecipients = (value) => {
32
+ if (Array.isArray(value)) return value.filter(Boolean);
33
+
34
+ return String(value || '')
35
+ .split(/[\n,;]+/)
36
+ .map((email) => email.trim())
37
+ .filter(Boolean);
38
+ };
39
+
40
+
41
+ export const ExportReactCSV = ({
42
+ csvData,
43
+ headers,
44
+ fileName,
45
+ pdfFileName,
46
+ title,
47
+ format = 'excel',
48
+ buttonText,
49
+ dropdown = false,
50
+ onSendReportToMail,
51
+ scriptId,
52
+ inputParameters,
53
+ }) => {
54
+ const [mailModalVisible, setMailModalVisible] = useState(false);
55
+ const [sendingMail, setSendingMail] = useState(false);
56
+ const [selectedFormat, setSelectedFormat] = useState('excel');
57
+ const [mailForm] = Form.useForm();
19
58
 
20
- export const ExportReactCSV = ({ csvData, headers, fileName,title }) => {
21
59
  /**
22
60
  * exportToExcel function
23
61
  * Triggered on button click, generates and downloads an Excel file
24
62
  */
25
63
 
26
- const exportToExcel = () => {
64
+ const exportToExcel = (downloadFileName) => {
27
65
  // if (!csvData?.length) return;
28
66
 
29
67
  let worksheet;
@@ -75,14 +113,302 @@ export const ExportReactCSV = ({ csvData, headers, fileName,title }) => {
75
113
  const blob = new Blob([excelBuffer], {
76
114
  type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
77
115
  });
78
- const flName = fileName || 'Report.xlsx';
116
+ const flName = downloadFileName || fileName || 'Report.xlsx';
79
117
  // Trigger download using file-saver
80
118
  saveAs(blob, flName);
81
119
  };
120
+
121
+ const exportToPdf = async (downloadFileName) => {
122
+ const pdfDoc = await PDFDocument.create();
123
+ const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
124
+ const boldFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
125
+ const pageSize = [842, 595];
126
+ const margin = 30;
127
+ const rowHeight = 20;
128
+ const titleHeight = 38;
129
+ const fontSize = 8;
130
+ const headerFontSize = 8;
131
+ const headersToUse = headers?.length
132
+ ? headers
133
+ : Object.keys(csvData?.[0] || {}).map((key) => ({ label: key, key }));
134
+ const availableWidth = pageSize[0] - margin * 2;
135
+ const columnWidth = headersToUse.length ? availableWidth / headersToUse.length : availableWidth;
136
+ let page;
137
+ let y;
138
+
139
+ const sanitizeValue = (value) => {
140
+ if (value === undefined || value === null) return '';
141
+ if (typeof value === 'object') return JSON.stringify(value);
142
+ return String(value);
143
+ };
144
+
145
+ const fitText = (text, width, textFont, size) => {
146
+ const sanitizedText = sanitizeValue(text);
147
+ if (textFont.widthOfTextAtSize(sanitizedText, size) <= width) return sanitizedText;
148
+
149
+ let fittedText = sanitizedText;
150
+ while (fittedText.length && textFont.widthOfTextAtSize(`${fittedText}...`, size) > width) {
151
+ fittedText = fittedText.slice(0, -1);
152
+ }
153
+ return fittedText ? `${fittedText}...` : '';
154
+ };
155
+
156
+ const addPage = () => {
157
+ page = pdfDoc.addPage(pageSize);
158
+ y = pageSize[1] - margin;
159
+
160
+ page.drawText(title || 'Report', {
161
+ x: margin,
162
+ y,
163
+ size: 14,
164
+ font: boldFont,
165
+ color: rgb(0.1, 0.1, 0.1),
166
+ });
167
+
168
+ y -= titleHeight;
169
+
170
+ headersToUse.forEach((header, index) => {
171
+ const x = margin + index * columnWidth;
172
+ page.drawRectangle({
173
+ x,
174
+ y: y - 5,
175
+ width: columnWidth,
176
+ height: rowHeight,
177
+ color: rgb(0.92, 0.94, 0.96),
178
+ borderColor: rgb(0.72, 0.75, 0.78),
179
+ borderWidth: 0.5,
180
+ });
181
+ page.drawText(fitText(header.label, columnWidth - 8, boldFont, headerFontSize), {
182
+ x: x + 4,
183
+ y: y + 1,
184
+ size: headerFontSize,
185
+ font: boldFont,
186
+ color: rgb(0.1, 0.1, 0.1),
187
+ });
188
+ });
189
+
190
+ y -= rowHeight;
191
+ };
192
+
193
+ addPage();
194
+
195
+ (csvData || []).forEach((row) => {
196
+ if (y < margin + rowHeight) addPage();
197
+
198
+ headersToUse.forEach((header, index) => {
199
+ const x = margin + index * columnWidth;
200
+ page.drawRectangle({
201
+ x,
202
+ y: y - 5,
203
+ width: columnWidth,
204
+ height: rowHeight,
205
+ color: row.isSummaryRow ? rgb(0.97, 0.97, 0.97) : rgb(1, 1, 1),
206
+ borderColor: rgb(0.82, 0.84, 0.86),
207
+ borderWidth: 0.5,
208
+ });
209
+ page.drawText(fitText(row[header.key], columnWidth - 8, row.isSummaryRow ? boldFont : font, fontSize), {
210
+ x: x + 4,
211
+ y: y + 1,
212
+ size: fontSize,
213
+ font: row.isSummaryRow ? boldFont : font,
214
+ color: rgb(0.12, 0.12, 0.12),
215
+ });
216
+ });
217
+
218
+ y -= rowHeight;
219
+ });
220
+
221
+ const pdfBytes = await pdfDoc.save();
222
+ const blob = new Blob([pdfBytes], { type: 'application/pdf' });
223
+ const flName = downloadFileName || pdfFileName || fileName || 'Report.pdf';
224
+ saveAs(blob, flName);
225
+ };
226
+
227
+ const handleDownloadMenuClick = ({ key }) => {
228
+ if (key === 'excel') {
229
+ exportToExcel(fileName);
230
+ return;
231
+ }
232
+
233
+ if (key === 'pdf') {
234
+ exportToPdf(pdfFileName);
235
+ return;
236
+ }
237
+
238
+ if (key === 'mail') {
239
+ setMailModalVisible(true);
240
+ }
241
+ };
242
+
243
+ const handleMailModalClose = () => {
244
+ setMailModalVisible(false);
245
+ mailForm.resetFields();
246
+ setSelectedFormat('excel');
247
+ };
248
+
249
+ const handleFormatToggle = (value) => {
250
+ const nextValue = selectedFormat === value ? null : value;
251
+ setSelectedFormat(nextValue);
252
+ mailForm.setFieldsValue({ format: nextValue });
253
+ };
254
+
255
+ // const handleSendReportToMail = async (values) => {
256
+ // setSendingMail(true);
257
+
258
+ // try {
259
+ // const mailFormat = values.format || selectedFormat || 'excel';
260
+ // const isBoth = mailFormat === 'both';
261
+ // const payload = {
262
+ // script_id: normalizeScriptId(scriptId),
263
+ // input_parameters: inputParameters || {},
264
+ // is_pdf: mailFormat === 'pdf' || isBoth,
265
+ // is_excel: mailFormat === 'excel' || isBoth,
266
+ // is_both: isBoth,
267
+ // recipients: getRecipients(values.email),
268
+ // };
269
+ // const data = onSendReportToMail
270
+ // ? await onSendReportToMail(payload)
271
+ // : await CoreScripts.sentToReportMail(payload);
272
+
273
+ // if (data?.success === false) throw data;
274
+
275
+ // message.success(data?.message || 'Report mail sent successfully');
276
+ // handleMailModalClose();
277
+ // } catch (error) {
278
+ // message.error(error?.message || 'Unable to send report mail');
279
+ // } finally {
280
+ // setSendingMail(false);
281
+ // }
282
+ // };
283
+
284
+ const downloadMenu = (
285
+ <Menu className="export-download-menu" onClick={handleDownloadMenuClick}>
286
+ <Menu.Item
287
+ key="excel"
288
+ icon={<FileExcelFilled className="export-download-menu__icon export-download-menu__icon--excel" />}
289
+ >
290
+ Download Excel Sheet
291
+ </Menu.Item>
292
+ <Menu.Item
293
+ key="pdf"
294
+ icon={<FilePdfFilled className="export-download-menu__icon export-download-menu__icon--pdf" />}
295
+ >
296
+ Download PDF
297
+ </Menu.Item>
298
+ {/* <Menu.Item
299
+ key="mail"
300
+ icon={<MailFilled className="export-download-menu__icon export-download-menu__icon--mail" />}
301
+ >
302
+ Send report to mail
303
+ </Menu.Item> */}
304
+ </Menu>
305
+ );
306
+
307
+ const isPdf = format === 'pdf';
308
+ const handleExportButtonClick = () => {
309
+ if (isPdf) {
310
+ exportToPdf();
311
+ return;
312
+ }
313
+
314
+ exportToExcel();
315
+ };
316
+
317
+ if (dropdown) {
318
+ return (
319
+ <>
320
+ <Dropdown overlay={downloadMenu} trigger={['click']} placement="bottomRight">
321
+ <Button type="primary" size="small" className="export-download-button">
322
+ <Trans i18nKey={buttonText || 'Download'} /> <DownloadOutlined className="export-download-button__icon" />
323
+ </Button>
324
+ </Dropdown>
325
+ {/*
326
+ <Modal
327
+ title="Send report to mail"
328
+ open={mailModalVisible}
329
+ onCancel={handleMailModalClose}
330
+ footer={null}
331
+ destroyOnClose
332
+ width={460}
333
+ >
334
+ <Form
335
+ form={mailForm}
336
+ layout="vertical"
337
+ initialValues={{ format: 'excel' }}
338
+ onFinish={handleSendReportToMail}
339
+ >
340
+ <Form.Item
341
+ name="format"
342
+ style={{ marginBottom: 16 }}
343
+ rules={[
344
+ {
345
+ validator: () =>
346
+ selectedFormat
347
+ ? Promise.resolve()
348
+ : Promise.reject(new Error('Please select a format')),
349
+ },
350
+ ]}
351
+ >
352
+ <div
353
+ className="export-mail-format-options"
354
+ style={{ display: 'flex', alignItems: 'center', columnGap: 24 }}
355
+ >
356
+ <Radio
357
+ checked={selectedFormat === 'excel'}
358
+ style={{ marginRight: 0 }}
359
+ onClick={() => handleFormatToggle('excel')}
360
+ >
361
+ Excel
362
+ </Radio>
363
+ <Radio
364
+ checked={selectedFormat === 'pdf'}
365
+ style={{ marginRight: 0 }}
366
+ onClick={() => handleFormatToggle('pdf')}
367
+ >
368
+ PDF
369
+ </Radio>
370
+ <Radio
371
+ checked={selectedFormat === 'both'}
372
+ style={{ marginRight: 0 }}
373
+ onClick={() => handleFormatToggle('both')}
374
+ >
375
+ Both
376
+ </Radio>
377
+ </div>
378
+ </Form.Item>
379
+
380
+ <Form.Item
381
+ name="email"
382
+ label="EMAIL ID"
383
+ rules={[
384
+ { required: true, message: 'Please enter email id' },
385
+ { type: 'email', message: 'Please enter a valid email id' },
386
+ ]}
387
+ >
388
+ <Input placeholder="Enter Mail Id" />
389
+ </Form.Item>
390
+
391
+ <Form.Item
392
+ name="remarks"
393
+ label="REMARKS"
394
+ rules={[{ required: true, message: 'Please enter remarks' }]}
395
+ >
396
+ <Input.TextArea placeholder="Enter Remarks" rows={4} />
397
+ </Form.Item>
398
+
399
+ <Button type="primary" htmlType="submit" loading={sendingMail}>
400
+ Send
401
+ </Button>
402
+ </Form>
403
+ </Modal> */}
404
+ </>
405
+ );
406
+ }
407
+
82
408
  // Render an Ant Design Button that triggers the Excel export
83
409
  return (
84
- <Button type="secondary" size="small" onClick={exportToExcel}>
85
- <Trans i18nKey="Download" />
410
+ <Button type="secondary" size="small" onClick={handleExportButtonClick} className="export-download-button">
411
+ <Trans i18nKey={buttonText || (isPdf ? 'PDF Download' : 'Download')} /> <DownloadOutlined className="export-download-button__icon" />
86
412
  </Button>
87
413
  );
88
414
  };