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
@@ -4,7 +4,7 @@ import { DatePicker } from "@mui/x-date-pickers/DatePicker";
4
4
  import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns";
5
5
  import moment from "moment";
6
6
  import { UpdatedFilterStateProps } from "../../../../../types/filter";
7
- import { SxProps, Theme } from "@mui/material";
7
+ import { SxProps, Theme, Box } from "@mui/material";
8
8
 
9
9
  type FormDatePickerProps = {
10
10
  filter: UpdatedFilterStateProps;
@@ -21,77 +21,186 @@ const FormDatePicker = ({
21
21
  views = ["day", "month", "year"],
22
22
  onValueChange,
23
23
  }: FormDatePickerProps) => {
24
+ const isRange = filter.filter_operator === "between";
25
+ const isRelativeToToday = filter.filter_operator === "today";
26
+
24
27
  return (
25
- <Controller
26
- name={`${filter?.name}.value`}
27
- control={control}
28
- defaultValue={filter.filter_value || ""}
29
- render={({ field }) => {
30
- const isYearOnly = views.length === 1 && views[0] === "year";
31
- // Convert string year (e.g., "2025") to Date for DatePicker, or null if empty
32
- const displayValue = isYearOnly
33
- ? field.value
34
- ? new Date(Number(field.value), 0, 1)
35
- : null
36
- : field.value
37
- ? moment(field.value, "DD-MM-YYYY").toDate()
38
- : null;
28
+ <LocalizationProvider dateAdapter={AdapterDateFns}>
29
+ <Box display="flex" gap={1}>
30
+ <Controller
31
+ name={`${filter?.name}.value`}
32
+ control={control}
33
+ defaultValue={
34
+ isRange
35
+ ? ["", ""]
36
+ : isRelativeToToday
37
+ ? moment().format("YYYY-MM-DD")
38
+ : filter.filter_value
39
+ ? moment(filter.filter_value, "YYYY-MM-DD").toDate()
40
+ : null
41
+ }
42
+ render={({ field }) => {
43
+ const value = field.value;
44
+ const todayDate = moment().toDate();
45
+ if (isRange) {
46
+ const fromDate = Array.isArray(value) ? value[0] : "";
47
+ const toDate = Array.isArray(value) ? value[1] : "";
39
48
 
40
- return (
41
- <LocalizationProvider dateAdapter={AdapterDateFns}>
42
- <DatePicker
43
- views={views}
44
- value={displayValue}
45
- onChange={(date) => {
46
- // Handle picker selection or typed input
47
- const formatted = date
48
- ? isYearOnly
49
- ? moment(date).format("YYYY")
50
- : moment(date).format("DD-MM-YYYY")
51
- : "";
52
- field.onChange(formatted);
53
- onValueChange?.();
54
- }}
55
- format={isYearOnly ? "yyyy" : "dd-MM-yyyy"}
56
- sx={{
57
- "& .MuiOutlinedInput-input": {
58
- padding: "8.5px 14px",
59
- fontSize: "14px",
60
- color: "#000",
61
- },
62
- "& .MuiInputBase-root": {
63
- bgcolor: "white",
64
- },
65
- ...sx,
66
- }}
67
- slotProps={{
68
- textField: {
69
- size: "small",
70
- fullWidth: true,
71
- placeholder: isYearOnly ? "YYYY" : "DD-MM-YYYY",
72
- inputProps: isYearOnly
73
- ? {
74
- maxLength: 4, // Limit to 4 digits
75
- inputMode: "numeric", // Optimize for numeric input
76
- pattern: "[0-9]*", // Restrict to numbers
49
+ return (
50
+ <>
51
+ <DatePicker
52
+ views={views}
53
+ value={
54
+ isRelativeToToday
55
+ ? todayDate
56
+ : fromDate
57
+ ? moment(fromDate, "YYYY-MM-DD").toDate()
58
+ : null
59
+ }
60
+ onChange={(date) => {
61
+ if (isRelativeToToday) return;
62
+ let formatted = "";
63
+ if (date) {
64
+ formatted =
65
+ views?.length === 1 && views[0] === "year"
66
+ ? moment(date).format("YYYY")
67
+ : moment(date).format("YYYY-MM-DD");
77
68
  }
78
- : undefined,
79
- onBlur: () => {
80
- if (isYearOnly) {
81
- const value = field.value;
82
- if (value && !/^\d{4}$/.test(value)) {
83
- field.onChange("");
84
- onValueChange?.();
69
+ const updated: [string, string] = [
70
+ formatted,
71
+ toDate || "",
72
+ ];
73
+ field.onChange(updated);
74
+ onValueChange?.();
75
+ }}
76
+ disabled={isRelativeToToday}
77
+ format={
78
+ views?.length === 1 && views[0] === "year"
79
+ ? "yyyy"
80
+ : "dd-MM-yyyy"
81
+ }
82
+ sx={{
83
+ "& .MuiOutlinedInput-input": {
84
+ padding: "12px 20px",
85
+ },
86
+ ...sx,
87
+ }}
88
+ slotProps={{
89
+ textField: {
90
+ size: "small",
91
+ fullWidth: true,
92
+ placeholder:
93
+ views?.length === 1 && views[0] === "year"
94
+ ? "YYYY"
95
+ : "From Date",
96
+ },
97
+ }}
98
+ />
99
+
100
+ <DatePicker
101
+ views={views}
102
+ value={
103
+ isRelativeToToday
104
+ ? todayDate
105
+ : toDate
106
+ ? moment(toDate, "YYYY-MM-DD").toDate()
107
+ : null
108
+ }
109
+ onChange={(date) => {
110
+ if (isRelativeToToday) return;
111
+ let formatted = "";
112
+ if (date) {
113
+ formatted =
114
+ views?.length === 1 && views[0] === "year"
115
+ ? moment(date).format("YYYY")
116
+ : moment(date).format("YYYY-MM-DD");
85
117
  }
118
+ const updated: [string, string] = [
119
+ fromDate || "",
120
+ formatted,
121
+ ];
122
+ field.onChange(updated);
123
+ onValueChange?.();
124
+ }}
125
+ disabled={isRelativeToToday}
126
+ format={
127
+ views?.length === 1 && views[0] === "year"
128
+ ? "yyyy"
129
+ : "dd-MM-yyyy"
86
130
  }
131
+ sx={{
132
+ "& .MuiOutlinedInput-input": {
133
+ padding: "12px 20px",
134
+ },
135
+ ...sx,
136
+ }}
137
+ slotProps={{
138
+ textField: {
139
+ size: "small",
140
+ fullWidth: true,
141
+ placeholder:
142
+ views?.length === 1 && views[0] === "year"
143
+ ? "YYYY"
144
+ : "To Date",
145
+ },
146
+ }}
147
+ />
148
+ </>
149
+ );
150
+ }
151
+
152
+ // Single DatePicker
153
+ return (
154
+ <DatePicker
155
+ {...field}
156
+ views={views}
157
+ value={
158
+ isRelativeToToday
159
+ ? todayDate
160
+ : field.value
161
+ ? moment(field.value, "YYYY-MM-DD").toDate()
162
+ : null
163
+ }
164
+ onChange={(date) => {
165
+ if (isRelativeToToday) return;
166
+ let formatted = "";
167
+ if (date) {
168
+ formatted =
169
+ views?.length === 1 && views[0] === "year"
170
+ ? moment(date).format("YYYY")
171
+ : moment(date).format("YYYY-MM-DD");
172
+ }
173
+ field.onChange(formatted);
174
+ onValueChange?.();
175
+ }}
176
+ disabled={isRelativeToToday}
177
+ format={
178
+ views?.length === 1 && views[0] === "year"
179
+ ? "yyyy"
180
+ : "dd-MM-yyyy"
181
+ }
182
+ sx={{
183
+ "& .MuiOutlinedInput-input": {
184
+ padding: "12px 20px",
185
+ },
186
+ ...sx,
187
+ }}
188
+ slotProps={{
189
+ textField: {
190
+ size: "small",
191
+ fullWidth: true,
192
+ placeholder:
193
+ views?.length === 1 && views[0] === "year"
194
+ ? "YYYY"
195
+ : "DD-MM-YYYY",
87
196
  },
88
- },
89
- }}
90
- />
91
- </LocalizationProvider>
92
- );
93
- }}
94
- />
197
+ }}
198
+ />
199
+ );
200
+ }}
201
+ />
202
+ </Box>
203
+ </LocalizationProvider>
95
204
  );
96
205
  };
97
206
 
@@ -1,10 +1,12 @@
1
1
  import { FormControl, MenuItem, Select, SxProps, Theme } from "@mui/material";
2
- import { Controller } from "react-hook-form";
2
+ import { Controller, UseFormSetValue } from "react-hook-form";
3
3
  import { UpdatedFilterStateProps } from "../../../../../types/filter";
4
+ import moment from "moment";
4
5
 
5
6
  interface FormDropdownProps {
6
7
  filter: UpdatedFilterStateProps;
7
8
  control: any;
9
+ setValue: UseFormSetValue<any>;
8
10
  dropdownList: {
9
11
  label?: string;
10
12
  value?: string;
@@ -17,6 +19,7 @@ interface FormDropdownProps {
17
19
  const FormDropdown = ({
18
20
  filter,
19
21
  control,
22
+ setValue,
20
23
  dropdownList,
21
24
  isLoading = false,
22
25
  sx,
@@ -48,8 +51,38 @@ const FormDropdown = ({
48
51
  disabled={isLoading}
49
52
  disableUnderline
50
53
  onChange={(e) => {
51
- field.onChange(e); // sync with RHF
52
- onValueChange?.(); // trigger debounce
54
+ const newOperator = e.target.value;
55
+ const oldOperator = field.value;
56
+
57
+ field.onChange(e);
58
+
59
+ if (
60
+ (filter.data_type === "date" || filter.data_type === "year") &&
61
+ newOperator !== oldOperator
62
+ ) {
63
+ if (newOperator === "today") {
64
+ setValue(
65
+ `${filter.name}.value`,
66
+ moment().format("YYYY-MM-DD"),
67
+ {
68
+ shouldDirty: true,
69
+ }
70
+ );
71
+ } else if (newOperator === "between") {
72
+ setValue(`${filter.name}.value`, ["", ""], {
73
+ shouldDirty: true,
74
+ });
75
+ } else if (
76
+ oldOperator === "between" ||
77
+ oldOperator === "today"
78
+ ) {
79
+ setValue(`${filter.name}.value`, "", {
80
+ shouldDirty: true,
81
+ });
82
+ }
83
+ }
84
+
85
+ onValueChange?.();
53
86
  }}
54
87
  >
55
88
  {dropdownList?.map((item, idx) => (
@@ -7,7 +7,7 @@ import {
7
7
  Paper,
8
8
  ListItemText,
9
9
  } from "@mui/material";
10
- import { useState, useRef } from "react";
10
+ import { useRef } from "react";
11
11
  import { AddIcon } from "../../../../../assets/svg";
12
12
  import {
13
13
  FilterColumnsDataProps,
@@ -1,5 +1,12 @@
1
1
  import { Controller } from "react-hook-form";
2
- import { FormControl, Select, MenuItem, Theme, SxProps } from "@mui/material";
2
+ import {
3
+ FormControl,
4
+ Select,
5
+ MenuItem,
6
+ Theme,
7
+ SxProps,
8
+ Checkbox,
9
+ } from "@mui/material";
3
10
  import { UpdatedFilterStateProps } from "../../../../../types/filter";
4
11
  import { DropdownOption } from "../../../../../types/common";
5
12
 
@@ -22,39 +29,60 @@ const FormMultiSelect = ({
22
29
  <Controller
23
30
  name={`${filter?.name}.value`}
24
31
  control={control}
25
- defaultValue={filter.filter_value || []}
26
- render={({ field }) => (
27
- <FormControl sx={sx} fullWidth size="small">
28
- <Select
29
- {...field}
30
- sx={{
31
- "& .MuiOutlinedInput-input": {
32
- padding: "12px 20px",
33
- },
34
- }}
35
- multiple
36
- value={field.value || []}
37
- onChange={(e) => {
38
- field.onChange(e.target.value);
39
- onValueChange?.();
40
- }}
41
- renderValue={(selected: string[]) =>
42
- selected
43
- .map(
44
- (val) =>
45
- options.find((item) => item.value === val)?.label || val
46
- )
47
- .join(", ")
48
- }
49
- >
50
- {options.map((item, idx) => (
51
- <MenuItem key={idx} value={item.value}>
52
- {item.label}
53
- </MenuItem>
54
- ))}
55
- </Select>
56
- </FormControl>
57
- )}
32
+ defaultValue={
33
+ Array.isArray(filter.filter_value)
34
+ ? filter.filter_value.filter(Boolean)
35
+ : []
36
+ }
37
+ render={({ field }) => {
38
+ const cleanedValue = Array.isArray(field.value)
39
+ ? field.value.filter(Boolean)
40
+ : [];
41
+
42
+ return (
43
+ <FormControl sx={sx} fullWidth size="small">
44
+ <Select
45
+ {...field}
46
+ sx={{
47
+ "& .MuiOutlinedInput-input": {
48
+ padding: "12px 20px",
49
+ },
50
+ }}
51
+ multiple
52
+ value={cleanedValue}
53
+ onChange={(e) => {
54
+ const value = e.target.value;
55
+ const filtered = Array.isArray(value)
56
+ ? value.filter(Boolean)
57
+ : [];
58
+ field.onChange(filtered);
59
+ onValueChange?.();
60
+ }}
61
+ renderValue={(selected) => {
62
+ const filtered = Array.isArray(selected)
63
+ ? selected.filter(Boolean)
64
+ : [];
65
+ return filtered
66
+ .map(
67
+ (val) =>
68
+ options.find((item) => item.value === val)?.label || val
69
+ )
70
+ .join(", ");
71
+ }}
72
+ >
73
+ {options.map((item, idx) => (
74
+ <MenuItem key={idx} value={item.value}>
75
+ <Checkbox
76
+ checked={cleanedValue.includes(item.value)}
77
+ sx={{ marginRight: 1 }}
78
+ />
79
+ {item.label}
80
+ </MenuItem>
81
+ ))}
82
+ </Select>
83
+ </FormControl>
84
+ );
85
+ }}
58
86
  />
59
87
  );
60
88
  };
@@ -16,7 +16,6 @@ import {
16
16
  import { Controller, useForm } from "react-hook-form";
17
17
  import FormTextfield from "./components/Textfield";
18
18
  import React, { useEffect, useMemo, useCallback } from "react";
19
- import FormSelect from "./components/Select";
20
19
  import FormDatePicker from "./components/Date";
21
20
  import FormDropdown from "./components/Dropdown";
22
21
  import FormMultiSelect from "./components/Multi-Select";
@@ -243,7 +242,10 @@ const FilterForm = ({
243
242
  <CustomSearch value={searchTerm} onChange={setSearchTerm} />
244
243
  )}
245
244
 
246
- <Box className="filter-form-inputs">
245
+ <Box
246
+ className="filter-form-inputs"
247
+ sx={filterFormStyles.formFlexContainer}
248
+ >
247
249
  {selectedFilters
248
250
  .filter(
249
251
  (filter) =>
@@ -255,6 +257,7 @@ const FilterForm = ({
255
257
  .toLowerCase()
256
258
  .includes(searchTerm.toLowerCase())
257
259
  )
260
+ .reverse()
258
261
  .map((filter) => {
259
262
  const { dropdown_list = [] } = filter;
260
263
  return (
@@ -269,6 +272,7 @@ const FilterForm = ({
269
272
  <FormDropdown
270
273
  filter={filter}
271
274
  control={control}
275
+ setValue={setValue}
272
276
  dropdownList={dropdown_list}
273
277
  sx={filterFormStyles.formListItemHeaderDropdown}
274
278
  onValueChange={updateFiltersFromForm}
@@ -332,6 +336,20 @@ const FilterForm = ({
332
336
  dropdownData={dropdownData}
333
337
  onValueChange={updateFiltersFromForm}
334
338
  />
339
+ ) : filter.data_type === "radio" ? (
340
+ <FormMultiSelect
341
+ filter={filter}
342
+ control={control}
343
+ dropdownData={dropdownData}
344
+ onValueChange={updateFiltersFromForm}
345
+ />
346
+ ) : filter.data_type === "checkbox" ? (
347
+ <FormMultiSelect
348
+ filter={filter}
349
+ control={control}
350
+ dropdownData={dropdownData}
351
+ onValueChange={updateFiltersFromForm}
352
+ />
335
353
  ) : (
336
354
  <FormControl fullWidth size="small" />
337
355
  )}
@@ -13,9 +13,10 @@ import {
13
13
  Typography,
14
14
  } from "@mui/material";
15
15
  import CustomSearch from "./search";
16
- import { DeleteIcon } from "../../../assets/svg";
16
+ import { DeleteIcon, EditIcon } from "../../../assets/svg";
17
17
  import SavedFilterEditComponent from "./saved-edit-filter";
18
18
  import { filterStyles } from "../style";
19
+ import { CheckBox } from "../../../assets/svg";
19
20
 
20
21
  const SavedFilter = ({
21
22
  columnsData,
@@ -66,11 +67,26 @@ const SavedFilter = ({
66
67
  activeFilterTabIndex: tabValue,
67
68
  } as FilterMasterStateProps)
68
69
  );
69
-
70
+ // setEditfilter state on edit icon click
70
71
  setEditMode && setEditMode(true);
71
72
  setFilterToDelete(filter);
72
73
  };
73
74
 
75
+ const handleAppyFilter = (filter: FilterOperationListProps) => {
76
+ setFilterMaster(
77
+ (prev) =>
78
+ ({
79
+ ...prev,
80
+ saved_filters: {
81
+ ...prev?.attributes,
82
+ selectedId: filter?.value,
83
+ selectedName: filter?.label,
84
+ },
85
+ activeFilterTabIndex: tabValue,
86
+ } as FilterMasterStateProps)
87
+ );
88
+ };
89
+
74
90
  const renderList = () => (
75
91
  <>
76
92
  <CustomSearch
@@ -99,24 +115,62 @@ const SavedFilter = ({
99
115
  key={filter?.value}
100
116
  sx={{
101
117
  cursor: "pointer",
102
- border: "1px solid #ccc",
118
+ border:
119
+ filter?.value ===
120
+ tableStates?.filterMaster?.saved_filters?.selectedId
121
+ ? `3px solid #7a5af8`
122
+ : "1px solid #C5C5C5",
103
123
  borderRadius: "8px",
104
124
  display: "flex",
105
125
  justifyContent: "space-between",
126
+ gap: 1,
106
127
  alignItems: "center",
128
+ "&:hover .action-icons": {
129
+ opacity: 1,
130
+ visibility: "visible",
131
+ },
107
132
  }}
108
- onClick={() => handleListItemClick(filter)}
133
+ onClick={() => handleAppyFilter(filter)}
109
134
  >
135
+ {filter?.value ===
136
+ tableStates?.filterMaster?.saved_filters?.selectedId && (
137
+ <Box
138
+ sx={{
139
+ display: "flex",
140
+ alignItems: "center",
141
+ cursor: "pointer",
142
+ color: "green",
143
+ rounded: "full",
144
+ }}
145
+ >
146
+ <CheckBox />
147
+ </Box>
148
+ )}
110
149
  <ListItemText primary={filter?.label} />
111
150
 
112
- <Box onClick={(e) => e.stopPropagation()}>
151
+ <Box
152
+ onClick={(e) => e.stopPropagation()}
153
+ className="action-icons"
154
+ sx={{
155
+ display: "flex",
156
+ gap: 1,
157
+ opacity: 0,
158
+ visibility: "hidden",
159
+ transition: "opacity 0.2s ease, visibility 0.2s ease",
160
+ }}
161
+ >
162
+ <IconButton
163
+ size="large"
164
+ onClick={() => handleListItemClick(filter)}
165
+ >
166
+ <EditIcon />
167
+ </IconButton>
168
+
113
169
  <IconButton
114
170
  size="small"
115
171
  onClick={() => {
116
- setFilterToDelete(filter); // Store the filter to delete
117
-
118
- setDeleteFilterModalOpen &&
119
- setDeleteFilterModalOpen(true); // Open the delete confirmation modal
172
+ setFilterToDelete(filter);
173
+ setDeleteFilterModalOpen?.(true);
120
174
  }}
121
175
  >
122
176
  <DeleteIcon />
@@ -79,7 +79,7 @@ export function TableFilter({
79
79
 
80
80
  const handleTabChange = (_: React.SyntheticEvent, newValue: number) => {
81
81
  setTabValue(newValue);
82
- if (newValue !== 1) {
82
+ if (newValue === 0) {
83
83
  setEditMode(false);
84
84
  setSelectedFilters([]);
85
85
  }
@@ -89,7 +89,7 @@ export function TableFilter({
89
89
  const tabItems: TabItem[] = [
90
90
  { label: "Filter" },
91
91
  { label: "Saved Filter" },
92
- // { label: "Attributes" },
92
+ { label: "Attributes" },
93
93
  ];
94
94
 
95
95
  const handleTabCrossClick = (index: number) => {
@@ -122,7 +122,7 @@ export function TableFilter({
122
122
  ({
123
123
  ...prev,
124
124
  attributes: {
125
- radio: "",
125
+ radio: [],
126
126
  selected: "",
127
127
  },
128
128
  } as FilterMasterStateProps)
@@ -90,7 +90,7 @@ export const filterFormStyles: filterFormStyleType = {
90
90
  formFlexContainer: {
91
91
  display: "flex",
92
92
  flexDirection: "column",
93
- gap: "1.25rem",
93
+ gap: "0.75rem",
94
94
  },
95
95
 
96
96
  formListItem: {