rez-table-listing-mui 0.0.25 → 0.0.27

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 (47) hide show
  1. package/.env.uat +1 -0
  2. package/.eslintrc.cjs +11 -9
  3. package/dist/index.d.ts +102 -8
  4. package/dist/index.js +1 -1
  5. package/dist/index.mjs +1 -1
  6. package/package.json +25 -11
  7. package/src/App.tsx +172 -129
  8. package/src/assets/svg.tsx +65 -2
  9. package/src/components/common/confirm-modal/index.tsx +200 -0
  10. package/src/components/filter/components/attributes-filter.tsx +28 -0
  11. package/src/components/filter/components/forms/components/Attributes-select.tsx +182 -0
  12. package/src/components/filter/components/forms/components/Date.tsx +58 -0
  13. package/src/components/filter/components/forms/components/Dropdown.tsx +62 -0
  14. package/src/components/filter/components/forms/components/Filter-criteria.tsx +164 -0
  15. package/src/components/filter/components/forms/components/Multi-Select.tsx +57 -0
  16. package/src/components/filter/components/forms/components/Select.tsx +53 -0
  17. package/src/components/filter/components/forms/components/Textfield.tsx +43 -0
  18. package/src/components/filter/components/forms/components/styles.tsx +11 -0
  19. package/src/components/filter/components/forms/index.tsx +444 -0
  20. package/src/components/filter/components/main-filter.tsx +66 -0
  21. package/src/components/filter/components/saved-edit-filter.tsx +107 -0
  22. package/src/components/filter/components/saved-filter.tsx +150 -0
  23. package/src/components/filter/components/search/index.tsx +56 -0
  24. package/src/components/filter/components/tabs/custom-tab-panel.tsx +29 -0
  25. package/src/components/filter/components/tabs/index.tsx +85 -0
  26. package/src/components/filter/index.tsx +261 -0
  27. package/src/components/index-table.tsx +3 -6
  28. package/src/components/index.scss +4 -0
  29. package/src/components/login/index.tsx +49 -0
  30. package/src/components/table-body.tsx +6 -4
  31. package/src/components/table-head.tsx +0 -10
  32. package/src/components/topbar/index.scss +5 -0
  33. package/src/components/topbar/index.tsx +54 -19
  34. package/src/components/viewmore/index.tsx +2 -2
  35. package/src/libs/hooks/useCraftTable.tsx +29 -5
  36. package/src/libs/hooks/useDefaultColumns.tsx +2 -2
  37. package/src/libs/hooks/useEntityTableAPI.tsx +183 -0
  38. package/src/libs/hooks/useEntityTableHooks.ts +25 -0
  39. package/src/libs/utils/apiColumn.ts +123 -0
  40. package/src/libs/utils/common.ts +42 -0
  41. package/src/main.tsx +6 -3
  42. package/src/types/common.ts +67 -0
  43. package/src/types/filter.ts +215 -0
  44. package/src/types/table-options.ts +15 -2
  45. package/src/types/table.ts +5 -5
  46. package/tsconfig.json +1 -1
  47. package/vite.config.ts +3 -3
@@ -0,0 +1,150 @@
1
+ import { useEffect, useState } from "react";
2
+ import {
3
+ FilterFormComponentProps,
4
+ FilterMasterStateProps,
5
+ FilterOperationListProps,
6
+ } from "../../../types/filter";
7
+ import {
8
+ Box,
9
+ IconButton,
10
+ List,
11
+ ListItem,
12
+ ListItemText,
13
+ Typography,
14
+ } from "@mui/material";
15
+ import CustomSearch from "./search";
16
+ import { DeleteIcon } from "../../../assets/svg";
17
+ import SavedFilterEditComponent from "./saved-edit-filter";
18
+
19
+ const SavedFilter = ({
20
+ columnsData,
21
+ dropdownData,
22
+ tableStates,
23
+ selectedFilters,
24
+ setSelectedFilters,
25
+ editMode,
26
+ setEditMode,
27
+ setDeleteFilterModalOpen,
28
+ setSavedFilterModalOpen,
29
+ tabValue,
30
+ }: FilterFormComponentProps) => {
31
+ const { setFilterMaster, setFilterToDelete } = tableStates;
32
+ const [searchTerm, setSearchTerm] = useState<string>("");
33
+
34
+ // reset savedFilterEditValue when component unmounts
35
+ useEffect(() => {
36
+ return () => {
37
+ setFilterMaster(
38
+ (prev) =>
39
+ ({
40
+ ...prev,
41
+ saved_filters: {
42
+ ...prev?.attributes,
43
+ selectedId: "",
44
+ selectedName: "",
45
+ },
46
+ } as FilterMasterStateProps)
47
+ );
48
+
49
+ setSelectedFilters([]);
50
+ setEditMode && setEditMode(false);
51
+ };
52
+ }, []);
53
+
54
+ const handleListItemClick = (filter: FilterOperationListProps) => {
55
+ setFilterMaster(
56
+ (prev) =>
57
+ ({
58
+ ...prev,
59
+ saved_filters: {
60
+ ...prev?.attributes,
61
+ selectedId: filter.value,
62
+ selectedName: filter.label,
63
+ },
64
+ activeFilterTabIndex: tabValue,
65
+ } as FilterMasterStateProps)
66
+ );
67
+
68
+ setEditMode && setEditMode(true);
69
+ setFilterToDelete(filter);
70
+ };
71
+
72
+ const renderList = () => (
73
+ <>
74
+ <CustomSearch value={searchTerm} onChange={setSearchTerm} />
75
+
76
+ {columnsData.saved_filter.length === 0 ? (
77
+ <Typography sx={{ mt: 2 }}>No saved filters yet.</Typography>
78
+ ) : (
79
+ <List
80
+ sx={{
81
+ display: "flex",
82
+ flexDirection: "column",
83
+ gap: 1,
84
+ mt: 2,
85
+ }}
86
+ >
87
+ {columnsData.saved_filter
88
+ .filter((filter) =>
89
+ filter.label?.toLowerCase().includes(searchTerm.toLowerCase())
90
+ )
91
+ .map((filter) => (
92
+ <ListItem
93
+ key={filter.value}
94
+ sx={{
95
+ cursor: "pointer",
96
+ border: "1px solid #ccc",
97
+ borderRadius: "8px",
98
+ display: "flex",
99
+ justifyContent: "space-between",
100
+ alignItems: "center",
101
+ }}
102
+ onClick={() => handleListItemClick(filter)}
103
+ >
104
+ <ListItemText primary={filter.label} />
105
+
106
+ <Box onClick={(e) => e.stopPropagation()}>
107
+ <IconButton
108
+ size="small"
109
+ onClick={() => {
110
+ setFilterToDelete(filter); // Store the filter to delete
111
+
112
+ setDeleteFilterModalOpen &&
113
+ setDeleteFilterModalOpen(true); // Open the delete confirmation modal
114
+ }}
115
+ >
116
+ <DeleteIcon />
117
+ </IconButton>
118
+ </Box>
119
+ </ListItem>
120
+ ))}
121
+ </List>
122
+ )}
123
+ </>
124
+ );
125
+
126
+ return (
127
+ <Box>
128
+ {/* Render search input and list */}
129
+ {!editMode && renderList()}
130
+
131
+ {editMode ? (
132
+ <SavedFilterEditComponent
133
+ columnsData={columnsData}
134
+ dropdownData={dropdownData}
135
+ tableStates={tableStates}
136
+ selectedFilters={selectedFilters}
137
+ setSelectedFilters={setSelectedFilters}
138
+ editMode={editMode}
139
+ setEditMode={setEditMode}
140
+ searchTerm={searchTerm}
141
+ setSearchTerm={setSearchTerm}
142
+ setSavedFilterModalOpen={setSavedFilterModalOpen}
143
+ setDeleteFilterModalOpen={setDeleteFilterModalOpen}
144
+ />
145
+ ) : null}
146
+ </Box>
147
+ );
148
+ };
149
+
150
+ export default SavedFilter;
@@ -0,0 +1,56 @@
1
+ import React, { useState } from "react";
2
+ import { TextField, InputAdornment } from "@mui/material";
3
+ import SearchIcon from "@mui/icons-material/Search";
4
+
5
+ interface SearchInputProps {
6
+ value: string;
7
+ onChange: (value: string) => void;
8
+ placeholder?: string;
9
+ }
10
+
11
+ const CustomSearch = ({
12
+ value = "",
13
+ onChange,
14
+ placeholder = "Search...",
15
+ }: SearchInputProps) => {
16
+ const [search, setSearch] = useState(value);
17
+
18
+ const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
19
+ const val = e.target.value;
20
+ setSearch(val);
21
+ onChange?.(val);
22
+ };
23
+
24
+ return (
25
+ <TextField
26
+ fullWidth
27
+ size="small"
28
+ value={search}
29
+ onChange={handleChange}
30
+ placeholder={placeholder}
31
+ InputProps={{
32
+ startAdornment: (
33
+ <InputAdornment position="start">
34
+ <SearchIcon sx={{ color: "#888888", fontSize: "20px" }} />
35
+ </InputAdornment>
36
+ ),
37
+ }}
38
+ sx={{
39
+ mt: 2,
40
+ "& .MuiOutlinedInput-root": {
41
+ borderRadius: "6px",
42
+ fontSize: "14px",
43
+ bgcolor: "#fafafa",
44
+ "& fieldset": {
45
+ borderColor: "#c1c1c1",
46
+ },
47
+ "&.Mui-focused fieldset": {
48
+ borderColor: "#7A5AF8",
49
+ },
50
+ },
51
+ }}
52
+ />
53
+ );
54
+ };
55
+
56
+ export default CustomSearch;
@@ -0,0 +1,29 @@
1
+ import * as React from "react";
2
+ import Box from "@mui/material/Box";
3
+
4
+ interface TabPanelProps {
5
+ children?: React.ReactNode;
6
+ index: number;
7
+ value: number;
8
+ }
9
+
10
+ const CustomTabPanel = ({
11
+ children,
12
+ value,
13
+ index,
14
+ ...other
15
+ }: TabPanelProps) => {
16
+ return (
17
+ <div
18
+ role="tabpanel"
19
+ hidden={value !== index}
20
+ id={`simple-tabpanel-${index}`}
21
+ aria-labelledby={`simple-tab-${index}`}
22
+ {...other}
23
+ >
24
+ {value === index && <Box sx={{ p: 3 }}>{children}</Box>}
25
+ </div>
26
+ );
27
+ };
28
+
29
+ export default CustomTabPanel;
@@ -0,0 +1,85 @@
1
+ import React, { useState } from "react";
2
+ import { Tabs, Tab, TabsProps, Box } from "@mui/material";
3
+ import { CheckBox, CrossBox } from "../../../../assets/svg";
4
+
5
+ export interface TabItem {
6
+ label: string;
7
+ }
8
+
9
+ interface StyledTabsProps extends TabsProps {
10
+ tabItems: TabItem[];
11
+ activeFilterIndex: number;
12
+ }
13
+
14
+ const CustomTabs = ({
15
+ value,
16
+ onChange,
17
+ tabItems,
18
+ activeFilterIndex = -1,
19
+ ...tabsProps
20
+ }: StyledTabsProps) => {
21
+ const [hoveredTab, setHoveredTab] = useState<number | null>(null);
22
+
23
+ const handleCrossClick = (idx: number) => (e: React.MouseEvent) => {
24
+ e.stopPropagation();
25
+ };
26
+
27
+ return (
28
+ <Tabs
29
+ value={value}
30
+ onChange={onChange}
31
+ variant="fullWidth"
32
+ sx={{
33
+ px: "12px",
34
+ borderBottom: `1px solid #ccc`,
35
+ "& .MuiTabs-indicator": {
36
+ backgroundColor: "black",
37
+ },
38
+ }}
39
+ {...tabsProps}
40
+ >
41
+ {tabItems.map((tab, idx) => {
42
+ const isActive = activeFilterIndex === idx;
43
+ const isHovered = hoveredTab === idx;
44
+
45
+ return (
46
+ <Tab
47
+ key={idx}
48
+ label={
49
+ <Box sx={{ display: "flex", alignItems: "center", gap: 0.5 }}>
50
+ <span>{tab.label}</span>
51
+ {isActive && (
52
+ <Box
53
+ onMouseEnter={() => setHoveredTab(idx)}
54
+ onMouseLeave={() => setHoveredTab(null)}
55
+ sx={{
56
+ display: "flex",
57
+ alignItems: "center",
58
+ cursor: isHovered ? "pointer" : "default",
59
+ }}
60
+ onClick={isHovered ? handleCrossClick(idx) : undefined}
61
+ >
62
+ {isHovered ? <CrossBox /> : <CheckBox />}
63
+ </Box>
64
+ )}
65
+ </Box>
66
+ }
67
+ sx={{
68
+ fontSize: "14px",
69
+ textTransform: "capitalize",
70
+ color: "#888888",
71
+ fontWeight: "normal",
72
+ whiteSpace: "nowrap",
73
+ "&.Mui-selected": {
74
+ color: "black",
75
+ fontWeight: "bold",
76
+ },
77
+ }}
78
+ />
79
+ );
80
+ })}
81
+ </Tabs>
82
+ );
83
+ };
84
+
85
+ export default CustomTabs;
@@ -0,0 +1,261 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import { Box, Drawer, IconButton, Typography } from "@mui/material";
3
+ import CloseIcon from "@mui/icons-material/Close";
4
+ import { FilterDrawerProps, UpdatedFilterStateProps } from "../../types/filter";
5
+
6
+ import ConfirmModal, { InputField } from "../common/confirm-modal";
7
+ import CustomTabPanel from "./components/tabs/custom-tab-panel";
8
+ import CustomTabs, { TabItem } from "./components/tabs/index";
9
+ import MainFilter from "./components/main-filter";
10
+ import SavedFilter from "./components/saved-filter";
11
+ import AttributesFilter from "./components/attributes-filter";
12
+
13
+ const FilterDrawer = ({
14
+ open,
15
+ onClose,
16
+ columnsData,
17
+ tableStates,
18
+ onDeleteFilter,
19
+ onSaveFilter,
20
+ onUpdateFilter,
21
+ dropdownData,
22
+ }: FilterDrawerProps) => {
23
+ const [tabValue, setTabValue] = useState(0);
24
+ const [editMode, setEditMode] = useState(false);
25
+ const [selectedFilters, setSelectedFilters] = useState<
26
+ UpdatedFilterStateProps[]
27
+ >([]);
28
+
29
+ // remove this
30
+ const [saveFilterModalOpen, setSaveFilterModalOpen] = useState(false);
31
+ const [deleteFilterModalOpen, setDeleteFilterModalOpen] = useState(false);
32
+
33
+ const [searchTerm, setSearchTerm] = useState<string>("");
34
+
35
+ const { filters, filterToDelete, filterMaster } = tableStates;
36
+
37
+ const filterNameInput: InputField = {
38
+ label: "Filter Name",
39
+ placeholder: 'e.g., "Website Leads - This Week"',
40
+ required: true,
41
+ type: "text",
42
+ };
43
+
44
+ useEffect(() => {
45
+ if (!columnsData || !columnsData.column_list) {
46
+ setSelectedFilters([]);
47
+ return;
48
+ }
49
+
50
+ const updated = filters?.map((filter) => {
51
+ const matchingColumn = columnsData.column_list.find(
52
+ (column) => column.attribute_key === filter.filter_attribute
53
+ );
54
+ const matchingDropdownList =
55
+ columnsData.operation_list[matchingColumn?.data_type || "text"];
56
+
57
+ return {
58
+ ...filter,
59
+ id: matchingColumn?.id ?? "",
60
+ name: matchingColumn?.name,
61
+ data_type: matchingColumn?.data_type,
62
+ dropdown_list: matchingDropdownList,
63
+ };
64
+ });
65
+
66
+ setSelectedFilters(updated || []);
67
+ }, [filters, columnsData, tabValue]);
68
+
69
+ const handleTabChange = (event: React.SyntheticEvent, newValue: number) => {
70
+ setTabValue(newValue);
71
+ if (newValue !== 1) {
72
+ setEditMode(false);
73
+ setSelectedFilters([]);
74
+ }
75
+ };
76
+
77
+ //FOR TABS
78
+ const tabItems: TabItem[] = [
79
+ { label: "Filter" },
80
+ { label: "Saved Filter" },
81
+ { label: "Attributes" },
82
+ ];
83
+
84
+ return (
85
+ <Drawer
86
+ anchor="right"
87
+ open={open}
88
+ onClose={onClose}
89
+ ModalProps={{
90
+ keepMounted: true,
91
+ }}
92
+ sx={{
93
+ "& .MuiPaper-root": {
94
+ overflowY: "auto",
95
+ },
96
+ }}
97
+ >
98
+ <Box sx={{ width: "400px" }}>
99
+ <Box
100
+ sx={{
101
+ display: "flex",
102
+ alignItems: "center",
103
+ justifyContent: "space-between",
104
+ bgcolor: "#EEEEEE",
105
+ height: "50px",
106
+ px: 2,
107
+ borderBottom: "1px solid #ccc",
108
+ mx: "auto",
109
+ }}
110
+ >
111
+ <Typography variant="h6" fontWeight="bold" fontSize="18px">
112
+ Filter
113
+ </Typography>
114
+ <IconButton
115
+ onClick={(e) => {
116
+ e.stopPropagation();
117
+ onClose && onClose();
118
+ }}
119
+ aria-label="close"
120
+ >
121
+ <CloseIcon fontSize="small" />
122
+ </IconButton>
123
+ </Box>
124
+
125
+ <CustomTabs
126
+ value={tabValue}
127
+ onChange={handleTabChange}
128
+ tabItems={tabItems}
129
+ activeFilterIndex={filterMaster?.activeFilterTabIndex ?? 0}
130
+ />
131
+
132
+ <Box>
133
+ <CustomTabPanel value={tabValue} index={0}>
134
+ {tabValue === 0 && (
135
+ <MainFilter
136
+ columnsData={columnsData}
137
+ tableStates={tableStates}
138
+ selectedFilters={selectedFilters}
139
+ setSelectedFilters={setSelectedFilters}
140
+ setSavedFilterModalOpen={setSaveFilterModalOpen}
141
+ dropdownData={dropdownData}
142
+ />
143
+ )}
144
+ </CustomTabPanel>
145
+
146
+ <CustomTabPanel value={tabValue} index={1}>
147
+ {tabValue === 1 && (
148
+ <SavedFilter
149
+ columnsData={columnsData}
150
+ tableStates={tableStates}
151
+ selectedFilters={selectedFilters}
152
+ setSelectedFilters={setSelectedFilters}
153
+ editMode={editMode}
154
+ setEditMode={setEditMode}
155
+ setDeleteFilterModalOpen={setDeleteFilterModalOpen}
156
+ setSavedFilterModalOpen={setSaveFilterModalOpen}
157
+ dropdownData={dropdownData}
158
+ tabValue={tabValue}
159
+ />
160
+ )}
161
+ </CustomTabPanel>
162
+
163
+ <CustomTabPanel value={tabValue} index={2}>
164
+ {tabValue === 2 && (
165
+ <AttributesFilter
166
+ columnsData={columnsData}
167
+ tableStates={tableStates}
168
+ dropdownData={dropdownData}
169
+ searchTerm={searchTerm}
170
+ setSearchTerm={setSearchTerm}
171
+ tabValue={tabValue}
172
+ />
173
+ )}
174
+ </CustomTabPanel>
175
+ </Box>
176
+
177
+ <ConfirmModal
178
+ open={saveFilterModalOpen}
179
+ onClose={() => setSaveFilterModalOpen(false)}
180
+ title={editMode ? "Replace Existing Filter ?" : "Save Filter"}
181
+ description={
182
+ editMode
183
+ ? "You already have a filter applied. Applying a new filter will replace the current one. Do you want to continue?"
184
+ : "Give a name to this filter so you can easily reuse it later."
185
+ }
186
+ buttons={[
187
+ {
188
+ label: "Cancel",
189
+ onClick: () => {
190
+ setSaveFilterModalOpen(false);
191
+ },
192
+ variant: "outlined",
193
+ color: "primary",
194
+ sx: {
195
+ color: "#7A5AF8",
196
+ border: `1px solid #7A5AF8`,
197
+ },
198
+ },
199
+ {
200
+ label: editMode ? "Replace Filter" : "Save",
201
+ onClick: (inputValue) => {
202
+ if (editMode) {
203
+ onUpdateFilter && onUpdateFilter(inputValue || "");
204
+ setSaveFilterModalOpen(false);
205
+ setEditMode(false);
206
+ return;
207
+ }
208
+
209
+ onSaveFilter && onSaveFilter(inputValue || "");
210
+ setSaveFilterModalOpen(false);
211
+
212
+ setTabValue(1);
213
+ },
214
+ variant: "contained",
215
+ color: "primary",
216
+ sx: {
217
+ color: "white",
218
+ backgroundColor: editMode ? "#7A5AF8" : "#7A5AF8",
219
+ },
220
+ },
221
+ ]}
222
+ input={editMode ? undefined : filterNameInput}
223
+ />
224
+
225
+ <ConfirmModal
226
+ open={deleteFilterModalOpen}
227
+ onClose={() => setDeleteFilterModalOpen(false)}
228
+ title="Delete Saved Filter?"
229
+ description={`You're about to delete the saved filter: "${
230
+ filterToDelete?.label || "[Filter Name]"
231
+ }". This action cannot be undone. Are you sure you want to continue?`}
232
+ buttons={[
233
+ {
234
+ label: "Cancel",
235
+ onClick: () => {
236
+ setDeleteFilterModalOpen(false);
237
+ },
238
+ variant: "outlined",
239
+ color: "primary",
240
+ sx: { color: "#7A5AF8", border: `1px solid #7A5AF8` },
241
+ },
242
+ {
243
+ label: "Delete",
244
+ onClick: () => {
245
+ onDeleteFilter && onDeleteFilter();
246
+
247
+ setDeleteFilterModalOpen(false);
248
+ setEditMode && setEditMode(false);
249
+ },
250
+ variant: "contained",
251
+ sx: { color: "white", backgroundColor: "#f63d68" },
252
+ },
253
+ ]}
254
+ maxWidth="xs"
255
+ />
256
+ </Box>
257
+ </Drawer>
258
+ );
259
+ };
260
+
261
+ export default FilterDrawer;
@@ -32,8 +32,6 @@ function TableWrapper<T>({
32
32
  loadingOptions = { isLoading: false },
33
33
  customRenderFn = {},
34
34
  // styleOptions,
35
- // searchValue, // 👈 ADD
36
- // onSearchChange, // 👈 ADD
37
35
  shouldHideColumn,
38
36
  }: CraftTableProps<T>) {
39
37
  if (!Array.isArray(data)) {
@@ -118,13 +116,11 @@ function TableWrapper<T>({
118
116
  const craftTopbarOptions: TopbarOptionsProps = {
119
117
  showColumnToggle: true,
120
118
  showCompactTableToggle: true,
121
- showFullscreenToggle: true,
122
119
  showChangeLayoutToggle: true,
123
120
  viewMoreToggle: true,
124
- showAddNewButton: true,
125
121
  showSearch: true,
126
- showFilter: true,
127
- showCustomizationToggle: true,
122
+ showSortingToggle: true,
123
+ showFilterToggle: true,
128
124
  tableStates,
129
125
 
130
126
  // Add other conditions above topbarOptions
@@ -262,6 +258,7 @@ function TableWrapper<T>({
262
258
  topbarOptions={craftTopbarOptions}
263
259
  isCompactTable={isCompactTable}
264
260
  setIsCompactTable={setIsCompactTable}
261
+ isFullscreen={isFullscreen}
265
262
  fullscreenToggle={handleFullscreenToggle}
266
263
  paginationComponent={
267
264
  craftPaginationOptions?.showPagination === true &&
@@ -31,6 +31,10 @@
31
31
  overflow-x: auto;
32
32
  max-height: calc(100vh - 110px);
33
33
 
34
+ &.is-fullscreen {
35
+ max-height: calc(100vh - 56px);
36
+ }
37
+
34
38
  .ts__table.ts--striped > .ts__body > .ts__body__tr:nth-of-type(odd) {
35
39
  background-color: var(--grey-200);
36
40
  }
@@ -0,0 +1,49 @@
1
+ import { useState } from "react";
2
+ import axios from "axios";
3
+ import Button from "@mui/material/Button";
4
+
5
+ const LoginButton = () => {
6
+ const [loading, setLoading] = useState(false);
7
+
8
+ const handleLogin = async () => {
9
+ setLoading(true);
10
+ try {
11
+ const response = await axios.post(
12
+ "http://13.200.182.92:9091/api/auth/login",
13
+ {
14
+ email_id: "admin@rezolut.in",
15
+ password: "Admin@123",
16
+ }
17
+ );
18
+
19
+ const token = response.data.accessToken;
20
+
21
+ if (token) {
22
+ localStorage.setItem("authToken", token);
23
+ alert("Login successful");
24
+ window.location.reload(); // reload app to re-trigger axios with token
25
+ } else {
26
+ alert("Token not found in response.");
27
+ }
28
+ } catch (error) {
29
+ console.error("Login failed:", error);
30
+ alert("Login failed. Check console for details.");
31
+ } finally {
32
+ setLoading(false);
33
+ }
34
+ };
35
+
36
+ return (
37
+ <Button
38
+ onClick={handleLogin}
39
+ disabled={loading}
40
+ variant="outlined"
41
+ size="small"
42
+ color="primary"
43
+ >
44
+ {loading ? "Logging in..." : "Login"}
45
+ </Button>
46
+ );
47
+ };
48
+
49
+ export default LoginButton;
@@ -97,12 +97,14 @@ function TableBody<T>({
97
97
  return (
98
98
  <React.Fragment key={row.id}>
99
99
  {renderedRow}
100
- <tr>
101
- {/* <td colSpan={table.getAllLeafColumns().length}>//commented out to remove extra line on opening of nested row
100
+ {NestedComponent && (
101
+ <tr>
102
+ {/* <td colSpan={table.getAllLeafColumns().length}>//commented out to remove extra line on opening of
102
103
  {NestedComponent && <NestedComponent {...{ row }} />}
103
104
  </td> */}
104
- {NestedComponent && <NestedComponent {...{ row }} />}
105
- </tr>
105
+ {<NestedComponent {...{ row }} />}
106
+ </tr>
107
+ )}
106
108
  </React.Fragment>
107
109
  );
108
110
  } else {