rez-table-listing-mui 0.0.25 → 0.0.26

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 +101 -8
  4. package/dist/index.js +1 -1
  5. package/dist/index.mjs +1 -1
  6. package/package.json +6 -10
  7. package/src/App.tsx +172 -129
  8. package/src/assets/svg.tsx +33 -2
  9. package/src/components/common/confirm-modal/index.tsx +200 -0
  10. package/src/components/filter/components/attributes-filter.tsx +26 -0
  11. package/src/components/filter/components/forms/components/Attributes-select.tsx +180 -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 +424 -0
  20. package/src/components/filter/components/main-filter.tsx +53 -0
  21. package/src/components/filter/components/saved-edit-filter.tsx +101 -0
  22. package/src/components/filter/components/saved-filter.tsx +148 -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 +52 -0
  26. package/src/components/filter/index.tsx +258 -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 +211 -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
package/src/App.tsx CHANGED
@@ -1,103 +1,119 @@
1
1
  import { useEffect, useMemo, useState } from "react";
2
2
  import { useCraftTable } from "./libs/hooks/useCraftTable";
3
3
  import { TableTabs } from "./components/tabs";
4
- import { makeData, Person } from "./libs/utils/make-hierar-data";
5
4
  import { useDefaultColumns } from "./libs/hooks/useDefaultColumns";
6
5
  import TableWrapper from "./components/index-table";
7
- import Papa from "papaparse";
8
- import { DataFormat } from "./libs/utils/Data-format";
6
+ import { entityTableMetaMaster } from "./libs/utils/apiColumn";
7
+ import {
8
+ useCommonDropdownAPI,
9
+ useDeleteFilterAPI,
10
+ useEntityTableAPI,
11
+ useSavedFilterAPI,
12
+ useUpdateFilterAPI,
13
+ } from "./libs/hooks/useEntityTableAPI";
14
+ import {
15
+ useDetailsQueryAPI,
16
+ useFetchData,
17
+ } from "./libs/hooks/useEntityTableHooks";
18
+ import LoginButton from "./components/login";
19
+ // import { ENTITY_TYPE } from "./libs/utils/common";
9
20
 
10
21
  function App() {
11
22
  const [mockLoading, setMockLoading] = useState<boolean>(true);
12
- const [activeTab, setActiveTab] = useState<string>("ALL");
13
- const [jsonData, setJsonData] = useState<any[]>([]);
23
+ // const [jsonData] = useState<any[]>([]);
14
24
  const [columns, setColumns] = useState<any[]>([]);
15
- const [metadata, setMetadata] = useState<any[]>([]);
16
25
  const [searchTerm, setSearchTerm] = useState("");
26
+ // const [data, setData] = useState<Person[]>(() => makeData(50, 3, 2));
27
+ // const [entity_type] = useState(ENTITY_TYPE); //OR UPR BRD
28
+
29
+ const [selectedTab, setSelectedTab] = useState("ALL");
30
+
31
+ const tableStates = useCraftTable();
32
+ const { filters, setFilters, filterMaster, filterToDelete } = tableStates;
17
33
 
18
- //To handle hierarchical data
19
34
  const { defaultColumns } = useDefaultColumns();
20
- const [data, setData] = useState<Person[]>(() => makeData(50, 3, 2));
35
+
36
+ const { metaQuery } = useFetchData("UPR");
37
+ const { detailsQuery } = useDetailsQueryAPI(
38
+ filterMaster?.saved_filters?.selectedId
39
+ ? filterMaster?.saved_filters?.selectedId
40
+ : metaQuery?.data?.default_filter?.value
41
+ );
42
+
43
+ //API CALL FOR SAVED FILTER
44
+ const { savedMutation } = useSavedFilterAPI();
45
+
46
+ //API FOR DELETING FILTER
47
+ const { deleteMutation } = useDeleteFilterAPI();
48
+
49
+ //API FOR UPDATE FILTER
50
+ const { updateMutation } = useUpdateFilterAPI();
51
+
52
+ // const { dropdownData } = useCommonDropdownAPI(
53
+ // metaQuery.data,
54
+ // tableStates.filterMaster?.attributes?.selected
55
+ // );
56
+
57
+ const { dropdownData } = useCommonDropdownAPI(metaQuery.data);
21
58
 
22
59
  useEffect(() => {
23
60
  setTimeout(() => {
24
61
  setMockLoading(false);
25
62
  }, 1000);
63
+
64
+ const fetchMeta = async () => {
65
+ try {
66
+ const { res } = await entityTableMetaMaster("UPR");
67
+ setColumns(res);
68
+ } catch (error) {
69
+ console.error("Failed to fetch metadata:", error);
70
+ }
71
+ };
72
+
73
+ fetchMeta();
26
74
  }, []);
27
75
 
28
- const tableStates = useCraftTable();
76
+ useEffect(() => {
77
+ setFilters(detailsQuery.data ?? []);
78
+ }, [detailsQuery.data]);
29
79
 
30
- const handleMetadataUpload = (event: React.ChangeEvent<HTMLInputElement>) => {
31
- const file = event.target.files?.[0];
32
- if (!file) return;
33
-
34
- Papa.parse(file, {
35
- delimiter: ",",
36
- header: true,
37
- skipEmptyLines: true,
38
- complete: (result: any) => {
39
- const meta = result.data as {
40
- header: string;
41
- accessorKey: string;
42
- id: "string";
43
- size: "number";
44
- align: "string";
45
- }[];
46
- setMetadata(meta);
47
-
48
- const dynamicColumns = meta.map(
49
- ({ header, accessorKey, size, align }) => ({
50
- header,
51
- id: header,
52
- accessorKey,
53
- size: size || 200,
54
- meta: { align },
55
- })
56
- );
80
+ const enableServerSideSorting = false;
57
81
 
58
- setColumns(dynamicColumns);
82
+ const { tableData } = useEntityTableAPI({
83
+ page: 0,
84
+ size: 50,
85
+ entity_type: "UPR",
86
+ tabs: {
87
+ columnName: "status",
88
+ sortBy: "ASC",
89
+ value: "active",
90
+ },
91
+ quickFilter: tableStates.filters,
92
+ sortby: [
93
+ {
94
+ sortColum: "name",
95
+ sortType: "ASC",
59
96
  },
60
- });
61
- };
97
+ ],
98
+ attributeFilter: [],
99
+ });
62
100
 
63
- const handleFileUpload = (event: React.ChangeEvent<HTMLInputElement>) => {
64
- const file = event.target.files?.[0];
65
- if (!file) return;
66
-
67
- Papa.parse(file, {
68
- delimiter: ",",
69
- header: true,
70
- skipEmptyLines: true,
71
- complete: (result: any) => {
72
- const data = result.data as object[];
73
-
74
- const dataMap: Record<string, any> = {};
75
- data.forEach((row: any) => {
76
- const parentId = row.parentId;
77
- if (parentId) {
78
- if (!dataMap[parentId]) {
79
- dataMap[parentId] = [];
80
- }
81
- dataMap[parentId].push(row);
82
- }
83
- });
84
-
85
- const formattedData = data.map((row: any) => {
86
- let formattedRow: any = {};
87
- metadata.forEach(({ accessorKey, type }) => {
88
- formattedRow[accessorKey] = DataFormat(row[accessorKey], type);
89
- });
90
-
91
- if (dataMap[row.id]) {
92
- formattedRow.subRows = dataMap[row.id];
93
- }
94
-
95
- return formattedRow;
96
- });
97
- setJsonData(formattedData);
98
- },
99
- });
100
- };
101
+ const newData = useMemo(
102
+ () => tableData?.entity_list || [],
103
+ [tableData?.entity_list]
104
+ );
105
+ const tabsData = tableData?.entity_tabs;
106
+
107
+ const totalCount = useMemo(() => {
108
+ return Number(
109
+ tableData?.entity_tabs?.find((tab) => {
110
+ const activeTab = selectedTab || "ALL";
111
+ return (
112
+ tab.tab_value?.toLocaleLowerCase() === activeTab.toLocaleLowerCase()
113
+ );
114
+ })?.tab_value_count || "0"
115
+ );
116
+ }, [tableData, selectedTab]);
101
117
 
102
118
  const handleRenderStatus = ({ value }: any) => {
103
119
  const statusValue = value?.toUpperCase();
@@ -119,57 +135,80 @@ function App() {
119
135
  };
120
136
 
121
137
  const handleRenderAction = ({ row }: any) => {
122
- return (
123
- <button
124
- onClick={() => {
125
- alert(JSON.stringify(row));
126
- }}
127
- >
128
- Edit
129
- </button>
130
- );
138
+ return <button onClick={() => alert(JSON.stringify(row))}>Edit</button>;
131
139
  };
132
140
 
133
- const entity_tabs = [
134
- {
135
- tab_value: "Active",
136
- tab_value_count: "5",
137
- },
138
- {
139
- tab_value: "INACTIVE",
140
- tab_value_count: "4",
141
- },
142
- {
143
- tab_value: "ALL",
144
- tab_value_count: 9,
145
- },
146
- ];
147
-
148
- console.log("+++", handleFileUpload, handleMetadataUpload, setData);
149
-
150
- const rawData = useMemo(() => {
151
- return jsonData && jsonData.length > 0 ? jsonData : data;
152
- }, [jsonData, data]);
153
-
154
141
  const filteredData = useMemo(() => {
155
- if (!searchTerm) return rawData;
142
+ if (!searchTerm) return newData;
156
143
 
157
- return rawData.filter((row) =>
144
+ return newData.filter((row: any) =>
158
145
  Object.values(row)
159
146
  .join(" ")
160
147
  .toLowerCase()
161
148
  .includes(searchTerm.toLowerCase())
162
149
  );
163
- }, [rawData, searchTerm]);
150
+ }, [newData, searchTerm]);
151
+
152
+ // API to handle saving a filter
153
+ const handleSaveFilter = (name: string) => {
154
+ const quickFilter = filters.map((f) => ({
155
+ filter_attribute: f.filter_attribute,
156
+ filter_operator: f.filter_operator,
157
+ filter_value: f.filter_value,
158
+ }));
159
+ console.log("Quick Filter in App.tsx", quickFilter);
160
+
161
+ const payload = {
162
+ name,
163
+ is_default: false,
164
+ mapped_entity_type: "UPR", // For that entity type
165
+ status: "ACTIVE",
166
+ entity_type: "SFM", // FIXED entity type
167
+ filterDetails: quickFilter,
168
+ };
169
+ const entity_type = "SFM";
170
+ savedMutation.mutate({ entity_type, payload });
171
+ };
172
+
173
+ // API to handle removing or deleting a filter
174
+ const handleRemoveFilter = () => {
175
+ const payload = {
176
+ name: filterToDelete?.label,
177
+ id: filterToDelete?.value,
178
+ is_default: false,
179
+ mapped_entity_type: "UPR",
180
+ status: "INACTIVE",
181
+ entity_type: "SFM",
182
+ };
183
+ const entity_type = "SFM";
184
+ deleteMutation.mutate({ entity_type, payload });
185
+ };
186
+
187
+ //API to update the filter
188
+ const handleUpdateFilter = () => {
189
+ const quickFilter = filters.map((f) => ({
190
+ filter_attribute: f.filter_attribute,
191
+ filter_operator: f.filter_operator,
192
+ filter_value: f.filter_value,
193
+ }));
194
+ console.log("Quick Filter in App.tsx", quickFilter);
195
+
196
+ const payload = {
197
+ name: filterMaster?.saved_filters?.selectedName, // Name of the filter
198
+ is_default: false,
199
+ id: filterMaster?.saved_filters?.selectedId,
200
+ mapped_entity_type: "UPR",
201
+ status: "ACTIVE",
202
+ entity_type: "SFM",
203
+ filterDetails: quickFilter,
204
+ };
205
+ const entity_type = "SFM";
206
+ updateMutation.mutate({ entity_type, payload });
207
+ };
164
208
 
165
209
  return (
166
210
  <div className="app_wrapper">
167
- {/* <div>
168
- <label>Meta Upload</label>&nbsp;
169
- <input type="file" accept=".csv" onChange={handleMetadataUpload} />
170
- <label>Data Upload</label>&nbsp;
171
- <input type="file" accept=".csv" onChange={handleFileUpload} />
172
- </div> */}
211
+ <LoginButton />
173
212
 
174
213
  <TableWrapper
175
214
  data={filteredData}
@@ -178,48 +217,52 @@ function App() {
178
217
  featureOptions={{
179
218
  striped: true,
180
219
  compactTable: false,
181
- enableSorting: false,
220
+ enableSorting: !enableServerSideSorting,
182
221
  enableColumnReordering: true,
183
222
  enableColumnResizing: true,
184
223
  enableRowSelection: false,
224
+ enableServerSideSorting: enableServerSideSorting,
185
225
  }}
186
226
  loadingOptions={{
187
227
  isLoading: mockLoading,
188
228
  loaderText: "Loading, Please wait...",
189
- // loadingComponent: <Loader/>,
190
229
  }}
191
230
  topbarOptions={{
192
231
  tableStates,
193
232
  leftSideComponent: (
194
233
  <TableTabs
195
- activeTab={activeTab}
234
+ activeTab={selectedTab}
196
235
  tableStates={tableStates}
197
- tabsData={entity_tabs}
236
+ tabsData={tabsData}
198
237
  onClick={(state) => {
199
- setActiveTab(state);
238
+ setSelectedTab(state);
200
239
  }}
201
240
  />
202
241
  ),
203
242
  searchValue: searchTerm,
204
243
  onSearchChange: (val) => setSearchTerm(val),
244
+ showFilterToggle: true,
245
+ filterOptions: {
246
+ tableStates: tableStates,
247
+ columnsData: metaQuery.data || [],
248
+ defaultFilters: detailsQuery.data || [],
249
+ tableData: tableData,
250
+ dropdownData: dropdownData || [],
251
+ onDeleteFilter: handleRemoveFilter,
252
+ onSaveFilter: handleSaveFilter,
253
+ onUpdateFilter: handleUpdateFilter,
254
+ },
205
255
  }}
206
256
  paginationOptions={{
207
257
  showPagination: true,
208
258
  paginationPosition: "top",
209
259
  paginationView: "compact",
260
+ totalRows: totalCount,
210
261
  }}
211
262
  customRenderFn={{
212
263
  renderStatus: handleRenderStatus,
213
264
  renderAction: handleRenderAction,
214
265
  }}
215
- // shouldHideColumn={(accessorKey?: string) =>
216
- // accessorKey === "action" && false
217
- // }
218
- // styleOptions={{
219
- // wrapperStyle: {
220
- // maxHeight: "calc(100vh - 280px)",
221
- // },
222
- // }}
223
266
  />
224
267
  </div>
225
268
  );
@@ -170,6 +170,36 @@ export const ArrowDownUp = () => (
170
170
  />
171
171
  </svg>
172
172
  );
173
+ export const EditIcon = () => (
174
+ <svg
175
+ width="12"
176
+ height="12"
177
+ viewBox="0 0 12 12"
178
+ fill="none"
179
+ xmlns="http://www.w3.org/2000/svg"
180
+ >
181
+ <path
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
+ fill="#0E0C0B"
184
+ fill-opacity="0.4"
185
+ />
186
+ </svg>
187
+ );
188
+
189
+ export const DeleteIcon = () => (
190
+ <svg
191
+ width="20"
192
+ height="20"
193
+ viewBox="0 0 10 12"
194
+ fill="none"
195
+ xmlns="http://www.w3.org/2000/svg"
196
+ >
197
+ <path
198
+ d="M1.87183 11.6665C1.54039 11.6665 1.25667 11.5485 1.02067 11.3125C0.784667 11.0765 0.666667 10.7928 0.666667 10.4613V1.99982H0.5C0.358333 1.99982 0.239611 1.95188 0.143833 1.85599C0.0479445 1.7601 0 1.64132 0 1.49966C0 1.35788 0.0479445 1.23916 0.143833 1.14349C0.239611 1.04771 0.358333 0.999823 0.5 0.999823H3C3 0.836601 3.0575 0.69749 3.1725 0.58249C3.28739 0.467601 3.42644 0.410156 3.58967 0.410156H6.41033C6.57356 0.410156 6.71261 0.467601 6.8275 0.58249C6.9425 0.69749 7 0.836601 7 0.999823H9.5C9.64167 0.999823 9.76039 1.04777 9.85617 1.14366C9.95206 1.23955 10 1.35832 10 1.49999C10 1.64177 9.95206 1.76049 9.85617 1.85616C9.76039 1.95193 9.64167 1.99982 9.5 1.99982H9.33333V10.4613C9.33333 10.7928 9.21533 11.0765 8.97933 11.3125C8.74333 11.5485 8.45961 11.6665 8.12817 11.6665H1.87183ZM8.33333 1.99982H1.66667V10.4613C1.66667 10.5212 1.68589 10.5704 1.72433 10.6088C1.76278 10.6473 1.81194 10.6665 1.87183 10.6665H8.12817C8.18806 10.6665 8.23722 10.6473 8.27567 10.6088C8.31411 10.5704 8.33333 10.5212 8.33333 10.4613V1.99982ZM3.7695 9.33316C3.91117 9.33316 4.02989 9.28527 4.12567 9.18949C4.22133 9.0936 4.26917 8.97482 4.26917 8.83316V3.83316C4.26917 3.69149 4.22122 3.57271 4.12533 3.47682C4.02956 3.38104 3.91078 3.33316 3.769 3.33316C3.62733 3.33316 3.50861 3.38104 3.41283 3.47682C3.31717 3.57271 3.26933 3.69149 3.26933 3.83316V8.83316C3.26933 8.97482 3.31722 9.0936 3.413 9.18949C3.50889 9.28527 3.62772 9.33316 3.7695 9.33316ZM6.231 9.33316C6.37267 9.33316 6.49139 9.28527 6.58717 9.18949C6.68283 9.0936 6.73067 8.97482 6.73067 8.83316V3.83316C6.73067 3.69149 6.68278 3.57271 6.587 3.47682C6.49111 3.38104 6.37228 3.33316 6.2305 3.33316C6.08883 3.33316 5.97011 3.38104 5.87433 3.47682C5.77867 3.57271 5.73083 3.69149 5.73083 3.83316V8.83316C5.73083 8.97482 5.77878 9.0936 5.87467 9.18949C5.97044 9.28527 6.08922 9.33316 6.231 9.33316Z"
199
+ fill="#F63D68"
200
+ />
201
+ </svg>
202
+ );
173
203
 
174
204
  export const CrossSearchIcon = () => (
175
205
  <svg
@@ -634,7 +664,7 @@ export const SortingIcon = () => {
634
664
  );
635
665
  };
636
666
 
637
- export const CustomizationIcon = () => {
667
+ export const FilterationIcon = () => {
638
668
  return (
639
669
  <svg
640
670
  width="20"
@@ -796,7 +826,7 @@ export const DropDownIcon = () => {
796
826
  );
797
827
  };
798
828
 
799
- export const AddIcon = () => {
829
+ export const AddIcon = ({ ...props }) => {
800
830
  return (
801
831
  <svg
802
832
  width="10"
@@ -804,6 +834,7 @@ export const AddIcon = () => {
804
834
  viewBox="0 0 10 10"
805
835
  fill="none"
806
836
  xmlns="http://www.w3.org/2000/svg"
837
+ {...props}
807
838
  >
808
839
  <path
809
840
  d="M4.50002 5.50002H1.16669C1.02502 5.50002 0.906298 5.45208 0.81052 5.35619C0.714632 5.2603 0.666687 5.14152 0.666687 4.99985C0.666687 4.85808 0.714632 4.73935 0.81052 4.64369C0.906298 4.54791 1.02502 4.50002 1.16669 4.50002H4.50002V1.16669C4.50002 1.02502 4.54797 0.906298 4.64385 0.81052C4.73974 0.714632 4.85852 0.666687 5.00019 0.666687C5.14197 0.666687 5.26069 0.714632 5.35635 0.81052C5.45213 0.906298 5.50002 1.02502 5.50002 1.16669V4.50002H8.83335C8.97502 4.50002 9.09374 4.54797 9.18952 4.64385C9.28541 4.73974 9.33335 4.85852 9.33335 5.00019C9.33335 5.14197 9.28541 5.26069 9.18952 5.35635C9.09374 5.45213 8.97502 5.50002 8.83335 5.50002H5.50002V8.83335C5.50002 8.97502 5.45208 9.09374 5.35619 9.18952C5.2603 9.28541 5.14152 9.33335 4.99985 9.33335C4.85808 9.33335 4.73935 9.28541 4.64369 9.18952C4.54791 9.09374 4.50002 8.97502 4.50002 8.83335V5.50002Z"
@@ -0,0 +1,200 @@
1
+ import React, { useState } from "react";
2
+ import {
3
+ Dialog,
4
+ DialogTitle,
5
+ DialogContent,
6
+ DialogActions,
7
+ Typography,
8
+ TextField,
9
+ Button,
10
+ IconButton,
11
+ Box,
12
+ SxProps,
13
+ } from "@mui/material";
14
+ import CloseIcon from "@mui/icons-material/Close";
15
+ import { Theme } from "@emotion/react";
16
+
17
+ // Types for the component props
18
+ export interface ModalButton {
19
+ label: string;
20
+ onClick: (inputValue?: string) => void;
21
+ variant?: "text" | "outlined" | "contained";
22
+ color?: "primary" | "secondary" | "error" | "info" | "success" | "warning";
23
+ disabled?: boolean;
24
+ sx?: SxProps<Theme>;
25
+ }
26
+
27
+ export interface InputField {
28
+ label: string;
29
+ placeholder?: string;
30
+ required?: boolean;
31
+ type?: "text" | "email" | "password" | "number";
32
+ multiline?: boolean;
33
+ rows?: number;
34
+ defaultValue?: string;
35
+ }
36
+
37
+ export interface ConfirmModalProps {
38
+ open: boolean;
39
+ onClose: () => void;
40
+ title: string;
41
+ description?: string;
42
+ buttons: ModalButton[];
43
+ input?: InputField;
44
+ maxWidth?: "xs" | "sm" | "md" | "lg" | "xl";
45
+ fullWidth?: boolean;
46
+ }
47
+
48
+ const ConfirmModal: React.FC<ConfirmModalProps> = ({
49
+ open,
50
+ onClose,
51
+ title,
52
+ description,
53
+ buttons,
54
+ input,
55
+ maxWidth = "sm",
56
+ fullWidth = true,
57
+ }) => {
58
+ const [inputValue, setInputValue] = useState(input?.defaultValue || "");
59
+
60
+ const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
61
+ setInputValue(event.target.value);
62
+ };
63
+
64
+ const handleButtonClick = (button: ModalButton) => {
65
+ if (input) {
66
+ button.onClick(inputValue);
67
+ } else {
68
+ button.onClick();
69
+ }
70
+ setInputValue("");
71
+ };
72
+
73
+ const handleClose = () => {
74
+ setInputValue(input?.defaultValue || "");
75
+ onClose();
76
+ };
77
+
78
+ return (
79
+ <Dialog
80
+ open={open}
81
+ onClose={handleClose}
82
+ maxWidth={maxWidth}
83
+ fullWidth={fullWidth}
84
+ PaperProps={{
85
+ sx: {
86
+ borderRadius: 2,
87
+ padding: 1,
88
+ },
89
+ }}
90
+ >
91
+ <DialogTitle
92
+ sx={{
93
+ display: "flex",
94
+ justifyContent: "space-between",
95
+ alignItems: "center",
96
+ // padding: "16px 0px",
97
+ px: "0px",
98
+ marginX: "24px",
99
+ paddingBottom: description ? "18px" : "20px",
100
+ borderBottom: "1px solid #eeeeee",
101
+ }}
102
+ >
103
+ <Typography variant="h6" component="h2" fontWeight="bold">
104
+ {title}
105
+ </Typography>
106
+ <IconButton
107
+ onClick={handleClose}
108
+ size="small"
109
+ sx={{
110
+ color: "text.secondary",
111
+ }}
112
+ >
113
+ <CloseIcon />
114
+ </IconButton>
115
+ </DialogTitle>
116
+
117
+ <DialogContent sx={{ padding: "0 24px 16px 24px", mt: 2 }}>
118
+ {description && (
119
+ <Typography
120
+ variant="body2"
121
+ color="text.secondary"
122
+ sx={{ marginBottom: input ? 3 : 0 }}
123
+ >
124
+ {description}
125
+ </Typography>
126
+ )}
127
+
128
+ {input && (
129
+ <Box sx={{ marginTop: description ? 0 : 2 }}>
130
+ <Typography
131
+ variant="body2"
132
+ component="label"
133
+ sx={{
134
+ display: "block",
135
+ marginBottom: 1,
136
+ fontWeight: 500,
137
+ color: "text.primary",
138
+ }}
139
+ >
140
+ {input.label}
141
+ {input.required && (
142
+ <Typography component="span" color="error.main">
143
+ {" "}
144
+ *
145
+ </Typography>
146
+ )}
147
+ </Typography>
148
+ <TextField
149
+ fullWidth
150
+ value={inputValue}
151
+ onChange={handleInputChange}
152
+ placeholder={input.placeholder}
153
+ type={input.type || "text"}
154
+ multiline={input.multiline}
155
+ rows={input.rows}
156
+ variant="outlined"
157
+ size="small"
158
+ sx={{
159
+ "& .MuiOutlinedInput-root": {
160
+ maxWidth: 280,
161
+ borderRadius: 1,
162
+ "&.Mui-focused .MuiOutlinedInput-notchedOutline": {
163
+ border: "2px solid #7A5AF8",
164
+ },
165
+ },
166
+ }}
167
+ />
168
+ </Box>
169
+ )}
170
+ </DialogContent>
171
+
172
+ <DialogActions
173
+ sx={{
174
+ padding: "16px 24px 24px 24px",
175
+ gap: 1,
176
+ }}
177
+ >
178
+ {buttons.map((button, index) => (
179
+ <Button
180
+ key={index}
181
+ variant={button.variant || "outlined"}
182
+ color={button.color || "primary"}
183
+ sx={button.sx}
184
+ onClick={() => handleButtonClick(button)}
185
+ disabled={
186
+ button.disabled ||
187
+ (input?.required &&
188
+ !inputValue.trim() &&
189
+ button.variant === "contained")
190
+ }
191
+ >
192
+ {button.label}
193
+ </Button>
194
+ ))}
195
+ </DialogActions>
196
+ </Dialog>
197
+ );
198
+ };
199
+
200
+ export default ConfirmModal;
@@ -0,0 +1,26 @@
1
+ import { Box } from "@mui/material";
2
+ import { AttributesFilterProps } from "../../../types/filter";
3
+ import SelectAttribute from "./forms/components/Attributes-select";
4
+
5
+ const AttributesFilter = ({
6
+ columnsData,
7
+ tableStates,
8
+ dropdownData,
9
+ searchTerm,
10
+ setSearchTerm,
11
+ }: AttributesFilterProps) => {
12
+ return (
13
+ <Box>
14
+ {/* Render select Attributes */}
15
+ <SelectAttribute
16
+ columnsData={columnsData}
17
+ tableStates={tableStates}
18
+ dropdownData={dropdownData}
19
+ searchTerm={searchTerm}
20
+ setSearchTerm={setSearchTerm}
21
+ />
22
+ </Box>
23
+ );
24
+ };
25
+
26
+ export default AttributesFilter;