SearchUsernameInput.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import React, {
  2. FC, Fragment, useState, useCallback,
  3. } from 'react';
  4. import { AsyncTypeahead, Menu, MenuItem } from 'react-bootstrap-typeahead';
  5. import { useSWRxUsernames } from '~/stores/user';
  6. const Categories = {
  7. activeUser: 'Active User',
  8. inactiveUser: 'Inactive User',
  9. activitySnapshotUser: 'ActivitySnapshot User',
  10. } as const;
  11. type CategorieType = typeof Categories[keyof typeof Categories]
  12. type AllUser = {
  13. username: string
  14. category: CategorieType
  15. }
  16. export const SearchUsernameInput: FC = () => {
  17. const [searchKeyword, setSearchKeyword] = useState('');
  18. const includeUserOptions = {
  19. isIncludeActiveUser: true,
  20. isIncludeInactiveUser: true,
  21. isIncludeActivitySnapshotUser: true,
  22. };
  23. const { data: usernameData, error } = useSWRxUsernames(searchKeyword, 0, 5, includeUserOptions);
  24. const activeUsernames = usernameData?.activeUser?.usernames != null ? usernameData.activeUser.usernames : [];
  25. const inactiveUsernames = usernameData?.inactiveUser?.usernames != null ? usernameData.inactiveUser.usernames : [];
  26. const activitySnapshotUsernames = usernameData?.activitySnapshotUser?.usernames != null ? usernameData.activitySnapshotUser.usernames : [];
  27. const isLoading = usernameData === undefined && error == null;
  28. const allUser: AllUser[] = [];
  29. const pushToAllUser = (usernames: string[], category: CategorieType) => {
  30. usernames.forEach(username => allUser.push({ username, category }));
  31. };
  32. pushToAllUser(activeUsernames, Categories.activeUser);
  33. pushToAllUser(inactiveUsernames, Categories.inactiveUser);
  34. pushToAllUser(activitySnapshotUsernames, Categories.activitySnapshotUser);
  35. const searchHandler = useCallback(async(text) => {
  36. setSearchKeyword(text);
  37. }, []);
  38. const renderMenu = useCallback((allUser: AllUser[], menuProps) => {
  39. if (allUser == null || allUser.length === 0) {
  40. return <></>;
  41. }
  42. let index = 0;
  43. const items = Object.values(Categories).map((category) => {
  44. const userData = allUser.filter(user => user.category === category);
  45. return (
  46. <Fragment key={category}>
  47. {index !== 0 && <Menu.Divider />}
  48. <Menu.Header>{category}</Menu.Header>
  49. {userData.map((user) => {
  50. const item = (
  51. <MenuItem key={index} option={user} position={index}>
  52. {user.username}
  53. </MenuItem>
  54. );
  55. index++;
  56. return item;
  57. })}
  58. </Fragment>
  59. );
  60. });
  61. return (
  62. <Menu {...menuProps}>{items}</Menu>
  63. );
  64. }, []);
  65. return (
  66. <div className="input-group mr-2">
  67. <div className="input-group-prepend">
  68. <span className="input-group-text">
  69. <i className="icon-user"></i>
  70. </span>
  71. </div>
  72. <AsyncTypeahead
  73. id="auditlog-username-typeahead-asynctypeahead"
  74. placeholder="username"
  75. labelKey={option => `${option.username}`}
  76. caseSensitive={false}
  77. isLoading={isLoading}
  78. minLength={0}
  79. newSelectionPrefix=""
  80. options={allUser}
  81. onSearch={searchHandler}
  82. renderMenu={renderMenu}
  83. />
  84. </div>
  85. );
  86. };