ui-soxo-bootstrap-core 2.6.1-dev.11 → 2.6.1-dev.13

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.
@@ -1,137 +1,20 @@
1
1
 
2
-
3
- // import React, { useState, useEffect, useRef } from "react";
4
- // import { Select, Checkbox, Input, Spin } from "antd";
5
- // import { CoreScripts } from "../../../../../models";
6
-
7
- // const { Search } = Input;
8
-
9
- // export default function AdvancedSearchSelect({ field, value = [], onChange }) {
10
- // const [searchResults, setSearchResults] = useState([]); // only API results
11
- // const [selectedItems, setSelectedItems] = useState(value); // persisted selections
12
- // const [loading, setLoading] = useState(false);
13
- // const debounceRef = useRef(null);
14
-
15
- // // Sync selectedItems if parent value changes externally
16
- // useEffect(() => {
17
- // setSelectedItems(value);
18
- // }, [value]);
19
-
20
- // const loadOptions = async (searchText = "") => {
21
- // try {
22
- // setLoading(true);
23
-
24
- // let query = field?.search_query || "";
25
- // query = query.replace("@search_text;", searchText || "");
26
-
27
- // const res = await CoreScripts.getQuery({ script: query });
28
- // const data = Array.isArray(res) ? res[0] : [];
29
- // const apiValues = data?.map((r) => r[field.field]) || [];
30
-
31
- // setSearchResults(apiValues);
32
- // } catch (error) {
33
- // console.error("Search API error", error);
34
- // } finally {
35
- // setLoading(false);
36
- // }
37
- // };
38
-
39
- // useEffect(() => {
40
- // loadOptions("");
41
- // }, [field]);
42
-
43
- // const handleSearch = (text) => {
44
- // if (debounceRef.current) clearTimeout(debounceRef.current);
45
- // debounceRef.current = setTimeout(() => loadOptions(text), 400);
46
- // };
47
-
48
- // const toggleValue = (checked, item) => {
49
- // let newValues;
50
-
51
- // if (checked) {
52
- // newValues = [...selectedItems, item];
53
- // } else {
54
- // newValues = selectedItems.filter((v) => v !== item);
55
- // }
56
-
57
- // setSelectedItems(newValues); // update local persisted state immediately
58
- // onChange(newValues);
59
- // };
60
-
61
- // // Merge: selected items always on top, then search results (excluding already selected)
62
- // const displayOptions = [
63
- // ...selectedItems,
64
- // ...searchResults.filter((item) => !selectedItems.includes(item)),
65
- // ];
66
-
67
- // return (
68
- // <Select
69
- // mode="multiple"
70
- // value={value}
71
- // style={{ width: 250 }}
72
- // placeholder={field.caption}
73
- // allowClear
74
- // maxTagCount={0}
75
- // onChange={onChange}
76
- // maxTagPlaceholder={() => (
77
- // <span style={{ display: "flex", alignItems: "center", gap: 8 }}>
78
- // {field.caption}
79
- // <span
80
- // style={{
81
- // background: "#e6f0ff",
82
- // color: "#1677ff",
83
- // borderRadius: "10px",
84
- // padding: "0 8px",
85
- // fontWeight: 600,
86
- // fontSize: 12,
87
- // }}
88
- // >
89
- // {value?.length || 0}
90
- // </span>
91
- // </span>
92
- // )}
93
- // dropdownRender={() => (
94
- // <div style={{ padding: 10 }}>
95
- // <Search
96
- // placeholder={`Search ${field.caption}`}
97
- // onChange={(e) => handleSearch(e.target.value)}
98
- // />
99
-
100
- // <div style={{ maxHeight: 200, overflowY: "auto", marginTop: 10 }}>
101
- // {loading ? (
102
- // <Spin />
103
- // ) : (
104
- // displayOptions.map((item) => (
105
- // <div key={item} style={{ marginBottom: 6 }}>
106
- // <Checkbox
107
- // checked={selectedItems.includes(item)}
108
- // onChange={(e) => toggleValue(e.target.checked, item)}
109
- // >
110
- // {item}
111
- // </Checkbox>
112
- // </div>
113
- // ))
114
- // )}
115
- // </div>
116
- // </div>
117
- // )}
118
- // />
119
- // );
120
- // }
121
-
122
2
  import React, { useState, useEffect, useRef } from "react";
123
3
  import { Select, Checkbox, Input, Spin } from "antd";
124
4
  import { CoreScripts } from "../../../../../models";
5
+ import "./advance-search.scss";
125
6
 
126
7
  const { Search } = Input;
127
8
 
128
- export default function AdvancedSearchSelect({ field, value = [], onChange }) {
129
- const [searchResults, setSearchResults] = useState([]); // only API results
130
- const [selectedItems, setSelectedItems] = useState(value); // persisted selections
9
+ export default function AdvancedSearchSelect({ reportId, field, value = [], onChange ,onReset}) {
10
+
11
+ const isSearchQuery = !!field.search_query;
12
+
13
+ const [searchResults, setSearchResults] = useState([]);
14
+ const [selectedItems, setSelectedItems] = useState(value);
131
15
  const [loading, setLoading] = useState(false);
132
16
  const debounceRef = useRef(null);
133
17
 
134
- // Sync selectedItems if parent value changes externally
135
18
  useEffect(() => {
136
19
  setSelectedItems(value);
137
20
  }, [value]);
@@ -140,11 +23,14 @@ export default function AdvancedSearchSelect({ field, value = [], onChange }) {
140
23
  try {
141
24
  setLoading(true);
142
25
 
143
- let query = field?.search_query || "";
144
- query = query.replace("@search_text;", searchText || "");
26
+ const formBody = {
27
+ script_id: reportId,
28
+ search_field: field.field,
29
+ search_condition: searchText,
30
+ };
145
31
 
146
- const res = await CoreScripts.getQuery({ script: query });
147
- const data = Array.isArray(res) ? res[0] : [];
32
+ const res = await CoreScripts.getQuerySeacch(formBody);
33
+ const data = Array.isArray(res.data) ? res.data : [];
148
34
  const apiValues = data?.map((r) => r[field.field]) || [];
149
35
 
150
36
  setSearchResults(apiValues);
@@ -156,7 +42,7 @@ export default function AdvancedSearchSelect({ field, value = [], onChange }) {
156
42
  };
157
43
 
158
44
  useEffect(() => {
159
- loadOptions("");
45
+ if (isSearchQuery) loadOptions("");
160
46
  }, [field]);
161
47
 
162
48
  const handleSearch = (text) => {
@@ -167,11 +53,8 @@ export default function AdvancedSearchSelect({ field, value = [], onChange }) {
167
53
  const toggleValue = (checked, item) => {
168
54
  let newValues;
169
55
 
170
- if (checked) {
171
- newValues = [...selectedItems, item];
172
- } else {
173
- newValues = selectedItems.filter((v) => v !== item);
174
- }
56
+ if (checked) newValues = [...selectedItems, item];
57
+ else newValues = selectedItems.filter((v) => v !== item);
175
58
 
176
59
  setSelectedItems(newValues);
177
60
  onChange(newValues);
@@ -180,53 +63,67 @@ export default function AdvancedSearchSelect({ field, value = [], onChange }) {
180
63
  const handleReset = () => {
181
64
  setSelectedItems([]);
182
65
  onChange([]);
66
+ // if (onReset) {
67
+ onReset(); // 🔥 trigger dashboard refresh
68
+ // }
183
69
  };
184
70
 
185
- // Merge: selected items always on top, then search results
186
71
  const displayOptions = [
187
72
  ...selectedItems,
188
73
  ...searchResults.filter((item) => !selectedItems.includes(item)),
189
74
  ];
190
75
 
76
+ const isActive = value && value.length > 0;
77
+
78
+ // -------- INPUT MODE --------
79
+ if (!isSearchQuery) {
80
+ return (
81
+ <Input
82
+ className={`advanced-search-input ${isActive ? "advanced-search-active" : ""}`}
83
+ placeholder={`Search ${field.caption}`}
84
+ // The parent provides an array for `value`.
85
+ // We take the first element for the input's display value.
86
+ value={value[0] || ""}
87
+ onChange={(e) => {
88
+ const text = e.target.value;
89
+ // Always pass an array back to the parent to be consistent with the Select mode.
90
+ onChange(text ? [text] : []);
91
+ }}
92
+ />
93
+ );
94
+ }
95
+
96
+ // -------- SELECT MODE --------
191
97
  return (
192
98
  <Select
99
+ className={`advanced-search-select ${isActive ? "advanced-search-active" : ""}`}
193
100
  mode="multiple"
194
101
  value={value}
195
- style={{ width: 250 }}
196
102
  placeholder={field.caption}
197
103
  allowClear
198
104
  maxTagCount={0}
199
105
  onChange={onChange}
200
106
  maxTagPlaceholder={() => (
201
- <span style={{ display: "flex", alignItems: "center", gap: 8 }}>
107
+ <span className="tag-placeholder">
202
108
  {field.caption}
203
- <span
204
- style={{
205
- background: "#e6f0ff",
206
- color: "#1677ff",
207
- borderRadius: "10px",
208
- padding: "0 8px",
209
- fontWeight: 600,
210
- fontSize: 12,
211
- }}
212
- >
109
+ <span className="tag-placeholder-count">
213
110
  {value?.length || 0}
214
111
  </span>
215
112
  </span>
216
113
  )}
217
114
  dropdownRender={() => (
218
- <div style={{ padding: 10 }}>
115
+ <div className="dropdown-content">
219
116
  <Search
220
117
  placeholder={`Search ${field.caption}`}
221
118
  onChange={(e) => handleSearch(e.target.value)}
222
119
  />
223
120
 
224
- <div style={{ maxHeight: 200, overflowY: "auto", marginTop: 10 }}>
121
+ <div className="dropdown-options-list">
225
122
  {loading ? (
226
123
  <Spin />
227
124
  ) : (
228
125
  displayOptions.map((item) => (
229
- <div key={item} style={{ marginBottom: 6 }}>
126
+ <div key={item} className="dropdown-option-item">
230
127
  <Checkbox
231
128
  checked={selectedItems.includes(item)}
232
129
  onChange={(e) => toggleValue(e.target.checked, item)}
@@ -238,24 +135,8 @@ export default function AdvancedSearchSelect({ field, value = [], onChange }) {
238
135
  )}
239
136
  </div>
240
137
 
241
- {/* Reset Button */}
242
- <div
243
- style={{
244
- display: "flex",
245
- justifyContent: "flex-end",
246
- marginTop: 10,
247
- borderTop: "1px solid #f0f0f0",
248
- paddingTop: 8,
249
- }}
250
- >
251
- <span
252
- style={{
253
- color: "#1677ff",
254
- cursor: "pointer",
255
- fontWeight: 500,
256
- }}
257
- onClick={handleReset}
258
- >
138
+ <div className="dropdown-footer">
139
+ <span className="dropdown-reset-button" onClick={handleReset}>
259
140
  Reset
260
141
  </span>
261
142
  </div>
@@ -0,0 +1,76 @@
1
+ // .advanced-search-select,
2
+ /* Base select width */
3
+ .advanced-search-select {
4
+ width: 160px;
5
+ }
6
+ .advanced-search-input {
7
+ width: 160px;
8
+ }
9
+ /* Active state (when value selected) */
10
+ .advanced-search-select.advanced-search-active .ant-select-selector {
11
+ border-color: #1677ff !important;
12
+ box-shadow: 0 0 0 2px rgba(22, 119, 255, 0.2) !important;
13
+ border-radius: 6px !important;
14
+ }
15
+
16
+ /* Input active state */
17
+ .advanced-search-input.advanced-search-active {
18
+ border-color: #1677ff !important;
19
+ box-shadow: 0 0 0 2px rgba(22, 119, 255, 0.2);
20
+ border-radius: 6px;
21
+ }
22
+ // .advanced-search-input {
23
+ // width: 250px;
24
+
25
+ // &.advanced-search-active {
26
+ // // Antd Select and Input don't share the same border-radius property,
27
+ // // so we apply a wrapper style that works for both.
28
+ // // For more specific control, you might need to target internal antd classes.
29
+ // border: 1px solid #91caff !important;
30
+ // box-shadow: 0 0 0 1px #91caff;
31
+ // border-radius: 6px;
32
+ // }
33
+ // }
34
+
35
+ .tag-placeholder {
36
+ display: flex;
37
+ align-items: center;
38
+ gap: 8px;
39
+
40
+ .tag-placeholder-count {
41
+ background: #e6f0ff;
42
+ color: #1677ff;
43
+ border-radius: 10px;
44
+ padding: 0 8px;
45
+ font-weight: 600;
46
+ font-size: 12px;
47
+ }
48
+ }
49
+
50
+ .dropdown-content {
51
+ padding: 10px;
52
+
53
+ .dropdown-options-list {
54
+ max-height: 200px;
55
+ overflow-y: auto;
56
+ margin-top: 10px;
57
+
58
+ .dropdown-option-item {
59
+ margin-bottom: 6px;
60
+ }
61
+ }
62
+
63
+ .dropdown-footer {
64
+ display: flex;
65
+ justify-content: flex-end;
66
+ margin-top: 10px;
67
+ border-top: 1px solid #f0f0f0;
68
+ padding-top: 8px;
69
+
70
+ .dropdown-reset-button {
71
+ color: #1677ff;
72
+ cursor: pointer;
73
+ font-weight: 500;
74
+ }
75
+ }
76
+ }