Yuki Takei 4 лет назад
Родитель
Сommit
309e22e856
2 измененных файлов с 98 добавлено и 17 удалено
  1. 63 4
      packages/app/src/components/SearchPage2.tsx
  2. 35 13
      packages/app/src/stores/search.tsx

+ 63 - 4
packages/app/src/components/SearchPage2.tsx

@@ -1,12 +1,59 @@
 import React from 'react';
+import { useTranslation } from 'react-i18next';
 
 import AppContainer from '~/client/services/AppContainer';
+import { IFormattedSearchResult } from '~/interfaces/search';
 
 import { useSWRxFullTextSearch } from '~/stores/search';
 
 import SearchPageBase from './SearchPage2/SearchPageBase';
 
 
+type SearchResultListHeadProps = {
+  searchResult: IFormattedSearchResult,
+  searchingKeyword: string,
+  currentPage: number,
+  pagingSize: number,
+  onPagingSizeChanged: (size: number) => void,
+}
+
+const SearchResultListHead = (props: SearchResultListHeadProps): JSX.Element => {
+  const { t } = useTranslation();
+
+  const {
+    searchResult, searchingKeyword, currentPage, pagingSize,
+    onPagingSizeChanged,
+  } = props;
+
+  const leftNum = pagingSize * (currentPage - 1) + 1;
+  const rightNum = (leftNum - 1) + (searchResult.meta.count || 0);
+
+  return (
+    <div className="d-flex align-items-center justify-content-between my-3 ml-4">
+      <div className="search-result-meta text-nowrap">
+        <span className="font-weight-light">{t('search_result.result_meta')} </span>
+        <span className="h5">{`"${searchingKeyword}"`}</span>
+        <span className="ml-3">{`${leftNum}-${rightNum}`} / {searchResult.meta.total || 0}</span>
+      </div>
+      <div className="input-group search-result-select-group ml-4 d-lg-flex d-none">
+        <div className="input-group-prepend">
+          <label className="input-group-text text-muted" htmlFor="inputGroupSelect01">{t('search_result.number_of_list_to_display')}</label>
+        </div>
+        <select
+          defaultValue={pagingSize}
+          className="custom-select"
+          id="inputGroupSelect01"
+          onChange={e => onPagingSizeChanged(Number(e.target.value))}
+        >
+          {[20, 50, 100, 200].map((limit) => {
+            return <option key={limit} value={limit}>{limit}{t('search_result.page_number_unit')}</option>;
+          })}
+        </select>
+      </div>
+    </div>
+  );
+};
+
 type Props = {
   appContainer: AppContainer,
 }
@@ -17,7 +64,7 @@ export const SearchPage = (props: Props): JSX.Element => {
     appContainer,
   } = props;
 
-  const { data } = useSWRxFullTextSearch('sand', {
+  const { data, conditions } = useSWRxFullTextSearch('sand', {
     limit: 20,
   });
 
@@ -28,9 +75,21 @@ export const SearchPage = (props: Props): JSX.Element => {
       SearchControl={() => (
         <></>
       )}
-      SearchResultListHead={() => (
-        <></>
-      )}
+      SearchResultListHead={() => {
+        if (data == null) {
+          return <></>;
+        }
+
+        return (
+          <SearchResultListHead
+            searchResult={data}
+            searchingKeyword={conditions.keyword}
+            currentPage={}
+            pagingSize={}
+            onPagingSizeChanged={() => {}}
+          />
+        );
+      }}
     />
   );
 };

+ 35 - 13
packages/app/src/stores/search.tsx

@@ -15,12 +15,23 @@ export type ISearchConfigurations = {
   includeUserPages?: boolean,
 }
 
+type ISearchConfigurationsFixed = {
+  limit: number,
+  offset: number,
+  sort: SORT_AXIS,
+  order: SORT_ORDER,
+  includeTrashPages: boolean,
+  includeUserPages: boolean,
+}
+
 export type ISearchConditions = {
-  q: string,
-  configurations: ISearchConfigurations,
+  conditions: ISearchConfigurationsFixed & {
+    keyword: string,
+    rawQuery: string,
+  }
 }
 
-const createSearchQuery = (keyword: string, includeTrashPages = false, includeUserPages = false): string => {
+const createSearchQuery = (keyword: string, includeTrashPages: boolean, includeUserPages: boolean): string => {
   let query = keyword;
 
   // pages included in specific path are not retrived when prefix is added
@@ -39,25 +50,33 @@ export const useSWRxFullTextSearch = (
 ): SWRResponse<IFormattedSearchResult, Error> & ISearchConditions => {
 
   const {
-    includeTrashPages, includeUserPages,
+    limit, offset, sort, order, includeTrashPages, includeUserPages,
   } = configurations;
 
-  const rawQuery = createSearchQuery(keyword, includeTrashPages, includeUserPages);
+  const fixedConfigurations: ISearchConfigurationsFixed = {
+    limit,
+    offset: offset ?? 0,
+    sort: sort ?? SORT_AXIS.RELATION_SCORE,
+    order: order ?? SORT_ORDER.DESC,
+    includeTrashPages: includeTrashPages ?? false,
+    includeUserPages: includeUserPages ?? false,
+  };
+  const rawQuery = createSearchQuery(keyword, fixedConfigurations.includeTrashPages, fixedConfigurations.includeUserPages);
 
   const swrResult = useSWRImmutable(
-    ['/search', keyword, configurations],
-    (endpoint, keyword, configurations) => {
+    ['/search', keyword, fixedConfigurations],
+    (endpoint, keyword, fixedConfigurations) => {
       const {
         limit, offset, sort, order,
-      } = configurations;
+      } = fixedConfigurations;
 
       return apiGet(
         endpoint, {
           q: encodeURIComponent(rawQuery),
           limit,
-          offset: offset ?? 0,
-          sort: sort ?? SORT_AXIS.RELATION_SCORE,
-          order: order ?? SORT_ORDER.DESC,
+          offset,
+          sort,
+          order,
         },
       // eslint-disable-next-line @typescript-eslint/no-explicit-any
       ).then(result => result as IFormattedSearchResult);
@@ -66,7 +85,10 @@ export const useSWRxFullTextSearch = (
 
   return {
     ...swrResult,
-    q: rawQuery,
-    configurations,
+    conditions: {
+      keyword,
+      rawQuery,
+      ...fixedConfigurations,
+    },
   };
 };