rez-table-listing-mui 1.0.49 → 1.2.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 (32) hide show
  1. package/dist/index.d.ts +5 -1
  2. package/dist/index.js +1 -1
  3. package/dist/index.mjs +1 -1
  4. package/package.json +1 -1
  5. package/src/App.tsx +80 -35
  6. package/src/assets/svg.tsx +5 -5
  7. package/src/components/filter/components/attributes-filter.tsx +78 -52
  8. package/src/components/filter/components/forms/components/Date.tsx +175 -66
  9. package/src/components/filter/components/forms/components/Dropdown.tsx +36 -3
  10. package/src/components/filter/components/forms/components/Filter-criteria.tsx +1 -1
  11. package/src/components/filter/components/forms/components/Multi-Select.tsx +62 -34
  12. package/src/components/filter/components/forms/index.tsx +20 -2
  13. package/src/components/filter/components/saved-filter.tsx +63 -9
  14. package/src/components/filter/index.tsx +3 -3
  15. package/src/components/filter/style.ts +1 -1
  16. package/src/components/index-table.tsx +42 -40
  17. package/src/components/index.scss +1 -1
  18. package/src/components/login/index.tsx +1 -1
  19. package/src/components/table-settings/common/info-alert.tsx +37 -0
  20. package/src/components/table-settings/common/listing-values.tsx +63 -48
  21. package/src/components/table-settings/components/column.tsx +210 -170
  22. package/src/components/table-settings/components/quick-tab.tsx +277 -153
  23. package/src/components/table-settings/components/sorting.tsx +135 -109
  24. package/src/components/table-settings/components/toggle-button-switch.tsx +2 -2
  25. package/src/components/table-settings/index.tsx +3 -5
  26. package/src/components/table-settings/style.ts +1 -0
  27. package/src/components/topbar/index.tsx +3 -1
  28. package/src/libs/hooks/useEntityTableAPI.tsx +1 -16
  29. package/src/libs/utils/apiColumn.ts +1 -11
  30. package/src/libs/utils/common.ts +4 -3
  31. package/src/types/filter-settings.ts +11 -0
  32. package/src/types/filter.ts +1 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rez-table-listing-mui",
3
- "version": "1.0.49",
3
+ "version": "1.2.1",
4
4
  "type": "module",
5
5
  "description": "A rez table listing component built on TanStack Table",
6
6
  "main": "dist/index.js",
package/src/App.tsx CHANGED
@@ -23,7 +23,9 @@ import { CraftTableFilter } from ".";
23
23
  import { useCraftTableFilterSettings } from "./libs/hooks/useCraftTableFilterSettings";
24
24
  import { QuickFilterSettings } from "./components/table-settings";
25
25
  import { SettingsDataProps } from "./types/filter-settings";
26
- // import { ENTITY_TYPE } from "./libs/utils/common";
26
+ import { FilterMasterStateProps } from "./types/filter";
27
+ import { ColumnDef } from "@tanstack/react-table";
28
+ import { ENTITY_TYPE } from "./libs/utils/common";
27
29
 
28
30
  function App() {
29
31
  // const [mockLoading, setMockLoading] = useState<boolean>(true);
@@ -31,21 +33,21 @@ function App() {
31
33
  const [columns, setColumns] = useState<any[]>([]);
32
34
  const [searchTerm, setSearchTerm] = useState("");
33
35
  // const [data, setData] = useState<Person[]>(() => makeData(50, 3, 2));
34
- // const [entity_type] = useState(ENTITY_TYPE); //OR UPR AYR
35
36
 
36
37
  const [selectedTab, setSelectedTab] = useState("ALL");
37
38
 
38
39
  const tableStates = useCraftTable();
39
40
  const filterSettingStates = useCraftTableFilterSettings();
40
41
 
41
- const { filters, setFilters, filterMaster, filterToDelete } = tableStates;
42
+ const { filters, setFilters, filterMaster, setFilterMaster, filterToDelete } =
43
+ tableStates;
42
44
 
43
45
  const { showListViewSettings, setShowListViewSettings, setSettingsData } =
44
46
  filterSettingStates;
45
47
 
46
48
  const { defaultColumns } = useDefaultColumns();
47
49
 
48
- const { metaQuery } = useFetchData("AYR");
50
+ const { metaQuery } = useFetchData(ENTITY_TYPE);
49
51
  const { detailsQuery } = useDetailsQueryAPI(
50
52
  filterMaster?.saved_filters?.selectedId
51
53
  ? filterMaster?.saved_filters?.selectedId
@@ -55,16 +57,16 @@ function App() {
55
57
  const { savedMutation } = useSavedFilterAPI(); //API CALL FOR SAVED FILTER
56
58
  const { deleteMutation } = useDeleteFilterAPI(); //API FOR DELETING FILTER
57
59
  const { updateMutation } = useUpdateFilterAPI(); //API FOR UPDATE FILTER
58
- const { saveSettingsDataMutation } = useSaveSettingsDataAPI("AYR");
60
+ const { saveSettingsDataMutation } = useSaveSettingsDataAPI(ENTITY_TYPE);
59
61
  const { dropdownData } = useCommonDropdownAPI(metaQuery.data);
60
62
  const { settingsTabDropdownData, settingsTabDropdownPending } =
61
63
  useSettingsDropDownAPI({
62
- entity_type: "AYR",
64
+ entity_type: ENTITY_TYPE,
63
65
  column: filterSettingStates?.quickTabStates?.attribute,
64
66
  sort_by: filterSettingStates?.quickTabStates?.sorting,
65
67
  });
66
68
 
67
- const { getSettingsAPIData } = useGetSettingsDataAPI("AYR");
69
+ const { getSettingsAPIData } = useGetSettingsDataAPI(ENTITY_TYPE);
68
70
 
69
71
  useEffect(() => {
70
72
  // setTimeout(() => {
@@ -73,10 +75,24 @@ function App() {
73
75
 
74
76
  const fetchMeta = async () => {
75
77
  try {
76
- const { res: allColumns } = await entityTableMetaMaster("AYR");
78
+ const { res: allColumns } = await entityTableMetaMaster(ENTITY_TYPE);
77
79
 
78
80
  const savedColumnSettings = filterSettingStates.settingsData?.column;
79
81
 
82
+ const getOrderedColumns = (
83
+ showList: { value: string }[],
84
+ filteredColumns: any[]
85
+ ) => {
86
+ // Build ordered columns using showList and filteredColumns
87
+ return showList
88
+ ?.map((showItem) => {
89
+ return filteredColumns.find(
90
+ (col) => col?.accessorKey === showItem?.value
91
+ );
92
+ })
93
+ ?.filter((col): col is ColumnDef<any> => col !== undefined); // Ensure non-undefined columns are returned
94
+ };
95
+
80
96
  if (
81
97
  savedColumnSettings &&
82
98
  !savedColumnSettings.isDefault &&
@@ -94,19 +110,11 @@ function App() {
94
110
 
95
111
  // First, filter columns based on visibleColumns
96
112
  const filteredColumns = allColumns.filter((col: any) =>
97
- visibleColumns.has(col.accessorKey)
113
+ visibleColumns.has(col?.accessorKey)
114
+ );
115
+ setColumns(
116
+ getOrderedColumns(activeTabSettings.show_list, filteredColumns)
98
117
  );
99
-
100
- // Then, order the filtered columns based on the sequence in show_list
101
- const orderedColumns = activeTabSettings.show_list
102
- .map((showItem) =>
103
- filteredColumns.find(
104
- (col: any) => col.accessorKey === showItem.value
105
- )
106
- )
107
- .filter((col: any) => col !== undefined); // To ensure we filter out any undefined columns
108
-
109
- setColumns(orderedColumns);
110
118
  } else {
111
119
  // Fallback if no specific settings for the active tab are found
112
120
  setColumns(allColumns);
@@ -117,9 +125,12 @@ function App() {
117
125
  savedColumnSettings.show_list.map((c) => c.value)
118
126
  );
119
127
  const filtered = allColumns.filter((col: any) =>
120
- visibleColumns.has(col.accessorKey)
128
+ visibleColumns.has(col?.accessorKey)
129
+ );
130
+
131
+ setColumns(
132
+ getOrderedColumns(savedColumnSettings.show_list, filtered)
121
133
  );
122
- setColumns(filtered);
123
134
  } else {
124
135
  // No settings found, use all columns
125
136
  setColumns(allColumns);
@@ -130,7 +141,7 @@ function App() {
130
141
  };
131
142
 
132
143
  fetchMeta();
133
- }, [filterSettingStates.settingsData, selectedTab]);
144
+ }, [selectedTab]);
134
145
 
135
146
  useEffect(() => {
136
147
  setFilters(detailsQuery.data ?? []);
@@ -146,10 +157,11 @@ function App() {
146
157
  const { tableData } = useEntityTableAPI({
147
158
  page: 0,
148
159
  size: 50,
149
- entity_type: "AYR",
160
+ entity_type: ENTITY_TYPE,
150
161
  tabs: {
151
- columnName: "status",
152
- sortBy: "ASC",
162
+ columnName:
163
+ getSettingsAPIData?.layout_json?.quick_tab?.attribute || "status",
164
+ sortBy: getSettingsAPIData?.layout_json?.quick_tab?.sorting || "ASC",
153
165
  value:
154
166
  selectedTab.toLowerCase() === "all" ? "" : selectedTab.toLowerCase(),
155
167
  },
@@ -169,6 +181,27 @@ function App() {
169
181
  );
170
182
  const tabsData = tableData?.entity_tabs;
171
183
 
184
+ // Auto-switch tab if the selected tab is removed
185
+ useEffect(() => {
186
+ if (
187
+ tabsData &&
188
+ tabsData.length > 0 &&
189
+ !tabsData.some(
190
+ (tab) => tab.tab_value?.toLowerCase() === selectedTab.toLowerCase()
191
+ )
192
+ ) {
193
+ // Try to select 'ALL' if it exists
194
+ const allTab = tabsData.find(
195
+ (tab) => tab.tab_value?.toLowerCase() === "all"
196
+ );
197
+ if (allTab) {
198
+ setSelectedTab(allTab.tab_value || "ALL");
199
+ } else {
200
+ setSelectedTab(tabsData[0].tab_value || "ALL");
201
+ }
202
+ }
203
+ }, [tabsData, selectedTab]);
204
+
172
205
  const totalCount = useMemo(() => {
173
206
  return Number(
174
207
  tableData?.entity_tabs?.find((tab) => {
@@ -225,7 +258,7 @@ function App() {
225
258
  const payload = {
226
259
  name,
227
260
  is_default: false,
228
- mapped_entity_type: "AYR", // For that entity type
261
+ mapped_entity_type: ENTITY_TYPE, // For that entity type
229
262
  status: "ACTIVE",
230
263
  entity_type: "SFM", // FIXED entity type
231
264
  filterDetails: quickFilter,
@@ -234,10 +267,22 @@ function App() {
234
267
  savedMutation.mutate(
235
268
  { entity_type, payload },
236
269
  {
237
- onSuccess: () => {},
238
- onError: (error: any) => {
239
- const msg = error?.response?.data?.message;
240
- console.log("Error in saving filter", msg, error);
270
+ onSuccess: (response) => {
271
+ const newFilterId = response?.id;
272
+ if (newFilterId) {
273
+ setFilterMaster(
274
+ (prev) =>
275
+ ({
276
+ ...prev,
277
+ saved_filters: {
278
+ ...prev?.saved_filters,
279
+ selectedId: newFilterId.toString(),
280
+ selectedName: name,
281
+ },
282
+ activeFilterTabIndex: 1,
283
+ } as FilterMasterStateProps)
284
+ );
285
+ }
241
286
  },
242
287
  }
243
288
  );
@@ -249,7 +294,7 @@ function App() {
249
294
  name: filterToDelete?.label,
250
295
  id: filterToDelete?.value,
251
296
  is_default: false,
252
- mapped_entity_type: "AYR",
297
+ mapped_entity_type: ENTITY_TYPE,
253
298
  status: "INACTIVE",
254
299
  entity_type: "SFM",
255
300
  };
@@ -269,7 +314,7 @@ function App() {
269
314
  name: filterMaster?.saved_filters?.selectedName, // Name of the filter
270
315
  is_default: false,
271
316
  id: filterMaster?.saved_filters?.selectedId,
272
- mapped_entity_type: "AYR",
317
+ mapped_entity_type: ENTITY_TYPE,
273
318
  status: "ACTIVE",
274
319
  entity_type: "SFM",
275
320
  filterDetails: quickFilter,
@@ -281,7 +326,7 @@ function App() {
281
326
  const handleSaveSettingsData = (settingsData: SettingsDataProps) => {
282
327
  const payload = {
283
328
  entity_type: "LAP",
284
- mapped_entity_type: "AYR",
329
+ mapped_entity_type: ENTITY_TYPE,
285
330
  layout_json: settingsData,
286
331
  };
287
332
 
@@ -344,7 +389,7 @@ function App() {
344
389
  showIcon: true,
345
390
  onClick: () => setShowListViewSettings(!showListViewSettings),
346
391
  }}
347
- activeTab={selectedTab}
392
+ activeTab={selectedTab?.toUpperCase()}
348
393
  tableStates={tableStates}
349
394
  tabsData={tabsData}
350
395
  onClick={(state) => {
@@ -172,7 +172,7 @@ export const ArrowDownUp = () => (
172
172
  );
173
173
  export const EditIcon = () => (
174
174
  <svg
175
- width="12"
175
+ width="18"
176
176
  height="12"
177
177
  viewBox="0 0 12 12"
178
178
  fill="none"
@@ -181,14 +181,14 @@ export const EditIcon = () => (
181
181
  <path
182
182
  d="M1.33331 10.6663H2.17431L8.99865 3.84201L8.15765 3.00101L1.33331 9.82534V10.6663ZM0.93598 11.6663C0.765202 11.6663 0.622091 11.6086 0.506646 11.493C0.391091 11.3776 0.333313 11.2345 0.333313 11.0637V9.90867C0.333313 9.74612 0.364535 9.59118 0.42698 9.44384C0.489313 9.29651 0.575202 9.16812 0.684646 9.05868L9.12698 0.620174C9.22776 0.528619 9.33904 0.457897 9.46081 0.408008C9.5827 0.358008 9.71048 0.333008 9.84415 0.333008C9.97781 0.333008 10.1073 0.35673 10.2325 0.404175C10.3578 0.451619 10.4688 0.527063 10.5653 0.630507L11.3795 1.45484C11.4829 1.5514 11.5566 1.66251 11.6006 1.78817C11.6446 1.91384 11.6666 2.03951 11.6666 2.16517C11.6666 2.29929 11.6438 2.42723 11.598 2.54901C11.5522 2.6709 11.4794 2.78223 11.3795 2.88301L2.94098 11.315C2.83154 11.4245 2.70315 11.5103 2.55581 11.5727C2.40848 11.6351 2.25354 11.6663 2.09098 11.6663H0.93598ZM8.57081 3.42884L8.15765 3.00101L8.99865 3.84201L8.57081 3.42884Z"
183
183
  fill="#0E0C0B"
184
- fill-opacity="0.4"
184
+ fillOpacity={0.4}
185
185
  />
186
186
  </svg>
187
187
  );
188
188
 
189
189
  export const DeleteIcon = () => (
190
190
  <svg
191
- width="20"
191
+ width="18"
192
192
  height="20"
193
193
  viewBox="0 0 10 12"
194
194
  fill="none"
@@ -664,7 +664,7 @@ export const SortingIcon = () => {
664
664
  );
665
665
  };
666
666
 
667
- export const FilterationIcon = () => {
667
+ export const FilterationIcon = ({ color = "#1C1B1F" }) => {
668
668
  return (
669
669
  <svg
670
670
  width="20"
@@ -687,7 +687,7 @@ export const FilterationIcon = () => {
687
687
  <g mask="url(#mask0_811_12698)">
688
688
  <path
689
689
  d="M8.33333 15V13.3333H11.6667V15H8.33333ZM5 10.8333V9.16667H15V10.8333H5ZM2.5 6.66667V5H17.5V6.66667H2.5Z"
690
- fill="#1C1B1F"
690
+ fill={color}
691
691
  />
692
692
  </g>
693
693
  </svg>
@@ -4,7 +4,6 @@ import {
4
4
  FormControlLabel,
5
5
  MenuItem,
6
6
  Radio,
7
- RadioGroup,
8
7
  Select,
9
8
  SelectChangeEvent,
10
9
  } from "@mui/material";
@@ -27,21 +26,23 @@ const AttributesFilter = ({
27
26
 
28
27
  const selectedAttribute = filterMaster?.attributes?.selected;
29
28
 
30
- // Get the current filter value to set radio button state
29
+ // Get the current filter value(s) to determine selected options
31
30
  const currentFilterValue = useMemo(() => {
32
- if (!selectedAttribute) return "";
31
+ if (!selectedAttribute) return [];
33
32
 
34
33
  const matchingColumn = columnsData.column_list.find(
35
34
  (column) => column.datasource_list === selectedAttribute
36
35
  );
37
36
 
38
- if (!matchingColumn) return "";
37
+ if (!matchingColumn) return [];
39
38
 
40
39
  const existingFilter = filters.find(
41
40
  (filter) => filter.filter_attribute === matchingColumn.attribute_key
42
41
  );
43
42
 
44
- return existingFilter?.filter_value || "";
43
+ return Array.isArray(existingFilter?.filter_value)
44
+ ? existingFilter?.filter_value
45
+ : [];
45
46
  }, [selectedAttribute, filters, columnsData]);
46
47
 
47
48
  const handleSelectChange = (event: SelectChangeEvent) => {
@@ -54,47 +55,69 @@ const AttributesFilter = ({
54
55
  attributes: {
55
56
  ...prev?.attributes,
56
57
  selected: attributeKey,
57
- radio: "", // Reset radio selection when changing attribute
58
+ radio: [],
58
59
  },
59
60
  } as FilterMasterStateProps)
60
61
  );
61
62
  };
62
63
 
63
- const handleRadioChange = (event: React.ChangeEvent<HTMLInputElement>) => {
64
- event.preventDefault();
64
+ const handleMultiRadioToggle = (value: string) => {
65
+ const selectedAttr = filterMaster?.attributes.selected;
66
+ if (!selectedAttr) return;
65
67
 
66
- const selectedValue = event.target.value;
68
+ const matchingColumn = columnsData.column_list.find(
69
+ (column) => column.datasource_list === selectedAttr
70
+ );
71
+ if (!matchingColumn) return;
67
72
 
68
- setFilterMaster(
69
- (prev) =>
70
- ({
71
- ...prev,
72
- attributes: {
73
- ...prev?.attributes,
74
- radio: selectedValue,
75
- },
76
- activeFilterTabIndex: tabValue,
77
- } as FilterMasterStateProps)
73
+ const existingFilter = filters.find(
74
+ (f) => f.filter_attribute === matchingColumn.attribute_key
78
75
  );
79
76
 
80
- const selectedAttribute = filterMaster?.attributes.selected;
81
- if (selectedAttribute) {
82
- const matchingColumn = columnsData.column_list.find(
83
- (column) => column.datasource_list === selectedAttribute
77
+ const currentValues: string[] = Array.isArray(existingFilter?.filter_value)
78
+ ? existingFilter.filter_value
79
+ : [];
80
+
81
+ const isAlreadySelected = currentValues.includes(value);
82
+
83
+ const updatedValues = isAlreadySelected
84
+ ? currentValues.filter((v) => v !== value)
85
+ : [...currentValues, value];
86
+
87
+ const defaultOperator =
88
+ columnsData.operation_list[matchingColumn.data_type]?.[0]?.value || "in";
89
+
90
+ const newFilter = {
91
+ filter_attribute: matchingColumn.attribute_key,
92
+ filter_operator: defaultOperator,
93
+ filter_value: updatedValues,
94
+ };
95
+
96
+ setFilters((prevFilters) => {
97
+ const exists = prevFilters.some(
98
+ (f) => f.filter_attribute === matchingColumn.attribute_key
84
99
  );
85
- if (matchingColumn) {
86
- const defaultOperator =
87
- columnsData.operation_list[matchingColumn.data_type]?.[0]?.value ||
88
- "equals";
89
- const newFilter = {
90
- filter_attribute: matchingColumn.attribute_key,
91
- filter_operator: defaultOperator,
92
- filter_value: selectedValue,
93
- };
94
-
95
- setFilters([newFilter]);
100
+ if (exists) {
101
+ return prevFilters.map((f) =>
102
+ f.filter_attribute === matchingColumn.attribute_key ? newFilter : f
103
+ );
104
+ } else {
105
+ return [...prevFilters, newFilter];
96
106
  }
97
- }
107
+ });
108
+
109
+ setFilterMaster((prev) => {
110
+ if (!prev || !prev.attributes.selected) return prev;
111
+
112
+ return {
113
+ ...prev,
114
+ attributes: {
115
+ ...prev.attributes,
116
+ radio: updatedValues,
117
+ },
118
+ activeFilterTabIndex: tabValue as number,
119
+ };
120
+ });
98
121
  };
99
122
 
100
123
  const selectedAttributeOptions = useMemo(() => {
@@ -170,27 +193,30 @@ const AttributesFilter = ({
170
193
  {dropdownData && (
171
194
  <Box sx={{ mt: 2 }}>
172
195
  <FormControl>
173
- <RadioGroup
174
- onChange={handleRadioChange}
175
- value={currentFilterValue} // Set the value from current filter
176
- >
177
- {selectedAttributeOptions
178
- ?.filter((option) => {
179
- if (!searchTerm) return true;
180
-
181
- return option.label
182
- .toLowerCase()
183
- .includes(searchTerm.toLowerCase());
184
- })
185
- .map((option) => (
196
+ {selectedAttributeOptions
197
+ ?.filter((option) => {
198
+ if (!searchTerm) return true;
199
+
200
+ return option.label
201
+ .toLowerCase()
202
+ .includes(searchTerm.toLowerCase());
203
+ })
204
+ .map((option) => {
205
+ const isSelected = currentFilterValue.includes(option.value);
206
+
207
+ return (
186
208
  <FormControlLabel
187
209
  key={option.value}
188
- value={option.value}
189
- control={<Radio />}
210
+ control={
211
+ <Radio
212
+ checked={isSelected}
213
+ onClick={() => handleMultiRadioToggle(option.value)}
214
+ />
215
+ }
190
216
  label={option.label}
191
217
  />
192
- ))}
193
- </RadioGroup>
218
+ );
219
+ })}
194
220
  </FormControl>
195
221
  </Box>
196
222
  )}