|
|
@@ -1,22 +1,80 @@
|
|
|
-import React, { FC, useState } from 'react';
|
|
|
+import React, {
|
|
|
+ FC, Fragment, useState, useCallback,
|
|
|
+} from 'react';
|
|
|
|
|
|
-import { AsyncTypeahead } from 'react-bootstrap-typeahead';
|
|
|
+import { AsyncTypeahead, Menu, MenuItem } from 'react-bootstrap-typeahead';
|
|
|
|
|
|
import { useSWRxUsernames } from '~/stores/user';
|
|
|
|
|
|
+
|
|
|
+const Categories = {
|
|
|
+ activeUser: 'Active User',
|
|
|
+ inactiveUser: 'Inactive User',
|
|
|
+ activitySnapshotUser: 'ActivitySnapshot User',
|
|
|
+} as const;
|
|
|
+
|
|
|
+type CategorieType = typeof Categories[keyof typeof Categories]
|
|
|
+
|
|
|
+type AllUser = {
|
|
|
+ username: string
|
|
|
+ category: CategorieType
|
|
|
+}
|
|
|
+
|
|
|
export const SearchUsernameInput: FC = () => {
|
|
|
- const [inputText, setInputText] = useState('');
|
|
|
+ const [searchKeyword, setSearchKeyword] = useState('');
|
|
|
|
|
|
const includeUserOptions = {
|
|
|
isIncludeActiveUser: true,
|
|
|
isIncludeInactiveUser: true,
|
|
|
isIncludeActivitySnapshotUser: true,
|
|
|
};
|
|
|
- const { data: usernameData, error } = useSWRxUsernames(inputText, 0, 3, includeUserOptions);
|
|
|
+ const { data: usernameData, error } = useSWRxUsernames(searchKeyword, 0, 5, includeUserOptions);
|
|
|
+ const activeUsernames = usernameData?.activeUser?.usernames != null ? usernameData.activeUser.usernames : [];
|
|
|
+ const inactiveUsernames = usernameData?.inactiveUser?.usernames != null ? usernameData.inactiveUser.usernames : [];
|
|
|
+ const activitySnapshotUsernames = usernameData?.activitySnapshotUser?.usernames != null ? usernameData.activitySnapshotUser.usernames : [];
|
|
|
const isLoading = usernameData === undefined && error == null;
|
|
|
|
|
|
+ const allUser: AllUser[] = [];
|
|
|
+ const pushToAllUser = (usernames: string[], category: CategorieType) => {
|
|
|
+ usernames.forEach(username => allUser.push({ username, category }));
|
|
|
+ };
|
|
|
+ pushToAllUser(activeUsernames, Categories.activeUser);
|
|
|
+ pushToAllUser(inactiveUsernames, Categories.inactiveUser);
|
|
|
+ pushToAllUser(activitySnapshotUsernames, Categories.activitySnapshotUser);
|
|
|
|
|
|
- console.log(usernameData);
|
|
|
+ const searchHandler = useCallback(async(text) => {
|
|
|
+ setSearchKeyword(text);
|
|
|
+ }, []);
|
|
|
+
|
|
|
+ const renderMenu = useCallback((allUser: AllUser[], menuProps) => {
|
|
|
+ if (allUser == null || allUser.length === 0) {
|
|
|
+ return <></>;
|
|
|
+ }
|
|
|
+
|
|
|
+ let index = 0;
|
|
|
+ const items = Object.values(Categories).map((category) => {
|
|
|
+ const userData = allUser.filter(user => user.category === category);
|
|
|
+ return (
|
|
|
+ <Fragment key={category}>
|
|
|
+ {index !== 0 && <Menu.Divider />}
|
|
|
+ <Menu.Header>{category}</Menu.Header>
|
|
|
+ {userData.map((user) => {
|
|
|
+ const item = (
|
|
|
+ <MenuItem key={index} option={user} position={index}>
|
|
|
+ {user.username}
|
|
|
+ </MenuItem>
|
|
|
+ );
|
|
|
+ index++;
|
|
|
+ return item;
|
|
|
+ })}
|
|
|
+ </Fragment>
|
|
|
+ );
|
|
|
+ });
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Menu {...menuProps}>{items}</Menu>
|
|
|
+ );
|
|
|
+ }, []);
|
|
|
|
|
|
return (
|
|
|
<div className="input-group mr-2">
|
|
|
@@ -27,14 +85,16 @@ export const SearchUsernameInput: FC = () => {
|
|
|
</div>
|
|
|
<AsyncTypeahead
|
|
|
id="auditlog-username-typeahead-asynctypeahead"
|
|
|
+ placeholder="username"
|
|
|
+ labelKey={option => `${option.username}`}
|
|
|
caseSensitive={false}
|
|
|
- defaultSelected={[]}
|
|
|
isLoading={isLoading}
|
|
|
- minLength={1}
|
|
|
- multiple
|
|
|
+ minLength={0}
|
|
|
newSelectionPrefix=""
|
|
|
+ options={allUser}
|
|
|
+ onSearch={searchHandler}
|
|
|
+ renderMenu={renderMenu}
|
|
|
/>
|
|
|
</div>
|
|
|
-
|
|
|
);
|
|
|
};
|