ctms-common-components 1.0.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.
Files changed (61) hide show
  1. package/.babelrc +3 -0
  2. package/.czrc +3 -0
  3. package/.github/CODEOWNERS +1 -0
  4. package/.github/workflows/cd.yml +38 -0
  5. package/.github/workflows/ci.yml +29 -0
  6. package/.storybook/main.js +22 -0
  7. package/.storybook/preview.js +14 -0
  8. package/CHANGELOG.md +11 -0
  9. package/README.md +1 -0
  10. package/dist/index.js.LICENSE.txt +50 -0
  11. package/package.json +58 -0
  12. package/public/fonts/lato-latin.woff2 +0 -0
  13. package/public/index.html +17 -0
  14. package/src/assets/components/index.css +3 -0
  15. package/src/assets/components/index.jsx +607 -0
  16. package/src/assets/pngs/background-logo.png +0 -0
  17. package/src/assets/pngs/logo.png +0 -0
  18. package/src/assets/styles/tailwind.css +3 -0
  19. package/src/assets/svgs/edit-icon.svg +12 -0
  20. package/src/assets/svgs/overflow-icon.svg +20 -0
  21. package/src/assets/svgs/tick-mark.svg +3 -0
  22. package/src/components/Button.jsx +50 -0
  23. package/src/components/Pagination/PaginationStyles.js +49 -0
  24. package/src/components/Pagination/index.jsx +85 -0
  25. package/src/components/PoojaCard/index.jsx +216 -0
  26. package/src/components/StatusCard/index.jsx +102 -0
  27. package/src/components/TokenCard/index.jsx +205 -0
  28. package/src/components/button.css +50 -0
  29. package/src/components/custom-Table/AdvancedTableBody.jsx +186 -0
  30. package/src/components/custom-Table/AdvancedTableHead.jsx +315 -0
  31. package/src/components/custom-Table/EllipsisCell.jsx +137 -0
  32. package/src/components/custom-Table/Loader.jsx +24 -0
  33. package/src/components/custom-Table/index.jsx +340 -0
  34. package/src/components/index.js +7 -0
  35. package/src/components/more-actions/MenuStyles.js +54 -0
  36. package/src/components/more-actions/index.jsx +50 -0
  37. package/src/index.jsx +11 -0
  38. package/src/lib.js +133 -0
  39. package/src/stories/AdvancedTable.stories.jsx +108 -0
  40. package/src/stories/Button.stories.js +45 -0
  41. package/src/stories/PoojaCard.stories.jsx +108 -0
  42. package/src/stories/StatusCard.stories.jsx +51 -0
  43. package/src/stories/TokenCard.stories.jsx +75 -0
  44. package/src/theme/README.md +23 -0
  45. package/src/theme/components/button.js +42 -0
  46. package/src/theme/components/checkbox.js +20 -0
  47. package/src/theme/components/index.js +27 -0
  48. package/src/theme/foundations/blur.js +12 -0
  49. package/src/theme/foundations/borders.js +9 -0
  50. package/src/theme/foundations/breakpoints.js +10 -0
  51. package/src/theme/foundations/colors.js +196 -0
  52. package/src/theme/foundations/index.js +27 -0
  53. package/src/theme/foundations/radius.js +13 -0
  54. package/src/theme/foundations/shadows.js +16 -0
  55. package/src/theme/foundations/sizes.js +60 -0
  56. package/src/theme/foundations/spacing.js +37 -0
  57. package/src/theme/foundations/transition.js +25 -0
  58. package/src/theme/foundations/typography.js +55 -0
  59. package/src/theme/foundations/z-index.js +17 -0
  60. package/src/theme/index.js +20 -0
  61. package/webpack.config.js +34 -0
@@ -0,0 +1,340 @@
1
+ /* eslint-disable no-return-assign */
2
+ /* eslint-disable react/no-array-index-key */
3
+ /* eslint-disable no-nested-ternary */
4
+ import React, {
5
+ useEffect, useState, useMemo, useRef
6
+ } from 'react';
7
+ import {
8
+
9
+ Table,
10
+
11
+ TableRow as Tr,
12
+
13
+ TableCell as Td,
14
+
15
+ CircularProgress,
16
+
17
+ Box,
18
+ Typography
19
+
20
+ } from '@mui/material';
21
+ import { debounce } from 'lodash-es';
22
+
23
+ import Pagination from '../Pagination';
24
+ import AdvancedTableHead from './AdvancedTableHead';
25
+ import AdvancedTableBody from './AdvancedTableBody';
26
+
27
+ const DEFAULT_ITEMS_PER_PAGE = 10;
28
+ const AdvancedTable = ({
29
+ columns = [],
30
+ tableData = [],
31
+ pagination = true,
32
+ scrollPagination = false,
33
+ itemsPerPage: defaultItemsPerPage = DEFAULT_ITEMS_PER_PAGE,
34
+ fetchData,
35
+ totalPages = 1,
36
+ onRowClick = () => {},
37
+ onRowCheck = () => {},
38
+ onRowRadioSelected = () => {},
39
+ rowDisabled = [],
40
+ rowDisabledOptionKey = '',
41
+ rowValues = () => {},
42
+ footer = [],
43
+ sortHandler = () => {},
44
+ paginationPosition = 'end',
45
+ tableSize = 'md',
46
+ isExpandable = false,
47
+ activeRows = [],
48
+ tableName,
49
+ leftActions,
50
+ rightActions
51
+ }) => {
52
+ const [page, setPage] = useState(1);
53
+ const [rowsPerPage, setRowsPerPage] = useState(defaultItemsPerPage);
54
+ const [filterValues, setFilterValues] = useState({});
55
+ const [filteredData, setFilteredData] = useState(tableData);
56
+ const [loading, setLoading] = useState(false);
57
+ const [sortConfig, setSortConfig] = useState({ field: '', direction: '' });
58
+ const [radioSelectedIndex, setRadioSelectedIndex] = useState(null);
59
+ const [selectedRows, setSelectedRows] = useState(new Set());
60
+ const [expandedRows, setExpandedRows] = useState([]);
61
+
62
+ const headerRefs = useRef({});
63
+ const cellRefs = useRef({});
64
+ const [columnWidths, setColumnWidths] = useState({});
65
+
66
+ const paginatedData = useMemo(() => {
67
+ if (!pagination || scrollPagination) return filteredData;
68
+ const start = (page - 1) * rowsPerPage;
69
+ return filteredData.slice(start, start + rowsPerPage);
70
+ }, [filteredData, page, rowsPerPage, pagination, scrollPagination]);
71
+
72
+ const checkedItems = paginatedData.map((row) => Array.from(selectedRows).some((item) => JSON.stringify(item) === JSON.stringify(row)));
73
+
74
+ useEffect(() => {
75
+ const widths = {};
76
+ columns.forEach((col) => {
77
+ const headerWidth = headerRefs.current[col.field]?.offsetWidth || 0;
78
+ const cellWidth = cellRefs.current[col.field]?.offsetWidth || 0;
79
+ widths[col.field] = Math.max(headerWidth, cellWidth);
80
+ });
81
+ setColumnWidths(widths);
82
+ }, [columns, tableData]);
83
+
84
+ const handleFilterChange = debounce((filters) => {
85
+ let tempData = [...tableData];
86
+ Object.entries(filters).forEach(([field, { type, value }]) => {
87
+ if (!value) return;
88
+ tempData = tempData.filter((row) => {
89
+ const rowVal = row[field];
90
+ if (type === 'text') return rowVal?.toString().toLowerCase().includes(value.toLowerCase());
91
+ if (type === 'select') return rowVal === value;
92
+ if (type === 'date') return rowVal?.startsWith(value);
93
+ return true;
94
+ });
95
+ });
96
+ setFilteredData(tempData);
97
+ }, 300);
98
+
99
+ const onFilterInput = (field, type, value) => {
100
+ const updatedFilters = {
101
+ ...filterValues,
102
+ [field]: {
103
+ ...(filterValues[field] || {}),
104
+ type,
105
+ value,
106
+ visible: true
107
+ }
108
+ };
109
+ setFilterValues(updatedFilters);
110
+ handleFilterChange(updatedFilters);
111
+ };
112
+
113
+ useEffect(() => {
114
+ setFilteredData(tableData);
115
+ setSelectedRows(new Set(activeRows));
116
+ }, [tableData]);
117
+
118
+ useEffect(() => {
119
+ if (!scrollPagination || page >= totalPages || !fetchData) return;
120
+ const fetch = async () => {
121
+ setLoading(true);
122
+ try {
123
+ await fetchData(page);
124
+ } finally {
125
+ setLoading(false);
126
+ }
127
+ };
128
+ fetch();
129
+ }, [scrollPagination, page, totalPages, fetchData]);
130
+
131
+ const handleScroll = (e) => {
132
+ if (
133
+ scrollPagination
134
+ && e.target.scrollTop + e.target.clientHeight >= e.target.scrollHeight - 5
135
+ && page < totalPages
136
+ && !loading
137
+ ) {
138
+ setPage((prev) => prev + 1);
139
+ }
140
+ };
141
+
142
+ const handleSort = (field) => {
143
+ const direction = sortConfig.field === field && sortConfig.direction === 'asc' ? 'desc' : 'asc';
144
+ setSortConfig({ field, direction });
145
+ sortHandler({ field, direction });
146
+ };
147
+
148
+ const handleIndividualCheck = (e, index, row) => {
149
+ const newSet = new Set(selectedRows);
150
+
151
+ if (e.target.checked) {
152
+ newSet.add(row);
153
+ } else {
154
+ Array.from(newSet).forEach((item) => {
155
+ if (JSON.stringify(item) === JSON.stringify(row)) {
156
+ newSet.delete(item);
157
+ }
158
+ });
159
+ }
160
+
161
+ setSelectedRows(newSet);
162
+
163
+ if (onRowCheck) {
164
+ onRowCheck({
165
+ elementCheck: e.target.checked,
166
+ selectedRow: row,
167
+ selectedRows: Array.from(newSet)
168
+ });
169
+ }
170
+ };
171
+
172
+ const handleAllCheck = () => {
173
+ const allChecked = checkedItems.every(Boolean);
174
+ const newSet = new Set(selectedRows);
175
+
176
+ tableData.forEach((row) => {
177
+ if (!allChecked) {
178
+ newSet.add(row);
179
+ } else {
180
+ Array.from(newSet).forEach((item) => {
181
+ if (JSON.stringify(item) === JSON.stringify(row)) {
182
+ newSet.delete(item);
183
+ }
184
+ });
185
+ }
186
+ });
187
+
188
+ setSelectedRows(newSet);
189
+
190
+ onRowCheck({
191
+ elementCheck: !allChecked,
192
+ selectedRow: null,
193
+ selectedRows: Array.from(newSet)
194
+ });
195
+ };
196
+
197
+ const handleRadioSelect = (index, row) => {
198
+ setRadioSelectedIndex(index);
199
+ onRowRadioSelected(row);
200
+ };
201
+
202
+ const radioSelected = (index) => index === radioSelectedIndex;
203
+
204
+ return (
205
+ <Box
206
+ sx={{
207
+ border: '1px solid #E5E7EB',
208
+ borderRadius: 2,
209
+ overflow: 'hidden',
210
+ backgroundColor: '#fff'
211
+ }}
212
+ >
213
+ <Box
214
+ onScroll={handleScroll}
215
+ sx={{
216
+ overflowX: 'auto',
217
+ overflowY: scrollPagination ? 'auto' : 'visible',
218
+ maxHeight: scrollPagination ? 400 : 'unset'
219
+ }}
220
+ >
221
+ {
222
+ tableName && (
223
+ <Box
224
+ sx={{
225
+ display: 'flex',
226
+ alignItems: 'center',
227
+ justifyContent: 'space-between',
228
+ px: 2,
229
+ py: 1.5,
230
+ borderBottom: '1px solid',
231
+ borderColor: 'divider',
232
+ }}
233
+ >
234
+ {/* Left Section */}
235
+ <Box
236
+ sx={{
237
+ display: 'flex',
238
+ alignItems: 'center',
239
+ gap: 1,
240
+ }}
241
+ >
242
+ {leftActions}
243
+
244
+ <Typography variant="h6" fontWeight={600}>
245
+ {tableName}
246
+ </Typography>
247
+ </Box>
248
+
249
+ {/* Right Section */}
250
+ <Box
251
+ sx={{
252
+ display: 'flex',
253
+ alignItems: 'center',
254
+ gap: 1,
255
+ }}
256
+ >
257
+ {rightActions}
258
+ </Box>
259
+ </Box>
260
+ )
261
+ }
262
+ <Table
263
+ stickyHeader
264
+ size={tableSize}
265
+ sx={{
266
+ minWidth: '100%',
267
+ tableLayout: 'fixed',
268
+ borderCollapse: 'separate',
269
+ borderSpacing: 0
270
+ }}
271
+ >
272
+ <AdvancedTableHead
273
+ columns={columns}
274
+ columnWidths={columnWidths}
275
+ checkedItems={checkedItems}
276
+ handleAllCheck={handleAllCheck}
277
+ sortConfig={sortConfig}
278
+ handleSort={handleSort}
279
+ filterValues={filterValues}
280
+ setFilterValues={setFilterValues}
281
+ onFilterInput={onFilterInput}
282
+ headerRefs={headerRefs}
283
+ />
284
+
285
+ <AdvancedTableBody
286
+ paginatedData={paginatedData}
287
+ columns={columns}
288
+ checkedItems={checkedItems}
289
+ handleIndividualCheck={handleIndividualCheck}
290
+ handleRadioSelect={handleRadioSelect}
291
+ radioSelected={radioSelected}
292
+ rowDisabled={rowDisabled}
293
+ rowDisabledOptionKey={rowDisabledOptionKey}
294
+ rowValues={rowValues}
295
+ onRowClick={onRowClick}
296
+ columnWidths={columnWidths}
297
+ expandedRows={expandedRows}
298
+ setExpandedRows={setExpandedRows}
299
+ />
300
+ </Table>
301
+ </Box>
302
+
303
+ {loading && (
304
+ <Box
305
+ sx={{
306
+ display: 'flex',
307
+ justifyContent: 'center',
308
+ py: 2
309
+ }}
310
+ >
311
+ <CircularProgress size={24} />
312
+ </Box>
313
+ )}
314
+
315
+ {!scrollPagination && pagination && (
316
+ <Box
317
+ sx={{
318
+ display: 'flex',
319
+ justifyContent: paginationPosition || 'flex-end',
320
+ p: 2
321
+ }}
322
+ >
323
+ <Pagination
324
+ currentPage={page}
325
+ itemsPerPage={rowsPerPage}
326
+ totalItems={tableData?.length || 0}
327
+ handlePageChange={(newPage) => setPage(newPage)}
328
+ handleRowsPerPageChange={(newLimit) => {
329
+ setRowsPerPage(newLimit);
330
+ setPage(1);
331
+ }}
332
+ rowsPerPageOptions={[5, 10, 25, 50]}
333
+ />
334
+ </Box>
335
+ )}
336
+ </Box>
337
+ );
338
+ };
339
+
340
+ export default AdvancedTable;
@@ -0,0 +1,7 @@
1
+ export * as Pagination from './Pagination';
2
+ export * as PoojaCard from './PoojaCard';
3
+ export * as StatusCard from './StatusCard';
4
+ export * as TokenCard from './TokenCard';
5
+ export * as AdvancedTable from './custom-Table';
6
+ export * as MoreActions from './more-actions';
7
+ export { Button as CustomButton } from './Button';
@@ -0,0 +1,54 @@
1
+ import colors from '../../theme/foundations/colors';
2
+
3
+ const component = {};
4
+
5
+ const style = {
6
+ '.menu-btn + div div': {
7
+ boxShadow: '0px 25px 33px 0px rgba(0, 0, 0, 0.19)',
8
+ padding: '15px',
9
+ borderRadius: '11px',
10
+ outline: 0,
11
+ border: 0
12
+ },
13
+ '.menu-btn + div > div::after': {
14
+ content: "''",
15
+ position: 'absolute',
16
+ width: '22px',
17
+ height: '22px',
18
+ borderRadius: '5px',
19
+ background: colors.white,
20
+ right: '-10px',
21
+ top: '50%',
22
+ transform: 'translateY(-120%) rotate(45deg)',
23
+ zIndex: '0'
24
+ },
25
+ '.menu-btn + div div button': {
26
+ padding: '10px 12px',
27
+ borderRadius: '8px',
28
+ color: colors.gray[800],
29
+ position: 'relative',
30
+ fontSize: '14px',
31
+ fontWeight: 500,
32
+ lineHeight: '14px',
33
+ transition: 'all 150ms ease-in-out',
34
+ ':hover': {
35
+ background: `${colors.primary[500]} !important`,
36
+ color: colors.white
37
+ },
38
+ ':focus': {
39
+ background: colors.white
40
+ }
41
+ },
42
+ '.menu-btn + div div button:not(:last-of-type):after': {
43
+ content: "''",
44
+ position: 'absolute',
45
+ bottom: 0,
46
+ width: '100%',
47
+ height: '1px',
48
+ left: 0,
49
+ right: 0,
50
+ background: colors.gray[100]
51
+ }
52
+ };
53
+
54
+ export default { component, style };
@@ -0,0 +1,50 @@
1
+ import React from 'react';
2
+ import {
3
+ Menu, MenuButton, MenuList, MenuItem
4
+ }from '@emotion/react';
5
+ import { ActionIcon } from '../../assets/components';
6
+
7
+ const MoreActions = (props) => {
8
+ const { actionData, rowData } = props;
9
+
10
+ return actionData.length === 1 ? (
11
+ <Menu>
12
+ {actionData.map(({
13
+ onClick: onItemClick, label, icon, id
14
+ }) => (
15
+ <MenuButton
16
+ key={label}
17
+ as="button"
18
+ onClick={() => {
19
+ onItemClick(rowData || id);
20
+ }}
21
+ >
22
+ {icon}
23
+ </MenuButton>
24
+ ))}
25
+ </Menu>
26
+ ) : (
27
+ <Menu placement="left">
28
+ <MenuButton as="button" className="menu-btn">
29
+ <ActionIcon />
30
+ </MenuButton>
31
+ <MenuList>
32
+ {actionData.map(({
33
+ onClick: onItemClick, label, icon, id
34
+ }) => (
35
+ <MenuItem
36
+ key={label}
37
+ as="button"
38
+ onClick={() => {
39
+ onItemClick(rowData || id);
40
+ }}
41
+ >
42
+ {icon} {label}
43
+ </MenuItem>
44
+ ))}
45
+ </MenuList>
46
+ </Menu>
47
+ );
48
+ };
49
+
50
+ export default MoreActions;
package/src/index.jsx ADDED
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom/client';
3
+
4
+
5
+ const root = ReactDOM.createRoot(document.getElementById('root'));
6
+
7
+ root.render(
8
+ <React.StrictMode>
9
+ <App />
10
+ </React.StrictMode>
11
+ );
package/src/lib.js ADDED
@@ -0,0 +1,133 @@
1
+ export {
2
+ ThemeProvider,
3
+ createTheme,
4
+ styled
5
+ } from '@mui/material/styles';
6
+
7
+ export {
8
+ Accordion,
9
+ AccordionActions,
10
+ AccordionDetails,
11
+ AccordionSummary,
12
+ Alert,
13
+ AlertTitle,
14
+ AppBar,
15
+ Autocomplete,
16
+ Avatar,
17
+ AvatarGroup,
18
+ Backdrop,
19
+ Badge,
20
+ BottomNavigation,
21
+ BottomNavigationAction,
22
+ Box,
23
+ Breadcrumbs,
24
+ Button,
25
+ ButtonBase,
26
+ ButtonGroup,
27
+ Card,
28
+ CardActions,
29
+ CardContent,
30
+ CardHeader,
31
+ CardMedia,
32
+ Checkbox,
33
+ Chip,
34
+ CircularProgress,
35
+ Collapse,
36
+ Container,
37
+ CssBaseline,
38
+ Dialog,
39
+ DialogActions,
40
+ DialogContent,
41
+ DialogContentText,
42
+ DialogTitle,
43
+ Divider,
44
+ Drawer,
45
+ Fab,
46
+ Fade,
47
+ FormControl,
48
+ FormControlLabel,
49
+ FormGroup,
50
+ FormHelperText,
51
+ FormLabel,
52
+ Grid,
53
+ IconButton,
54
+ ImageList,
55
+ ImageListItem,
56
+ Input,
57
+ InputAdornment,
58
+ InputBase,
59
+ InputLabel,
60
+ LinearProgress,
61
+ Link,
62
+ List,
63
+ ListItem,
64
+ ListItemAvatar,
65
+ ListItemButton,
66
+ ListItemIcon,
67
+ ListItemText,
68
+ Menu,
69
+ MenuItem,
70
+ MenuList,
71
+ Modal,
72
+ Pagination,
73
+ Paper,
74
+ Popover,
75
+ Portal,
76
+ Radio,
77
+ RadioGroup,
78
+ Rating,
79
+ Select,
80
+ Skeleton,
81
+ Slide,
82
+ Slider,
83
+ Snackbar,
84
+ Stack,
85
+ Step,
86
+ StepButton,
87
+ StepConnector,
88
+ StepContent,
89
+ StepLabel,
90
+ Stepper,
91
+ SvgIcon,
92
+ Switch,
93
+ Tab,
94
+ Table,
95
+ TableBody,
96
+ TableCell,
97
+ TableContainer,
98
+ TableFooter,
99
+ TableHead,
100
+ TablePagination,
101
+ TableRow,
102
+ Tabs,
103
+ TextField,
104
+ Toolbar,
105
+ Tooltip,
106
+ Typography,
107
+ useMediaQuery
108
+ } from '@mui/material';
109
+
110
+ export * from '@mui/icons-material';
111
+
112
+ export { motion, AnimatePresence } from 'framer-motion';
113
+
114
+ export {
115
+ debounce,
116
+ throttle,
117
+ cloneDeep,
118
+ merge,
119
+ uniq,
120
+ groupBy
121
+ } from 'lodash-es';
122
+
123
+
124
+ export {
125
+ PoojaCard,
126
+ MoreActions,
127
+ AdvancedTable,
128
+ TokenCard,
129
+ StatusCard,
130
+ CustomButton
131
+ } from './components'
132
+
133
+
@@ -0,0 +1,108 @@
1
+ import React from 'react';
2
+ import { Button } from '@mui/material';
3
+
4
+ import AdvancedTable from '../components/custom-Table';
5
+
6
+ export default {
7
+ title: 'Components/AdvancedTable',
8
+ component: AdvancedTable
9
+ };
10
+
11
+ const mockColumns = [
12
+ {
13
+ header: 'Select',
14
+ type: 'multi-select',
15
+ alignment: 'center',
16
+ width: '20'
17
+ },
18
+ {
19
+ header: 'Expandable',
20
+ type: 'isExpandable',
21
+ alignment: 'start',
22
+ width: '10%'
23
+ },
24
+ {
25
+ field: 'id',
26
+ header: 'ID',
27
+ sort: true,
28
+ alignment: 'center',
29
+ filterType: 'text'
30
+ },
31
+ {
32
+ field: 'name',
33
+ header: 'Name',
34
+ sort: true,
35
+ alignment: 'center',
36
+ filterType: 'text'
37
+ },
38
+ {
39
+ field: 'status',
40
+ header: 'Status',
41
+ filterType: 'select',
42
+ alignment: 'center',
43
+ options: ['Active', 'Inactive']
44
+ },
45
+ {
46
+ field: 'date',
47
+ header: 'Date',
48
+ alignment: 'center',
49
+ filterType: 'date'
50
+ },
51
+ {
52
+ header: 'List',
53
+ field: 'list2',
54
+ alignment: 'center',
55
+ isExpandable: true,
56
+ width: '30%'
57
+ }
58
+ ];
59
+
60
+ const mockData = Array.from({ length: 15 }).map((_, i) => ({
61
+ id: i + 1,
62
+ name: `User ${i + 1}`,
63
+ status: i % 2 === 0 ? 'Active' : 'Inactive',
64
+ date: `2024-07-${String(i + 1).padStart(2, '0')}`,
65
+ list2: [
66
+ 'Sale of Agricultural Implements',
67
+ 'Machineries',
68
+ 'Acupuncture Clinic'
69
+ ]
70
+ }));
71
+
72
+ const Template = (args) => <AdvancedTable {...args} />;
73
+
74
+ export const Default = Template.bind({});
75
+
76
+ Default.args = {
77
+ columns: mockColumns,
78
+ tableData: mockData,
79
+ pagination: true,
80
+ scrollPagination: false,
81
+
82
+ tableName: 'Orders',
83
+
84
+ rightActions: (
85
+ <>
86
+ <Button variant="outlined">
87
+ Export
88
+ </Button>
89
+
90
+ <Button variant="contained">
91
+ Add Order
92
+ </Button>
93
+ </>
94
+ ),
95
+
96
+ footer: [
97
+ {
98
+ field: 'name',
99
+ alignment: 'center',
100
+ value: 'Total Users'
101
+ },
102
+ {
103
+ field: 'id',
104
+ alignment: 'center',
105
+ value: mockData.length.toString()
106
+ }
107
+ ]
108
+ };