rez-table-listing-mui 1.0.32 → 1.0.34
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.
- package/dist/index.d.ts +11 -4
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/src/App.tsx +31 -29
- package/src/components/filter/components/attributes-filter.tsx +186 -13
- package/src/components/filter/components/forms/components/Date.tsx +94 -16
- package/src/components/filter/components/forms/components/Dropdown.tsx +12 -7
- package/src/components/filter/components/forms/components/Filter-criteria.tsx +47 -40
- package/src/components/filter/components/forms/components/Multi-Select.tsx +6 -1
- package/src/components/filter/components/forms/components/Select.tsx +9 -0
- package/src/components/filter/components/forms/components/Textfield.tsx +6 -0
- package/src/components/filter/components/forms/index.tsx +135 -211
- package/src/components/filter/components/main-filter.tsx +2 -7
- package/src/components/filter/components/saved-edit-filter.tsx +15 -17
- package/src/components/filter/components/saved-filter.tsx +2 -1
- package/src/components/filter/components/search/index.tsx +0 -1
- package/src/components/filter/components/tabs/custom-tab-panel.tsx +7 -3
- package/src/components/filter/components/tabs/index.tsx +8 -8
- package/src/components/filter/index.tsx +187 -172
- package/src/components/filter/style.ts +106 -0
- package/src/components/index-table.tsx +87 -63
- package/src/components/index.scss +33 -0
- package/src/components/topbar/index.tsx +7 -33
- package/src/index.ts +2 -0
- package/src/libs/utils/common.ts +1 -1
- package/src/types/filter.ts +1 -0
- package/src/types/table.ts +7 -2
- package/src/components/filter/components/forms/components/Attributes-select.tsx +0 -192
package/src/App.tsx
CHANGED
|
@@ -16,15 +16,17 @@ import {
|
|
|
16
16
|
useFetchData,
|
|
17
17
|
} from "./libs/hooks/useEntityTableHooks";
|
|
18
18
|
import LoginButton from "./components/login";
|
|
19
|
+
import { CraftTableFilter } from ".";
|
|
19
20
|
// import { ENTITY_TYPE } from "./libs/utils/common";
|
|
20
21
|
|
|
21
22
|
function App() {
|
|
22
|
-
const [mockLoading, setMockLoading] = useState<boolean>(true);
|
|
23
|
+
// const [mockLoading, setMockLoading] = useState<boolean>(true);
|
|
23
24
|
// const [jsonData] = useState<any[]>([]);
|
|
24
25
|
const [columns, setColumns] = useState<any[]>([]);
|
|
26
|
+
const [showFilter, setShowFilter] = useState<boolean>(true);
|
|
25
27
|
const [searchTerm, setSearchTerm] = useState("");
|
|
26
28
|
// const [data, setData] = useState<Person[]>(() => makeData(50, 3, 2));
|
|
27
|
-
// const [entity_type] = useState(ENTITY_TYPE); //OR
|
|
29
|
+
// const [entity_type] = useState(ENTITY_TYPE); //OR UPR BRD
|
|
28
30
|
|
|
29
31
|
const [selectedTab, setSelectedTab] = useState("ALL");
|
|
30
32
|
|
|
@@ -33,32 +35,27 @@ function App() {
|
|
|
33
35
|
|
|
34
36
|
const { defaultColumns } = useDefaultColumns();
|
|
35
37
|
|
|
36
|
-
const { metaQuery } = useFetchData("
|
|
38
|
+
const { metaQuery } = useFetchData("UPR");
|
|
37
39
|
const { detailsQuery } = useDetailsQueryAPI(
|
|
38
40
|
filterMaster?.saved_filters?.selectedId
|
|
39
41
|
? filterMaster?.saved_filters?.selectedId
|
|
40
42
|
: metaQuery?.data?.default_filter?.value
|
|
41
43
|
);
|
|
42
44
|
|
|
43
|
-
//API CALL FOR SAVED FILTER
|
|
44
|
-
const {
|
|
45
|
-
|
|
46
|
-
//API FOR DELETING FILTER
|
|
47
|
-
const { deleteMutation } = useDeleteFilterAPI();
|
|
48
|
-
|
|
49
|
-
//API FOR UPDATE FILTER
|
|
50
|
-
const { updateMutation } = useUpdateFilterAPI();
|
|
45
|
+
const { savedMutation } = useSavedFilterAPI(); //API CALL FOR SAVED FILTER
|
|
46
|
+
const { deleteMutation } = useDeleteFilterAPI(); //API FOR DELETING FILTER
|
|
47
|
+
const { updateMutation } = useUpdateFilterAPI(); //API FOR UPDATE FILTER
|
|
51
48
|
|
|
52
49
|
const { dropdownData } = useCommonDropdownAPI(metaQuery.data);
|
|
53
50
|
|
|
54
51
|
useEffect(() => {
|
|
55
|
-
setTimeout(() => {
|
|
56
|
-
|
|
57
|
-
}, 1000);
|
|
52
|
+
// setTimeout(() => {
|
|
53
|
+
// setMockLoading(false);
|
|
54
|
+
// }, 1000);
|
|
58
55
|
|
|
59
56
|
const fetchMeta = async () => {
|
|
60
57
|
try {
|
|
61
|
-
const { res } = await entityTableMetaMaster("
|
|
58
|
+
const { res } = await entityTableMetaMaster("UPR");
|
|
62
59
|
setColumns(res);
|
|
63
60
|
} catch (error) {
|
|
64
61
|
console.error("Failed to fetch metadata:", error);
|
|
@@ -77,7 +74,7 @@ function App() {
|
|
|
77
74
|
const { tableData, isTableDataPending } = useEntityTableAPI({
|
|
78
75
|
page: 0,
|
|
79
76
|
size: 50,
|
|
80
|
-
entity_type: "
|
|
77
|
+
entity_type: "UPR",
|
|
81
78
|
tabs: {
|
|
82
79
|
columnName: "status",
|
|
83
80
|
sortBy: "ASC",
|
|
@@ -156,7 +153,7 @@ function App() {
|
|
|
156
153
|
const payload = {
|
|
157
154
|
name,
|
|
158
155
|
is_default: false,
|
|
159
|
-
mapped_entity_type: "
|
|
156
|
+
mapped_entity_type: "UPR", // For that entity type
|
|
160
157
|
status: "ACTIVE",
|
|
161
158
|
entity_type: "SFM", // FIXED entity type
|
|
162
159
|
filterDetails: quickFilter,
|
|
@@ -171,7 +168,7 @@ function App() {
|
|
|
171
168
|
name: filterToDelete?.label,
|
|
172
169
|
id: filterToDelete?.value,
|
|
173
170
|
is_default: false,
|
|
174
|
-
mapped_entity_type: "
|
|
171
|
+
mapped_entity_type: "UPR",
|
|
175
172
|
status: "INACTIVE",
|
|
176
173
|
entity_type: "SFM",
|
|
177
174
|
};
|
|
@@ -192,7 +189,7 @@ function App() {
|
|
|
192
189
|
name: filterMaster?.saved_filters?.selectedName, // Name of the filter
|
|
193
190
|
is_default: false,
|
|
194
191
|
id: filterMaster?.saved_filters?.selectedId,
|
|
195
|
-
mapped_entity_type: "
|
|
192
|
+
mapped_entity_type: "UPR",
|
|
196
193
|
status: "ACTIVE",
|
|
197
194
|
entity_type: "SFM",
|
|
198
195
|
filterDetails: quickFilter,
|
|
@@ -237,16 +234,7 @@ function App() {
|
|
|
237
234
|
searchValue: searchTerm,
|
|
238
235
|
onSearchChange: (val) => setSearchTerm(val),
|
|
239
236
|
showFilterToggle: true,
|
|
240
|
-
|
|
241
|
-
tableStates: tableStates,
|
|
242
|
-
tableData: tableData,
|
|
243
|
-
columnsData: metaQuery.data || [],
|
|
244
|
-
defaultFilters: detailsQuery.data || [],
|
|
245
|
-
dropdownData: dropdownData || [],
|
|
246
|
-
onDeleteFilter: handleRemoveFilter,
|
|
247
|
-
onSaveFilter: handleSaveFilter,
|
|
248
|
-
onUpdateFilter: handleUpdateFilter,
|
|
249
|
-
},
|
|
237
|
+
onFilterButtonClick: () => setShowFilter(!showFilter),
|
|
250
238
|
}}
|
|
251
239
|
paginationOptions={{
|
|
252
240
|
showPagination: true,
|
|
@@ -258,6 +246,20 @@ function App() {
|
|
|
258
246
|
renderStatus: handleRenderStatus,
|
|
259
247
|
renderAction: handleRenderAction,
|
|
260
248
|
}}
|
|
249
|
+
filterOptions={{
|
|
250
|
+
show: showFilter,
|
|
251
|
+
component: (
|
|
252
|
+
<CraftTableFilter
|
|
253
|
+
tableStates={tableStates}
|
|
254
|
+
columnsData={metaQuery.data || []}
|
|
255
|
+
dropdownData={dropdownData || []}
|
|
256
|
+
onDeleteFilter={handleRemoveFilter}
|
|
257
|
+
onSaveFilter={handleSaveFilter}
|
|
258
|
+
onUpdateFilter={handleUpdateFilter}
|
|
259
|
+
onClose={() => setShowFilter(false)}
|
|
260
|
+
/>
|
|
261
|
+
),
|
|
262
|
+
}}
|
|
261
263
|
/>
|
|
262
264
|
</div>
|
|
263
265
|
);
|
|
@@ -1,6 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
Box,
|
|
3
|
+
FormControl,
|
|
4
|
+
FormControlLabel,
|
|
5
|
+
MenuItem,
|
|
6
|
+
Radio,
|
|
7
|
+
RadioGroup,
|
|
8
|
+
Select,
|
|
9
|
+
SelectChangeEvent,
|
|
10
|
+
} from "@mui/material";
|
|
11
|
+
import {
|
|
12
|
+
AttributesFilterProps,
|
|
13
|
+
FilterMasterStateProps,
|
|
14
|
+
} from "../../../types/filter";
|
|
15
|
+
import CustomSearch from "./search";
|
|
16
|
+
import { useMemo } from "react";
|
|
4
17
|
|
|
5
18
|
const AttributesFilter = ({
|
|
6
19
|
columnsData,
|
|
@@ -10,17 +23,177 @@ const AttributesFilter = ({
|
|
|
10
23
|
setSearchTerm,
|
|
11
24
|
tabValue,
|
|
12
25
|
}: AttributesFilterProps) => {
|
|
26
|
+
const { filterMaster, setFilterMaster, filters, setFilters } = tableStates;
|
|
27
|
+
|
|
28
|
+
const selectedAttribute = filterMaster?.attributes?.selected;
|
|
29
|
+
|
|
30
|
+
// Get the current filter value to set radio button state
|
|
31
|
+
const currentFilterValue = useMemo(() => {
|
|
32
|
+
if (!selectedAttribute) return "";
|
|
33
|
+
|
|
34
|
+
const matchingColumn = columnsData.column_list.find(
|
|
35
|
+
(column) => column.datasource_list === selectedAttribute
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
if (!matchingColumn) return "";
|
|
39
|
+
|
|
40
|
+
const existingFilter = filters.find(
|
|
41
|
+
(filter) => filter.filter_attribute === matchingColumn.attribute_key
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
return existingFilter?.filter_value || "";
|
|
45
|
+
}, [selectedAttribute, filters, columnsData]);
|
|
46
|
+
|
|
47
|
+
const handleSelectChange = (event: SelectChangeEvent) => {
|
|
48
|
+
const attributeKey = event.target.value as string;
|
|
49
|
+
|
|
50
|
+
setFilterMaster(
|
|
51
|
+
(prev) =>
|
|
52
|
+
({
|
|
53
|
+
...prev,
|
|
54
|
+
attributes: {
|
|
55
|
+
...prev?.attributes,
|
|
56
|
+
selected: attributeKey,
|
|
57
|
+
radio: "", // Reset radio selection when changing attribute
|
|
58
|
+
},
|
|
59
|
+
} as FilterMasterStateProps)
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const handleRadioChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
64
|
+
event.preventDefault();
|
|
65
|
+
|
|
66
|
+
const selectedValue = event.target.value;
|
|
67
|
+
|
|
68
|
+
setFilterMaster(
|
|
69
|
+
(prev) =>
|
|
70
|
+
({
|
|
71
|
+
...prev,
|
|
72
|
+
attributes: {
|
|
73
|
+
...prev?.attributes,
|
|
74
|
+
radio: selectedValue,
|
|
75
|
+
},
|
|
76
|
+
activeFilterTabIndex: tabValue,
|
|
77
|
+
} as FilterMasterStateProps)
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const selectedAttribute = filterMaster?.attributes.selected;
|
|
81
|
+
if (selectedAttribute) {
|
|
82
|
+
const matchingColumn = columnsData.column_list.find(
|
|
83
|
+
(column) => column.datasource_list === selectedAttribute
|
|
84
|
+
);
|
|
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]);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const selectedAttributeOptions = useMemo(() => {
|
|
101
|
+
const selected = columnsData.column_list.find(
|
|
102
|
+
(col) => col.datasource_list === selectedAttribute
|
|
103
|
+
)?.attribute_key;
|
|
104
|
+
|
|
105
|
+
return selected ? dropdownData[selected] : [];
|
|
106
|
+
}, [selectedAttribute, dropdownData]);
|
|
107
|
+
|
|
13
108
|
return (
|
|
14
|
-
<Box
|
|
15
|
-
{
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
109
|
+
<Box
|
|
110
|
+
sx={{
|
|
111
|
+
display: "flex",
|
|
112
|
+
flexDirection: "column",
|
|
113
|
+
gap: "1.25rem",
|
|
114
|
+
}}
|
|
115
|
+
>
|
|
116
|
+
<FormControl fullWidth size="small">
|
|
117
|
+
<Select
|
|
118
|
+
value={selectedAttribute || ""}
|
|
119
|
+
onChange={handleSelectChange}
|
|
120
|
+
displayEmpty
|
|
121
|
+
renderValue={(selected) => {
|
|
122
|
+
if (!selected) {
|
|
123
|
+
return <span>Select Attribute</span>;
|
|
124
|
+
}
|
|
125
|
+
return columnsData?.column_list?.find(
|
|
126
|
+
(col) => col.datasource_list === selected
|
|
127
|
+
)?.name;
|
|
128
|
+
}}
|
|
129
|
+
sx={{
|
|
130
|
+
"& .MuiOutlinedInput-root": {
|
|
131
|
+
borderRadius: "6px",
|
|
132
|
+
fontSize: "14px",
|
|
133
|
+
bgcolor: "#fafafa",
|
|
134
|
+
"& fieldset": {
|
|
135
|
+
borderColor: "#7a5af8 !important",
|
|
136
|
+
},
|
|
137
|
+
"&:hover fieldset": {
|
|
138
|
+
borderColor: "#7a5af8 !important",
|
|
139
|
+
},
|
|
140
|
+
"&.Mui-focused fieldset": {
|
|
141
|
+
borderColor: "#7a5af8 !important",
|
|
142
|
+
boxShadow: "none",
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
"& .MuiSelect-select": {
|
|
146
|
+
padding: "8px 14px",
|
|
147
|
+
},
|
|
148
|
+
}}
|
|
149
|
+
>
|
|
150
|
+
{columnsData?.column_list
|
|
151
|
+
?.filter((column) => column.data_type.includes("select"))
|
|
152
|
+
.map((column, index) => (
|
|
153
|
+
<MenuItem
|
|
154
|
+
key={index}
|
|
155
|
+
value={column.datasource_list}
|
|
156
|
+
disabled={column.datasource_list === selectedAttribute}
|
|
157
|
+
>
|
|
158
|
+
{column.name}
|
|
159
|
+
</MenuItem>
|
|
160
|
+
))}
|
|
161
|
+
</Select>
|
|
162
|
+
</FormControl>
|
|
163
|
+
|
|
164
|
+
<Box>
|
|
165
|
+
{selectedAttribute && (
|
|
166
|
+
<CustomSearch value={searchTerm} onChange={setSearchTerm} />
|
|
167
|
+
)}
|
|
168
|
+
|
|
169
|
+
{dropdownData && (
|
|
170
|
+
<Box sx={{ mt: 2 }}>
|
|
171
|
+
<FormControl>
|
|
172
|
+
<RadioGroup
|
|
173
|
+
onChange={handleRadioChange}
|
|
174
|
+
value={currentFilterValue} // Set the value from current filter
|
|
175
|
+
>
|
|
176
|
+
{selectedAttributeOptions
|
|
177
|
+
?.filter((option) => {
|
|
178
|
+
if (!searchTerm) return true;
|
|
179
|
+
|
|
180
|
+
return option.label
|
|
181
|
+
.toLowerCase()
|
|
182
|
+
.includes(searchTerm.toLowerCase());
|
|
183
|
+
})
|
|
184
|
+
.map((option) => (
|
|
185
|
+
<FormControlLabel
|
|
186
|
+
key={option.value}
|
|
187
|
+
value={option.value}
|
|
188
|
+
control={<Radio />}
|
|
189
|
+
label={option.label}
|
|
190
|
+
/>
|
|
191
|
+
))}
|
|
192
|
+
</RadioGroup>
|
|
193
|
+
</FormControl>
|
|
194
|
+
</Box>
|
|
195
|
+
)}
|
|
196
|
+
</Box>
|
|
24
197
|
</Box>
|
|
25
198
|
);
|
|
26
199
|
};
|
|
@@ -6,20 +6,24 @@ import moment from "moment";
|
|
|
6
6
|
import { UpdatedFilterStateProps } from "../../../../../types/filter";
|
|
7
7
|
import { SxProps, Theme } from "@mui/material";
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
filter,
|
|
11
|
-
control,
|
|
12
|
-
}: {
|
|
9
|
+
type FormDatePickerProps = {
|
|
13
10
|
filter: UpdatedFilterStateProps;
|
|
14
11
|
control: any;
|
|
15
12
|
sx?: SxProps<Theme>;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
views?: Array<"year" | "month" | "day">;
|
|
14
|
+
onValueChange?: () => void;
|
|
15
|
+
};
|
|
19
16
|
|
|
17
|
+
const FormDatePicker = ({
|
|
18
|
+
filter,
|
|
19
|
+
control,
|
|
20
|
+
sx,
|
|
21
|
+
views = ["day", "month", "year"], // default to full date picker
|
|
22
|
+
onValueChange,
|
|
23
|
+
}: FormDatePickerProps) => {
|
|
20
24
|
return (
|
|
21
25
|
<Controller
|
|
22
|
-
name={`${filter?.name}.value`} //
|
|
26
|
+
name={`${filter?.name}.value`} // Use consistent field structure
|
|
23
27
|
control={control}
|
|
24
28
|
defaultValue={
|
|
25
29
|
filter.filter_value
|
|
@@ -29,25 +33,40 @@ const FormDatePicker = ({
|
|
|
29
33
|
render={({ field }) => (
|
|
30
34
|
<LocalizationProvider dateAdapter={AdapterDateFns}>
|
|
31
35
|
<DatePicker
|
|
32
|
-
sx={{
|
|
33
|
-
"& .MuiOutlinedInput-input": {
|
|
34
|
-
padding: "12px 20px",
|
|
35
|
-
},
|
|
36
|
-
}}
|
|
37
36
|
{...field}
|
|
37
|
+
views={views}
|
|
38
38
|
value={
|
|
39
39
|
field.value ? moment(field.value, "DD-MM-YYYY").toDate() : null
|
|
40
40
|
}
|
|
41
41
|
onChange={(date) => {
|
|
42
|
-
|
|
42
|
+
let formatted = "";
|
|
43
|
+
if (date) {
|
|
44
|
+
if (views?.length === 1 && views[0] === "year") {
|
|
45
|
+
formatted = moment(date).format("YYYY");
|
|
46
|
+
} else {
|
|
47
|
+
formatted = moment(date).format("DD-MM-YYYY");
|
|
48
|
+
}
|
|
49
|
+
}
|
|
43
50
|
field.onChange(formatted);
|
|
51
|
+
onValueChange?.();
|
|
52
|
+
}}
|
|
53
|
+
format={
|
|
54
|
+
views?.length === 1 && views[0] === "year" ? "yyyy" : "dd-MM-yyyy"
|
|
55
|
+
}
|
|
56
|
+
sx={{
|
|
57
|
+
"& .MuiOutlinedInput-input": {
|
|
58
|
+
padding: "12px 20px",
|
|
59
|
+
},
|
|
60
|
+
...sx,
|
|
44
61
|
}}
|
|
45
|
-
format="dd-MM-yyyy"
|
|
46
62
|
slotProps={{
|
|
47
63
|
textField: {
|
|
48
64
|
size: "small",
|
|
49
65
|
fullWidth: true,
|
|
50
|
-
placeholder:
|
|
66
|
+
placeholder:
|
|
67
|
+
views?.length === 1 && views[0] === "year"
|
|
68
|
+
? "YYYY"
|
|
69
|
+
: "DD-MM-YYYY",
|
|
51
70
|
},
|
|
52
71
|
}}
|
|
53
72
|
/>
|
|
@@ -58,3 +77,62 @@ const FormDatePicker = ({
|
|
|
58
77
|
};
|
|
59
78
|
|
|
60
79
|
export default FormDatePicker;
|
|
80
|
+
|
|
81
|
+
// import { Controller } from "react-hook-form";
|
|
82
|
+
// import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
|
|
83
|
+
// import { DatePicker } from "@mui/x-date-pickers/DatePicker";
|
|
84
|
+
// import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns";
|
|
85
|
+
// import moment from "moment";
|
|
86
|
+
// import { UpdatedFilterStateProps } from "../../../../../types/filter";
|
|
87
|
+
// import { SxProps, Theme } from "@mui/material";
|
|
88
|
+
|
|
89
|
+
// const FormDatePicker = ({
|
|
90
|
+
// filter,
|
|
91
|
+
// control,
|
|
92
|
+
// sx,
|
|
93
|
+
// }: {
|
|
94
|
+
// filter: UpdatedFilterStateProps;
|
|
95
|
+
// control: any;
|
|
96
|
+
// sx?: SxProps<Theme>;
|
|
97
|
+
// }) => {
|
|
98
|
+
// return (
|
|
99
|
+
// <Controller
|
|
100
|
+
// name={`${filter?.name}.value`} // or use a consistent structure like `filters.${index}.filter_value`
|
|
101
|
+
// control={control}
|
|
102
|
+
// defaultValue={
|
|
103
|
+
// filter.filter_value
|
|
104
|
+
// ? moment(filter.filter_value, "DD-MM-YYYY").toDate()
|
|
105
|
+
// : null
|
|
106
|
+
// }
|
|
107
|
+
// render={({ field }) => (
|
|
108
|
+
// <LocalizationProvider dateAdapter={AdapterDateFns}>
|
|
109
|
+
// <DatePicker
|
|
110
|
+
// sx={{
|
|
111
|
+
// "& .MuiOutlinedInput-input": {
|
|
112
|
+
// padding: "12px 20px",
|
|
113
|
+
// },
|
|
114
|
+
// }}
|
|
115
|
+
// {...field}
|
|
116
|
+
// value={
|
|
117
|
+
// field.value ? moment(field.value, "DD-MM-YYYY").toDate() : null
|
|
118
|
+
// }
|
|
119
|
+
// onChange={(date) => {
|
|
120
|
+
// const formatted = date ? moment(date).format("DD-MM-YYYY") : "";
|
|
121
|
+
// field.onChange(formatted);
|
|
122
|
+
// }}
|
|
123
|
+
// format="dd-MM-yyyy"
|
|
124
|
+
// slotProps={{
|
|
125
|
+
// textField: {
|
|
126
|
+
// size: "small",
|
|
127
|
+
// fullWidth: true,
|
|
128
|
+
// placeholder: "DD-MM-YYYY",
|
|
129
|
+
// },
|
|
130
|
+
// }}
|
|
131
|
+
// />
|
|
132
|
+
// </LocalizationProvider>
|
|
133
|
+
// )}
|
|
134
|
+
// />
|
|
135
|
+
// );
|
|
136
|
+
// };
|
|
137
|
+
|
|
138
|
+
// export default FormDatePicker;
|
|
@@ -11,6 +11,7 @@ interface FormDropdownProps {
|
|
|
11
11
|
}[];
|
|
12
12
|
isLoading?: boolean;
|
|
13
13
|
sx?: SxProps<Theme>;
|
|
14
|
+
onValueChange?: () => void;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
const FormDropdown = ({
|
|
@@ -19,6 +20,7 @@ const FormDropdown = ({
|
|
|
19
20
|
dropdownList,
|
|
20
21
|
isLoading = false,
|
|
21
22
|
sx,
|
|
23
|
+
onValueChange,
|
|
22
24
|
}: FormDropdownProps) => {
|
|
23
25
|
return (
|
|
24
26
|
<Controller
|
|
@@ -36,7 +38,7 @@ const FormDropdown = ({
|
|
|
36
38
|
border: "none",
|
|
37
39
|
boxShadow: "none",
|
|
38
40
|
"& .MuiSelect-icon": {
|
|
39
|
-
top: "45%",
|
|
41
|
+
top: "45%",
|
|
40
42
|
transform: "translateY(-50%)",
|
|
41
43
|
"& .MuiOutlinedInput-input": {
|
|
42
44
|
padding: "12px 20px",
|
|
@@ -45,13 +47,16 @@ const FormDropdown = ({
|
|
|
45
47
|
}}
|
|
46
48
|
disabled={isLoading}
|
|
47
49
|
disableUnderline
|
|
50
|
+
onChange={(e) => {
|
|
51
|
+
field.onChange(e); // ✅ sync with RHF
|
|
52
|
+
onValueChange?.(); // ✅ trigger debounce
|
|
53
|
+
}}
|
|
48
54
|
>
|
|
49
|
-
{dropdownList
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
))}
|
|
55
|
+
{dropdownList?.map((item, idx) => (
|
|
56
|
+
<MenuItem key={idx} value={item.value}>
|
|
57
|
+
{item.label}
|
|
58
|
+
</MenuItem>
|
|
59
|
+
))}
|
|
55
60
|
</Select>
|
|
56
61
|
</FormControl>
|
|
57
62
|
)}
|
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
List,
|
|
6
6
|
ListItem,
|
|
7
7
|
Paper,
|
|
8
|
-
ListSubheader,
|
|
9
8
|
ListItemText,
|
|
10
9
|
} from "@mui/material";
|
|
11
10
|
import { useState, useRef } from "react";
|
|
@@ -22,12 +21,16 @@ const FilterCriteria = ({
|
|
|
22
21
|
columnsData,
|
|
23
22
|
tableStates,
|
|
24
23
|
setSelectedFilters,
|
|
24
|
+
searchTerm,
|
|
25
|
+
setSearchTerm,
|
|
25
26
|
}: {
|
|
26
27
|
columnsData: FilterColumnsDataProps;
|
|
27
28
|
tableStates: CraftTableOptionsProps;
|
|
28
29
|
setSelectedFilters: React.Dispatch<
|
|
29
30
|
React.SetStateAction<UpdatedFilterStateProps[]>
|
|
30
31
|
>;
|
|
32
|
+
searchTerm: string;
|
|
33
|
+
setSearchTerm: React.Dispatch<React.SetStateAction<string>>;
|
|
31
34
|
}) => {
|
|
32
35
|
const FilterButton = styled(Button)(({ theme }) => ({
|
|
33
36
|
borderRadius: 20,
|
|
@@ -112,11 +115,10 @@ const FilterCriteria = ({
|
|
|
112
115
|
{showFilterOptions && (
|
|
113
116
|
<Paper
|
|
114
117
|
sx={{
|
|
115
|
-
mt: 2,
|
|
116
118
|
width: filterButtonRef.current?.offsetWidth || 360, // Dynamic width based on button
|
|
117
119
|
p: 1,
|
|
118
|
-
|
|
119
|
-
overflowY: "auto",
|
|
120
|
+
mt: 2,
|
|
121
|
+
// overflowY: "auto",
|
|
120
122
|
cursor: "pointer",
|
|
121
123
|
position: "absolute",
|
|
122
124
|
zIndex: 1300,
|
|
@@ -124,46 +126,51 @@ const FilterCriteria = ({
|
|
|
124
126
|
>
|
|
125
127
|
<Box
|
|
126
128
|
sx={{
|
|
127
|
-
maxHeight: "300px", // Adjust height as needed
|
|
128
129
|
overflowY: "auto", // Enable vertical scrolling
|
|
129
130
|
width: "100%", // Adjust width as needed
|
|
130
131
|
}}
|
|
131
132
|
>
|
|
132
|
-
<List
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
133
|
+
<List>
|
|
134
|
+
<CustomSearch
|
|
135
|
+
placeholder="Filter by..."
|
|
136
|
+
value={searchTerm}
|
|
137
|
+
onChange={setSearchTerm}
|
|
138
|
+
/>
|
|
139
|
+
|
|
140
|
+
<Box
|
|
141
|
+
sx={{
|
|
142
|
+
my: 2,
|
|
143
|
+
maxHeight: `calc(100vh - 360px)`,
|
|
144
|
+
overflowY: "auto",
|
|
145
|
+
transition: "all 0.4s ease-in-out",
|
|
146
|
+
}}
|
|
147
|
+
>
|
|
148
|
+
{columnsData?.column_list
|
|
149
|
+
?.filter((column) =>
|
|
150
|
+
column.name.toLowerCase().includes(searchTerm.toLowerCase())
|
|
151
|
+
)
|
|
152
|
+
.map((column, index) => {
|
|
153
|
+
const isAlreadySelected = filters?.some(
|
|
154
|
+
(filter) =>
|
|
155
|
+
filter.filter_attribute === column.attribute_key
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
return (
|
|
159
|
+
<ListItem
|
|
160
|
+
key={index}
|
|
161
|
+
onClick={() =>
|
|
162
|
+
!isAlreadySelected && handleAddFilter(column)
|
|
163
|
+
} // Prevent click if already selected
|
|
164
|
+
sx={{
|
|
165
|
+
opacity: isAlreadySelected ? 0.5 : 1,
|
|
166
|
+
cursor: isAlreadySelected ? "not-allowed" : "pointer",
|
|
167
|
+
}}
|
|
168
|
+
>
|
|
169
|
+
<ListItemText primary={column.name} />
|
|
170
|
+
</ListItem>
|
|
171
|
+
);
|
|
172
|
+
})}
|
|
173
|
+
</Box>
|
|
167
174
|
</List>
|
|
168
175
|
</Box>
|
|
169
176
|
</Paper>
|
|
@@ -8,11 +8,13 @@ const FormMultiSelect = ({
|
|
|
8
8
|
control,
|
|
9
9
|
dropdownData,
|
|
10
10
|
sx,
|
|
11
|
+
onValueChange,
|
|
11
12
|
}: {
|
|
12
13
|
filter: UpdatedFilterStateProps;
|
|
13
14
|
control: any;
|
|
14
15
|
dropdownData: Record<string, DropdownOption[]>;
|
|
15
16
|
sx?: SxProps<Theme>;
|
|
17
|
+
onValueChange?: () => void;
|
|
16
18
|
}) => {
|
|
17
19
|
const options = dropdownData[filter.filter_attribute] || [];
|
|
18
20
|
|
|
@@ -32,7 +34,10 @@ const FormMultiSelect = ({
|
|
|
32
34
|
}}
|
|
33
35
|
multiple
|
|
34
36
|
value={field.value || []}
|
|
35
|
-
onChange={(e) =>
|
|
37
|
+
onChange={(e) => {
|
|
38
|
+
field.onChange(e.target.value);
|
|
39
|
+
onValueChange?.();
|
|
40
|
+
}}
|
|
36
41
|
renderValue={(selected: string[]) =>
|
|
37
42
|
selected
|
|
38
43
|
.map(
|