rez-table-listing-mui 1.3.29 → 1.3.31

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.
@@ -4,14 +4,37 @@ import FormTextfield from "../components/Textfield";
4
4
  import FormDatePicker from "../components/Date";
5
5
  import FormMultiSelect from "../components/Multi-Select";
6
6
 
7
- // Operators that SHOULD use TextField when applied on date fields
8
- export const NON_DATE_OPERATORS = [
7
+ export type DateOperator =
8
+ | "equal"
9
+ | "before"
10
+ | "after"
11
+ | "between"
12
+ | "is"
13
+ | "today"
14
+ | "is_day_before"
15
+ | "is_day_after"
16
+ | "is_month_before"
17
+ | "is_month_after"
18
+ | "is_before"
19
+ | "is_after"
20
+ | "is_on_or_before"
21
+ | "is_on_or_after";
22
+
23
+ export const DATE_ALLOWED_OPERATORS: DateOperator[] = [
24
+ "equal",
25
+ "before",
26
+ "after",
27
+ "between",
28
+ "is",
29
+ "today",
9
30
  "is_day_before",
10
31
  "is_day_after",
11
32
  "is_month_before",
12
33
  "is_month_after",
13
- "is_before_bussiness_days",
14
- "is_after_bussiness_days",
34
+ "is_before",
35
+ "is_after",
36
+ "is_on_or_before",
37
+ "is_on_or_after",
15
38
  ];
16
39
 
17
40
  export const resolveFilterInput = ({
@@ -27,10 +50,20 @@ export const resolveFilterInput = ({
27
50
  dropdownData: any;
28
51
  updateFiltersFromForm: () => void;
29
52
  }) => {
30
- const dataType = filter?.filter_attribute_data_type;
53
+ const isDateType = filter.filter_attribute_data_type === "date";
54
+
55
+ const showDatePicker =
56
+ isDateType && operator && DATE_ALLOWED_OPERATORS.includes(operator as any);
31
57
 
32
- // TEXT / NUMBER → always textfield
33
- if (dataType === "text" || dataType === "number") {
58
+ const showTextInsteadOfDate =
59
+ isDateType &&
60
+ (!operator || !DATE_ALLOWED_OPERATORS.includes(operator as any));
61
+
62
+ // TEXT / NUMBER -> Always TextField
63
+ if (
64
+ filter?.filter_attribute_data_type === "text" ||
65
+ filter?.filter_attribute_data_type === "number"
66
+ ) {
34
67
  return (
35
68
  <FormTextfield
36
69
  filter={filter}
@@ -40,8 +73,8 @@ export const resolveFilterInput = ({
40
73
  );
41
74
  }
42
75
 
43
- // YEAR → DatePicker (Year mode)
44
- if (dataType === "year") {
76
+ // YEAR
77
+ if (filter?.filter_attribute_data_type === "year") {
45
78
  return (
46
79
  <FormDatePicker
47
80
  filter={filter}
@@ -52,22 +85,8 @@ export const resolveFilterInput = ({
52
85
  );
53
86
  }
54
87
 
55
- // DATE FIELD LOGIC
56
- if (dataType === "date") {
57
- const isNonDateOperator = operator && NON_DATE_OPERATORS.includes(operator);
58
-
59
- if (isNonDateOperator) {
60
- // Non-date operator → show TEXT FIELD
61
- return (
62
- <FormTextfield
63
- filter={filter}
64
- control={control}
65
- onValueChange={updateFiltersFromForm}
66
- />
67
- );
68
- }
69
-
70
- // Default for all other operators → Date Picker
88
+ // DATE LOGIC
89
+ if (showDatePicker) {
71
90
  return (
72
91
  <FormDatePicker
73
92
  filter={filter}
@@ -77,7 +96,17 @@ export const resolveFilterInput = ({
77
96
  );
78
97
  }
79
98
 
80
- // SELECT / MULTISELECT / RADIO / CHECKBOX
99
+ if (showTextInsteadOfDate) {
100
+ return (
101
+ <FormTextfield
102
+ filter={filter}
103
+ control={control}
104
+ onValueChange={updateFiltersFromForm}
105
+ />
106
+ );
107
+ }
108
+
109
+ // MULTISELECT / SELECT / RADIO / CHECKBOX
81
110
  if (
82
111
  filter?.filter_attribute_data_type !== undefined &&
83
112
  ["select", "multiselect", "radio", "checkbox"].includes(
@@ -11,7 +11,7 @@ const MainFilter = ({
11
11
  columnsData,
12
12
  dropdownData,
13
13
  tableStates,
14
- setSavedFilterModalOpen,
14
+ onSaveFilterButtonClick,
15
15
  onChangeFunction,
16
16
  filterComponentOptions,
17
17
  }: FilterFormComponentProps) => {
@@ -22,10 +22,10 @@ const MainFilter = ({
22
22
  useEffect(() => {
23
23
  setFilterMaster(
24
24
  (prev) =>
25
- ({
26
- ...prev,
27
- activeFilterTabIndex: 0,
28
- } as FilterMasterStateProps)
25
+ ({
26
+ ...prev,
27
+ activeFilterTabIndex: 0,
28
+ } as FilterMasterStateProps)
29
29
  );
30
30
  }, []);
31
31
 
@@ -61,7 +61,7 @@ const MainFilter = ({
61
61
  setSearchTerm={setSearchTerm}
62
62
  handleRemoveFilter={handleRemoveFilter}
63
63
  tableStates={tableStates}
64
- setSavedFilterModalOpen={setSavedFilterModalOpen}
64
+ onSaveFilterButtonClick={onSaveFilterButtonClick}
65
65
  dropdownData={dropdownData}
66
66
  onChangeFunction={onChangeFunction}
67
67
  filterComponentOptions={filterComponentOptions}
@@ -18,7 +18,7 @@ const SavedFilterEditComponent = ({
18
18
  setEditMode,
19
19
  searchTerm,
20
20
  setSearchTerm,
21
- setSavedFilterModalOpen,
21
+ onSaveFilterButtonClick,
22
22
  setDeleteFilterModalOpen,
23
23
  onChangeFunction,
24
24
  filterComponentOptions,
@@ -30,7 +30,7 @@ const SavedFilterEditComponent = ({
30
30
  setEditMode?: React.Dispatch<React.SetStateAction<boolean>>;
31
31
  searchTerm?: string;
32
32
  setSearchTerm: React.Dispatch<React.SetStateAction<string>>;
33
- setSavedFilterModalOpen?: React.Dispatch<React.SetStateAction<boolean>>;
33
+ onSaveFilterButtonClick?: () => void;
34
34
  setDeleteFilterModalOpen?: React.Dispatch<React.SetStateAction<boolean>>;
35
35
  onChangeFunction: ({
36
36
  updatedFilters,
@@ -62,6 +62,8 @@ const SavedFilterEditComponent = ({
62
62
  selectedId: "",
63
63
  selectedName: "",
64
64
  selectedCode: "",
65
+ shareWithTeam: false,
66
+ allowTeamEdit: false,
65
67
  },
66
68
  activeFilterTabIndex: -1,
67
69
  } as FilterMasterStateProps)
@@ -99,7 +101,7 @@ const SavedFilterEditComponent = ({
99
101
  dropdownData={dropdownData}
100
102
  searchTerm={searchTerm}
101
103
  setSearchTerm={setSearchTerm}
102
- setSavedFilterModalOpen={setSavedFilterModalOpen}
104
+ onSaveFilterButtonClick={onSaveFilterButtonClick}
103
105
  setDeleteFilterModalOpen={setDeleteFilterModalOpen}
104
106
  onChangeFunction={onChangeFunction}
105
107
  filterComponentOptions={filterComponentOptions}
@@ -5,7 +5,11 @@ import {
5
5
  FilterOperationListProps,
6
6
  } from "../../../types/filter";
7
7
  import {
8
+ Accordion,
9
+ AccordionDetails,
10
+ AccordionSummary,
8
11
  Box,
12
+ Divider,
9
13
  IconButton,
10
14
  List,
11
15
  ListItem,
@@ -15,8 +19,9 @@ import {
15
19
  import CustomSearch from "./search";
16
20
  import { DeleteIcon, EditIcon } from "../../../../assets/svg";
17
21
  import SavedFilterEditComponent from "./saved-edit-filter";
18
- import { filterStyles } from "../style";
22
+ // import { filterStyles } from "../style";
19
23
  import { CheckBox } from "../../../../assets/svg";
24
+ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
20
25
 
21
26
  const SavedFilter = ({
22
27
  columnsData,
@@ -25,31 +30,60 @@ const SavedFilter = ({
25
30
  editMode,
26
31
  setEditMode,
27
32
  setDeleteFilterModalOpen,
28
- setSavedFilterModalOpen,
33
+ onSaveFilterButtonClick,
29
34
  tabValue,
30
35
  onChangeFunction,
31
36
  filterComponentOptions,
32
37
  }: FilterFormComponentProps) => {
33
38
  const { filters, filterMaster, setFilterMaster, setFilterToDelete } =
34
39
  tableStates;
40
+
35
41
  const [searchTerm, setSearchTerm] = useState<string>("");
36
42
 
37
- // reset savedFilterEditValue when component unmounts
43
+ const normalizeFilter = (f: any): FilterOperationListProps => {
44
+ const prefs =
45
+ f.sharedPreferences || f.preferences || f.meta || f.shared_meta || {};
46
+
47
+ return {
48
+ label: f.name || f.label || "Unnamed Filter",
49
+ value: f.id || f.value,
50
+ code: f.code ?? "",
51
+ is_shared: f.is_shared ?? prefs.is_shared ?? false,
52
+
53
+ // 🔥 STRING ko BOOLEAN banaya
54
+ is_editable:
55
+ f.is_editable === true ||
56
+ f.is_editable === "true" ||
57
+ prefs.is_editable === true ||
58
+ prefs.is_editable === "true",
59
+ };
60
+ };
61
+
62
+ const mappedSavedFilter: FilterOperationListProps[] =
63
+ columnsData?.saved_filter?.map(normalizeFilter) ?? [];
64
+
65
+ const mappedSharedFilter: FilterOperationListProps[] =
66
+ columnsData?.shared_filter?.map(normalizeFilter) ?? [];
67
+
68
+ // Reset on unmount
38
69
  useEffect(() => {
39
70
  return () => {
40
- const editModeFromTabOptions =
71
+ const editModeFromTab =
41
72
  filterComponentOptions?.tabOptions?.savedFilter?.editMode;
42
- if (!editModeFromTabOptions) {
73
+
74
+ if (!editModeFromTab) {
43
75
  setEditMode && setEditMode(false);
44
76
  setFilterMaster(
45
77
  (prev) =>
46
78
  ({
47
79
  ...prev,
48
80
  saved_filters: {
49
- ...prev?.attributes,
81
+ ...(prev?.saved_filters ?? {}),
50
82
  selectedId: "",
51
83
  selectedName: "",
52
84
  selectedCode: "",
85
+ shareWithTeam: undefined,
86
+ allowTeamEdit: undefined,
53
87
  },
54
88
  } as FilterMasterStateProps)
55
89
  );
@@ -57,14 +91,16 @@ const SavedFilter = ({
57
91
  };
58
92
  }, []);
59
93
 
60
- const handleListItemClick = (filter: FilterOperationListProps) => {
61
- const newFilterMasterState = {
94
+ const applyFilterStates = (filter: FilterOperationListProps) => {
95
+ const newFilterMaster = {
62
96
  ...filterMaster,
63
97
  saved_filters: {
64
- ...filterMaster?.attributes,
65
- selectedId: filter?.value,
66
- selectedName: filter?.label,
67
- selectedCode: filter?.code,
98
+ ...(filterMaster?.saved_filters ?? {}),
99
+ selectedId: filter.value,
100
+ selectedName: filter.label,
101
+ selectedCode: filter.code,
102
+ shareWithTeam: filter.is_shared,
103
+ allowTeamEdit: filter.is_editable,
68
104
  },
69
105
  attributes: {
70
106
  ...filterMaster?.attributes,
@@ -73,125 +109,109 @@ const SavedFilter = ({
73
109
  activeFilterTabIndex: tabValue,
74
110
  } as FilterMasterStateProps;
75
111
 
76
- setFilterMaster(newFilterMasterState);
77
-
78
- const newState = {
79
- filterMaster: newFilterMasterState,
80
- filters: filters,
81
- };
112
+ setFilterMaster(newFilterMaster);
82
113
 
83
- onChangeFunction && onChangeFunction(newState);
114
+ onChangeFunction &&
115
+ onChangeFunction({
116
+ filterMaster: newFilterMaster,
117
+ filters,
118
+ });
119
+ };
84
120
 
85
- // setEditfilter state on edit icon click
121
+ const handleListItemClick = (filter: FilterOperationListProps) => {
122
+ applyFilterStates(filter);
86
123
  setEditMode && setEditMode(true);
87
124
  setFilterToDelete(filter);
88
125
  };
89
126
 
90
- const handleAppyFilter = (filter: FilterOperationListProps) => {
91
- const newFilterMasterState = {
92
- ...filterMaster,
93
- saved_filters: {
94
- ...filterMaster?.attributes,
95
- selectedId: filter?.value,
96
- selectedName: filter?.label,
97
- selectedCode: filter?.code,
98
- },
99
- attributes: {
100
- ...filterMaster?.attributes,
101
- radio: [],
102
- },
103
- activeFilterTabIndex: tabValue,
104
- } as FilterMasterStateProps;
105
-
106
- setFilterMaster(newFilterMasterState);
127
+ const handleApplyFilter = (filter: FilterOperationListProps) => {
128
+ applyFilterStates(filter);
129
+ };
107
130
 
108
- const newState = {
109
- filterMaster: newFilterMasterState,
110
- filters: filters,
111
- };
131
+ /**
132
+ * renderList
133
+ * @param source - list to render
134
+ * @param isSharedList - true when rendering Shared Filters (default false)
135
+ *
136
+ * Behavior:
137
+ * - If isSharedList === true -> show Edit icon ONLY when filter.is_editable === true
138
+ * - If isSharedList === false -> show Edit icon always (or as per filter.is_editable if you prefer)
139
+ */
140
+ const renderList = (
141
+ source: FilterOperationListProps[],
142
+ isSharedList: boolean = false,
143
+ { emptyMessage = "No saved filters yet." } = {}
144
+ ) =>
145
+ source.length === 0 ? (
146
+ <Typography>{emptyMessage}</Typography>
147
+ ) : (
148
+ <List
149
+ sx={{
150
+ display: "flex",
151
+ flexDirection: "column",
152
+ gap: 1,
153
+ }}
154
+ >
155
+ {source
156
+ .filter((f) =>
157
+ f.label?.toLowerCase().includes(searchTerm.toLowerCase())
158
+ )
159
+ .map((filter) => (
160
+ <ListItem
161
+ key={filter.value}
162
+ sx={{
163
+ cursor: "pointer",
164
+ // border:
165
+ // filter.value ===
166
+ // tableStates?.filterMaster?.saved_filters?.selectedId
167
+ // ? `3px solid #7a5af8`
168
+ // : "1px solid #C5C5C5",
169
+ borderRadius: "8px",
170
+ bgcolor: "#f2f6f8ff",
171
+ display: "flex",
172
+ justifyContent: "space-between",
173
+ gap: 1,
174
+ alignItems: "center",
175
+ "&:hover .action-icons": {
176
+ opacity: 1,
177
+ visibility: "visible",
178
+ },
179
+ }}
180
+ onClick={() => handleApplyFilter(filter)}
181
+ >
182
+ {filter.value ===
183
+ tableStates?.filterMaster?.saved_filters?.selectedId && (
184
+ <Box sx={{ display: "flex", alignItems: "center" }}>
185
+ <CheckBox />
186
+ </Box>
187
+ )}
112
188
 
113
- onChangeFunction && onChangeFunction(newState);
114
- };
189
+ <ListItemText primary={filter.label} />
115
190
 
116
- const renderList = () => (
117
- <>
118
- <CustomSearch
119
- value={searchTerm}
120
- onChange={setSearchTerm}
121
- className="search-input"
122
- />
123
-
124
- {columnsData?.saved_filter?.length === 0 ? (
125
- <Typography sx={{ mt: 2 }}>No saved filters yet.</Typography>
126
- ) : (
127
- <List
128
- sx={{
129
- display: "flex",
130
- flexDirection: "column",
131
- gap: 1,
132
- mt: 2,
133
- }}
134
- >
135
- {columnsData?.saved_filter
136
- ?.filter((filter) =>
137
- filter.label?.toLowerCase().includes(searchTerm.toLowerCase())
138
- )
139
- ?.map((filter) => (
140
- <ListItem
141
- key={filter?.value}
191
+ <Box
192
+ onClick={(e) => e.stopPropagation()}
193
+ className="action-icons"
142
194
  sx={{
143
- cursor: "pointer",
144
- border:
145
- filter?.value ===
146
- tableStates?.filterMaster?.saved_filters?.selectedId
147
- ? `3px solid #7a5af8`
148
- : "1px solid #C5C5C5",
149
- borderRadius: "8px",
150
195
  display: "flex",
151
- justifyContent: "space-between",
152
196
  gap: 1,
153
- alignItems: "center",
154
- "&:hover .action-icons": {
155
- opacity: 1,
156
- visibility: "visible",
157
- },
197
+ opacity: 0,
198
+ visibility: "hidden",
199
+ transition: "all 0.2s ease",
158
200
  }}
159
- onClick={() => handleAppyFilter(filter)}
160
201
  >
161
- {filter?.value ===
162
- tableStates?.filterMaster?.saved_filters?.selectedId && (
163
- <Box
164
- sx={{
165
- display: "flex",
166
- alignItems: "center",
167
- cursor: "pointer",
168
- color: "green",
169
- rounded: "full",
170
- }}
171
- >
172
- <CheckBox />
173
- </Box>
174
- )}
175
- <ListItemText primary={filter?.label} />
176
-
177
- <Box
178
- onClick={(e) => e.stopPropagation()}
179
- className="action-icons"
180
- sx={{
181
- display: "flex",
182
- gap: 1,
183
- opacity: 0,
184
- visibility: "hidden",
185
- transition: "opacity 0.2s ease, visibility 0.2s ease",
186
- }}
187
- >
202
+ {/** Show edit icon:
203
+ * - For shared lists: only if filter.is_editable === true
204
+ * - For non-shared lists: show (keeps previous behavior)
205
+ */}
206
+ {(!isSharedList || filter.is_editable === true) && (
188
207
  <IconButton
189
208
  size="large"
190
209
  onClick={() => handleListItemClick(filter)}
191
210
  >
192
211
  <EditIcon />
193
212
  </IconButton>
194
-
213
+ )}
214
+ {(!isSharedList || filter.is_editable === true) && (
195
215
  <IconButton
196
216
  size="small"
197
217
  onClick={() => {
@@ -201,24 +221,82 @@ const SavedFilter = ({
201
221
  >
202
222
  <DeleteIcon />
203
223
  </IconButton>
204
- </Box>
205
- </ListItem>
206
- ))}
207
- </List>
208
- )}
209
- </>
210
- );
211
-
212
- const mainBoxStyles = {
213
- ...filterStyles.filterMainComponentWrapper,
214
- ...filterStyles.scrollbarCustom,
215
- };
224
+ )}
225
+ </Box>
226
+ </ListItem>
227
+ ))}
228
+ </List>
229
+ );
216
230
 
217
231
  return (
218
- <Box sx={mainBoxStyles} className="saved-filter-component-wrapper">
219
- {/* Render search input and list */}
220
- {!editMode && renderList()}
232
+ <Box
233
+ // sx={{
234
+ // ...filterStyles.filterMainComponentWrapper,
235
+ // ...filterStyles.scrollbarCustom,
236
+ // }}
237
+ className="saved-filter-component-wrapper"
238
+ >
239
+ {!editMode && (
240
+ <>
241
+ {/* Search Box */}
242
+ <Box sx={{ mb: 2 }}>
243
+ <CustomSearch
244
+ value={searchTerm}
245
+ onChange={setSearchTerm}
246
+ className="search-input"
247
+ />
248
+ </Box>
249
+
250
+ {/* ---- My Filters Section ---- */}
251
+ <Box
252
+ sx={{
253
+ background: "#fff",
254
+ borderRadius: "12px",
255
+ border: "1px solid #eee",
256
+ mb: 2,
257
+ overflow: "hidden",
258
+ }}
259
+ >
260
+ <Accordion defaultExpanded disableGutters elevation={0}>
261
+ <AccordionSummary
262
+ expandIcon={<ExpandMoreIcon fontSize="small" />}
263
+ >
264
+ <Typography fontWeight={600}>My Filters</Typography>
265
+ </AccordionSummary>
266
+ <Divider sx={{ width: "100%" }} />
267
+ <AccordionDetails sx={{ p: "9px" }}>
268
+ {renderList(mappedSavedFilter, false)}
269
+ </AccordionDetails>
270
+ </Accordion>
271
+ </Box>
272
+
273
+ {/* ---- Shared Filters Section ---- */}
274
+ <Box
275
+ sx={{
276
+ background: "#fff",
277
+ borderRadius: "12px",
278
+ border: "1px solid #eee",
279
+ mb: 2,
280
+ overflow: "hidden",
281
+ }}
282
+ >
283
+ <Accordion disableGutters elevation={0}>
284
+ <AccordionSummary
285
+ expandIcon={<ExpandMoreIcon fontSize="small" />}
286
+ >
287
+ <Typography fontWeight={600}>Shared Filters</Typography>
288
+ </AccordionSummary>
289
+ <Divider sx={{ width: "100%" }} />
290
+
291
+ <AccordionDetails sx={{ p: "9px" }}>
292
+ {renderList(mappedSharedFilter, true)}
293
+ </AccordionDetails>
294
+ </Accordion>
295
+ </Box>
296
+ </>
297
+ )}
221
298
 
299
+ {/* Edit Component */}
222
300
  {editMode && (
223
301
  <SavedFilterEditComponent
224
302
  columnsData={columnsData}
@@ -228,7 +306,7 @@ const SavedFilter = ({
228
306
  setEditMode={setEditMode}
229
307
  searchTerm={searchTerm}
230
308
  setSearchTerm={setSearchTerm}
231
- setSavedFilterModalOpen={setSavedFilterModalOpen}
309
+ onSaveFilterButtonClick={onSaveFilterButtonClick}
232
310
  setDeleteFilterModalOpen={setDeleteFilterModalOpen}
233
311
  onChangeFunction={onChangeFunction}
234
312
  filterComponentOptions={filterComponentOptions}
@@ -13,7 +13,7 @@ const SingleFilterRendering = ({
13
13
  columnsData,
14
14
  dropdownData,
15
15
  tableStates,
16
- setSavedFilterModalOpen,
16
+ onSaveFilterButtonClick,
17
17
  onChangeFunction,
18
18
  filterComponentOptions,
19
19
  editMode,
@@ -50,7 +50,7 @@ const SingleFilterRendering = ({
50
50
  {showFilter === "main" && (
51
51
  <MainFilter
52
52
  {...commonProps}
53
- setSavedFilterModalOpen={setSavedFilterModalOpen}
53
+ onSaveFilterButtonClick={onSaveFilterButtonClick}
54
54
  filterComponentOptions={filterComponentOptions}
55
55
  />
56
56
  )}
@@ -59,7 +59,7 @@ const SingleFilterRendering = ({
59
59
  <SavedFilter
60
60
  {...commonProps}
61
61
  {...editProps}
62
- setSavedFilterModalOpen={setSavedFilterModalOpen}
62
+ onSaveFilterButtonClick={onSaveFilterButtonClick}
63
63
  filterComponentOptions={filterComponentOptions}
64
64
  />
65
65
  )}