SearchResultMenuItem.tsx 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import React, { useCallback } from 'react';
  2. import { PagePathLabel, UserPicture } from '@growi/ui/dist/components';
  3. import { useDebounce } from 'usehooks-ts';
  4. import { useSWRxSearch } from '~/stores/search';
  5. import { SearchMenuItem } from './SearchMenuItem';
  6. type Props = {
  7. searchKeyword: string,
  8. getItemProps: any,
  9. highlightedIndex: number | null,
  10. }
  11. export const SearchResultMenuItem = (props: Props): JSX.Element => {
  12. const { searchKeyword, highlightedIndex, getItemProps } = props;
  13. const debouncedKeyword = useDebounce(searchKeyword, 500);
  14. const isEmptyKeyword = searchKeyword.trim().length === 0;
  15. const { data: searchResult, isLoading } = useSWRxSearch(isEmptyKeyword ? null : debouncedKeyword, null, { limit: 10 });
  16. const getFiexdIndex = useCallback((index: number | null) => {
  17. if (index == null) {
  18. return -1;
  19. }
  20. return (isEmptyKeyword ? 1 : 3) + index;
  21. }, [isEmptyKeyword]);
  22. if (isLoading) {
  23. return (
  24. <>
  25. Searching...
  26. <div className="border-top mt-3" />
  27. </>
  28. );
  29. }
  30. if (isEmptyKeyword || searchResult == null || searchResult.data.length === 0) {
  31. return <></>;
  32. }
  33. return (
  34. <>
  35. {searchResult?.data
  36. .map((item, index) => (
  37. <SearchMenuItem key={item.data._id} index={getFiexdIndex(index)} highlightedIndex={highlightedIndex} getItemProps={getItemProps} url={item.data._id}>
  38. <UserPicture user={item.data.creator} />
  39. <span className="ms-3 text-break text-wrap">
  40. <PagePathLabel path={item.data.path} />
  41. </span>
  42. <span className="ms-2 text-muted d-flex justify-content-center align-items-center">
  43. <span className="material-symbols-outlined fs-5">footprint</span>
  44. <span>{item.data.seenUsers.length}</span>
  45. </span>
  46. </SearchMenuItem>
  47. ))
  48. }
  49. <div className="border-top mt-3" />
  50. </>
  51. );
  52. };