search.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import type { SWRResponse } from 'swr';
  2. import useSWR, { mutate } from 'swr';
  3. import { apiGet } from '~/client/util/apiv1-client';
  4. import type { IFormattedSearchResult } from '~/interfaces/search';
  5. import { SORT_AXIS, SORT_ORDER } from '~/interfaces/search';
  6. export type ISearchConfigurations = {
  7. limit: number,
  8. offset?: number,
  9. sort?: SORT_AXIS,
  10. order?: SORT_ORDER,
  11. includeTrashPages?: boolean,
  12. includeUserPages?: boolean,
  13. }
  14. type ISearchConfigurationsFixed = {
  15. limit: number,
  16. offset: number,
  17. sort: SORT_AXIS,
  18. order: SORT_ORDER,
  19. includeTrashPages: boolean,
  20. includeUserPages: boolean,
  21. }
  22. export type ISearchConditions = ISearchConfigurationsFixed & {
  23. keyword: string | null,
  24. rawQuery: string,
  25. }
  26. const createSearchQuery = (keyword: string, includeTrashPages: boolean, includeUserPages: boolean): string => {
  27. let query = keyword;
  28. // pages included in specific path are not retrived when prefix is added
  29. if (!includeTrashPages) {
  30. query = `${query} -prefix:/trash`;
  31. }
  32. if (!includeUserPages) {
  33. query = `${query} -prefix:/user`;
  34. }
  35. return query;
  36. };
  37. export const mutateSearching = async(): Promise<void[]> => {
  38. return mutate(
  39. key => Array.isArray(key) && key[0] === '/search',
  40. );
  41. };
  42. export const useSWRxSearch = (
  43. keyword: string | null, nqName: string | null, configurations: ISearchConfigurations,
  44. ): SWRResponse<IFormattedSearchResult, Error> & { conditions: ISearchConditions } => {
  45. const {
  46. limit, offset, sort, order, includeTrashPages, includeUserPages,
  47. } = configurations;
  48. const fixedConfigurations: ISearchConfigurationsFixed = {
  49. limit,
  50. offset: offset ?? 0,
  51. sort: sort ?? SORT_AXIS.RELATION_SCORE,
  52. order: order ?? SORT_ORDER.DESC,
  53. includeTrashPages: includeTrashPages ?? false,
  54. includeUserPages: includeUserPages ?? false,
  55. };
  56. const rawQuery = createSearchQuery(keyword ?? '', fixedConfigurations.includeTrashPages, fixedConfigurations.includeUserPages);
  57. const isKeywordValid = keyword != null && keyword.length > 0;
  58. const swrResult = useSWR(
  59. isKeywordValid ? ['/search', keyword, fixedConfigurations] : null,
  60. ([endpoint, , fixedConfigurations]) => {
  61. const {
  62. limit, offset, sort, order,
  63. } = fixedConfigurations;
  64. return apiGet(
  65. endpoint, {
  66. q: encodeURIComponent(rawQuery),
  67. nq: typeof nqName === 'string' ? encodeURIComponent(nqName) : null,
  68. limit,
  69. offset,
  70. sort,
  71. order,
  72. },
  73. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  74. ).then(result => result as IFormattedSearchResult);
  75. },
  76. {
  77. keepPreviousData: true,
  78. revalidateOnFocus: false,
  79. },
  80. );
  81. return {
  82. ...swrResult,
  83. conditions: {
  84. keyword,
  85. rawQuery,
  86. ...fixedConfigurations,
  87. },
  88. };
  89. };