@visns-studio/visns-components 4.5.7 → 4.5.8

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,4 +1,4 @@
1
- import React, { useEffect, useState } from 'react';
1
+ import React, { useEffect, useRef, useState, useCallback } from 'react';
2
2
  import { Link, useLocation, useNavigate } from 'react-router-dom';
3
3
  import {
4
4
  ArrowCycle,
@@ -31,6 +31,7 @@ import {
31
31
  Person,
32
32
  Question,
33
33
  QuestionFill,
34
+ Search,
34
35
  SettingsVertical,
35
36
  ShippingBoxV1,
36
37
  SignOut,
@@ -44,16 +45,178 @@ import CustomFetch from './Fetch';
44
45
  import Notification from './Notification';
45
46
  import styles from './styles/Navigation.module.css';
46
47
 
48
+ const SearchComponent = ({
49
+ navigate,
50
+ search,
51
+ setSearch,
52
+ searchResultShow,
53
+ searchResult,
54
+ setSearchResultShow,
55
+ setSearchResult,
56
+ navConfig,
57
+ }) => {
58
+ const searchWrapperRef = useRef(null);
59
+
60
+ const handleClickSearch = (url) => {
61
+ if (url) {
62
+ setSearchResultShow(false);
63
+ navigate(url);
64
+ }
65
+ };
66
+
67
+ const handleKeyPress = (e) => {
68
+ if (e.key === 'Enter') {
69
+ fetchSearchResult();
70
+ }
71
+ };
72
+
73
+ const handleSearch = (e) => {
74
+ e.preventDefault();
75
+ fetchSearchResult();
76
+ };
77
+
78
+ const handleSearchChange = (e) => {
79
+ setSearch(e.target.value);
80
+ };
81
+
82
+ const fetchSearchResult = useCallback(async () => {
83
+ try {
84
+ if (search.trim() === '') {
85
+ setSearchResultShow(false);
86
+ return;
87
+ }
88
+
89
+ const res = await CustomFetch(navConfig.search.url, 'POST', {
90
+ search,
91
+ });
92
+
93
+ if (res.data) {
94
+ const updatedSearchResult = searchResult.map((searchItem) => {
95
+ const newData = res.data[searchItem.id] || [];
96
+ return {
97
+ ...searchItem,
98
+ data: newData,
99
+ };
100
+ });
101
+
102
+ setSearchResult(updatedSearchResult);
103
+ setSearchResultShow(true);
104
+ }
105
+ } catch (err) {
106
+ console.error(err);
107
+ }
108
+ }, [
109
+ search,
110
+ navConfig.search.url,
111
+ searchResult,
112
+ setSearchResult,
113
+ setSearchResultShow,
114
+ ]);
115
+
116
+ useEffect(() => {
117
+ const handleClickOutside = (event) => {
118
+ if (
119
+ searchWrapperRef.current &&
120
+ !searchWrapperRef.current.contains(event.target)
121
+ ) {
122
+ setSearchResultShow(false);
123
+ }
124
+ };
125
+
126
+ document.addEventListener('mousedown', handleClickOutside);
127
+ return () => {
128
+ document.removeEventListener('mousedown', handleClickOutside);
129
+ };
130
+ }, [searchWrapperRef, setSearchResultShow]);
131
+
132
+ const getNestedValues = (obj, keys) => {
133
+ return keys
134
+ .map((key) => obj[key])
135
+ .filter((value) => value)
136
+ .join(' ');
137
+ };
138
+
139
+ return (
140
+ <div className={styles.globalsearch} ref={searchWrapperRef}>
141
+ <input
142
+ type="text"
143
+ placeholder="Search"
144
+ value={search}
145
+ onChange={handleSearchChange}
146
+ onKeyDown={handleKeyPress}
147
+ />
148
+ {searchResultShow && (
149
+ <ul
150
+ className={styles['AutocompletePlace-results']}
151
+ style={{ marginTop: '40px' }}
152
+ >
153
+ {searchResult.length > 0 &&
154
+ searchResult.map(
155
+ (searchItem, searchItemKey) =>
156
+ searchItem.data.length > 0 && (
157
+ <React.Fragment
158
+ key={`search-category-${searchItem.id}-${searchItemKey}`}
159
+ >
160
+ <li
161
+ className={
162
+ styles[
163
+ 'AutocompletePlace-items'
164
+ ]
165
+ }
166
+ >
167
+ <strong>{searchItem.label}</strong>
168
+ </li>
169
+ <ul>
170
+ {searchItem.data.map((item) => (
171
+ <li
172
+ key={`${searchItemKey}-${item.id}`}
173
+ className={
174
+ styles[
175
+ 'AutocompletePlace-items'
176
+ ]
177
+ }
178
+ onClick={() => {
179
+ handleClickSearch(
180
+ `${searchItem.url}${item.id}`
181
+ );
182
+ }}
183
+ data-type={searchItem.id}
184
+ data-id={item.id}
185
+ >
186
+ {getNestedValues(
187
+ item,
188
+ searchItem.key
189
+ )}
190
+ </li>
191
+ ))}
192
+ </ul>
193
+ </React.Fragment>
194
+ )
195
+ )}
196
+ </ul>
197
+ )}
198
+ <button onClick={handleSearch}>
199
+ <Search strokeWidth={2} size={36} />
200
+ </button>
201
+ </div>
202
+ );
203
+ };
204
+
47
205
  function Navigation({
48
206
  children,
49
207
  layout = 'full',
50
208
  logo,
51
209
  navConfig,
52
- searchComponent,
53
210
  setSystemAuth,
54
211
  themeType,
55
212
  userProfile,
56
213
  }) {
214
+ const [search, setSearch] = useState('');
215
+ const [searchResultShow, setSearchResultShow] = useState(false);
216
+ const [searchResult, setSearchResult] = useState(
217
+ navConfig.search?.tables || []
218
+ );
219
+
57
220
  const location = useLocation();
58
221
  const navigate = useNavigate();
59
222
  const currentPage = location.pathname.substr(1) || 'dashboard';
@@ -61,7 +224,6 @@ function Navigation({
61
224
  const [isScrolled, setIsScrolled] = useState(false);
62
225
  const [navData, setNavData] = useState(navConfig);
63
226
 
64
- // const appNavClasses = isScrolled ? styles['app-nav'] : styles['app-nav'];
65
227
  const appNavClasses = styles['app-nav'];
66
228
 
67
229
  const handleLogout = () => {
@@ -150,6 +312,7 @@ function Navigation({
150
312
  peopleMultiple: PeopleMultiple,
151
313
  question: Question,
152
314
  questionFill: QuestionFill,
315
+ search: Search,
153
316
  settingsVertical: SettingsVertical,
154
317
  signOut: SignOut,
155
318
  shippingBoxV1: ShippingBoxV1,
@@ -160,6 +323,7 @@ function Navigation({
160
323
  };
161
324
 
162
325
  const IconComponent = iconComponents[n.icon];
326
+
163
327
  let navItemClasses;
164
328
 
165
329
  if (n.class.includes('active')) {
@@ -366,7 +530,19 @@ function Navigation({
366
530
  </aside>
367
531
  <main className={styles.content}>
368
532
  <div className={styles['content-header']}>
369
- {searchComponent}
533
+ {navConfig.search?.enable === true && (
534
+ <SearchComponent
535
+ navigate={navigate}
536
+ search={search}
537
+ setSearch={setSearch}
538
+ searchResultShow={searchResultShow}
539
+ searchResult={searchResult}
540
+ setSearchResultShow={setSearchResultShow}
541
+ setSearchResult={setSearchResult}
542
+ navConfig={navConfig}
543
+ />
544
+ )}
545
+
370
546
  <div className={styles['content-title']}>
371
547
  <button
372
548
  className={
@@ -900,3 +900,79 @@
900
900
  padding: 0 1rem;
901
901
  }
902
902
  }
903
+
904
+ .globalsearch {
905
+ display: flex;
906
+ flex-wrap: nowrap;
907
+ align-content: center;
908
+ width: 50%;
909
+
910
+ button {
911
+ width: max-content;
912
+ padding: 0.15rem 0.65rem;
913
+ margin: 0 0.5rem;
914
+ border: none;
915
+ background: var(--primary-color);
916
+ appearance: none;
917
+ border-radius: 0.375rem;
918
+
919
+ svg {
920
+ display: block;
921
+ color: white;
922
+ width: 100%;
923
+ max-width: 20px;
924
+ }
925
+ }
926
+ }
927
+
928
+ .AutocompletePlace-results {
929
+ z-index: 999;
930
+ }
931
+
932
+ .AutocompletePlace {
933
+ position: relative;
934
+
935
+ > svg {
936
+ position: absolute;
937
+ right: 0.5em;
938
+ top: 0.5em;
939
+ color: var(--paragraph-color);
940
+ cursor: pointer;
941
+ }
942
+
943
+ .toggleActive {
944
+ color: var(--highlight-color);
945
+ }
946
+ }
947
+
948
+ .AutocompletePlace-input {
949
+ padding: 0.65rem 3rem 0.65rem 0.95rem !important;
950
+ height: 38px;
951
+ }
952
+
953
+ .AutocompletePlace-results {
954
+ width: 400px;
955
+ position: absolute;
956
+ background-color: white;
957
+ padding: 0;
958
+ margin: 0;
959
+ border: 1px solid rgba(var(--primary-color), 0.25);
960
+ border-radius: var(--br);
961
+ overflow: hidden;
962
+
963
+ ul {
964
+ padding: 0;
965
+ margin: 0;
966
+ }
967
+ }
968
+
969
+ .AutocompletePlace-items {
970
+ list-style: none;
971
+ border-bottom: 1px solid rgba(var(--primary-color-rgb), 0.1);
972
+ cursor: pointer;
973
+ padding: 10px 10px;
974
+ }
975
+
976
+ .AutocompletePlace-items:hover {
977
+ background-color: rgba(var(--paragraph-color-rgb), 0.065);
978
+ }
package/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "axios": "^1.7.2",
15
15
  "dayjs": "^1.11.12",
16
16
  "file-saver": "^2.0.5",
17
- "framer-motion": "^11.3.18",
17
+ "framer-motion": "^11.3.19",
18
18
  "html-react-parser": "^5.1.12",
19
19
  "lodash": "^4.17.21",
20
20
  "lodash.debounce": "^4.0.8",
@@ -58,7 +58,7 @@
58
58
  "react-dom": "^17.0.1"
59
59
  },
60
60
  "name": "@visns-studio/visns-components",
61
- "version": "4.5.7",
61
+ "version": "4.5.8",
62
62
  "description": "Various packages to assist in the development of our Custom Applications.",
63
63
  "main": "index.js",
64
64
  "scripts": {