From 162a4a305af559ed3c62b779fa737c7715017637 Mon Sep 17 00:00:00 2001 From: Jonas Carlsen Date: Fri, 1 Nov 2024 16:30:13 +0100 Subject: [PATCH] refactor: Use Combobox in AddExistingResource --- .../plannedResource/AddExistingResource.tsx | 94 +++++++++---------- 1 file changed, 43 insertions(+), 51 deletions(-) diff --git a/src/containers/StructurePage/plannedResource/AddExistingResource.tsx b/src/containers/StructurePage/plannedResource/AddExistingResource.tsx index 609f872a5..09556fa2c 100644 --- a/src/containers/StructurePage/plannedResource/AddExistingResource.tsx +++ b/src/containers/StructurePage/plannedResource/AddExistingResource.tsx @@ -9,43 +9,30 @@ import { ChangeEvent, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { useQueryClient } from "@tanstack/react-query"; -import { Button, FieldInput, FieldLabel, FieldRoot, Text } from "@ndla/primitives"; +import { Button, ComboboxLabel, FieldInput, FieldLabel, FieldRoot, Text } from "@ndla/primitives"; import { styled } from "@ndla/styled-system/jsx"; import { IArticleV2 } from "@ndla/types-backend/article-api"; import { ILearningPathSummaryV2, ILearningPathV2 } from "@ndla/types-backend/learningpath-api"; -import { IGroupSearchResult, IMultiSearchSummary } from "@ndla/types-backend/search-api"; +import { IMultiSearchSummary } from "@ndla/types-backend/search-api"; +import { GenericComboboxInput, GenericComboboxItemContent } from "../../../components/abstractions/Combobox"; import ArticlePreview from "../../../components/ArticlePreview"; -import AsyncDropdown from "../../../components/Dropdown/asyncDropdown/AsyncDropdown"; +import { GenericSearchCombobox } from "../../../components/Form/GenericSearchCombobox"; import { FormActionsContainer, FormContent } from "../../../components/FormikForm"; import Spinner from "../../../components/Spinner"; import { RESOURCE_TYPE_LEARNING_PATH, RESOURCE_TYPE_SUBJECT_MATERIAL } from "../../../constants"; import { getArticle } from "../../../modules/article/articleApi"; -import { - fetchLearningpaths, - learningpathSearch, - updateLearningPathTaxonomy, -} from "../../../modules/learningpath/learningpathApi"; +import { fetchLearningpaths, updateLearningPathTaxonomy } from "../../../modules/learningpath/learningpathApi"; import { fetchNodes } from "../../../modules/nodes/nodeApi"; import { usePostResourceForNodeMutation } from "../../../modules/nodes/nodeMutations"; import { nodeQueryKeys, useNodes } from "../../../modules/nodes/nodeQueries"; -import { postSearch } from "../../../modules/search/searchApi"; +import { useSearch } from "../../../modules/search/searchQueries"; import { resolveUrls } from "../../../modules/taxonomy/taxonomyApi"; import handleError from "../../../util/handleError"; import { getResourceIdFromPath } from "../../../util/routeHelpers"; +import { usePaginatedQuery } from "../../../util/usePaginatedQuery"; import ResourceTypeSelect from "../../ArticlePage/components/ResourceTypeSelect"; import { useTaxonomyVersion } from "../../StructureVersion/TaxonomyVersionProvider"; -const emptySearchResults: IGroupSearchResult = { - totalCount: 0, - page: 0, - pageSize: 0, - language: "", - results: [], - suggestions: [], - aggregations: [], - resourceType: "", -}; - const StyledText = styled(Text, { base: { textAlign: "center", @@ -77,6 +64,7 @@ type PossibleResources = IMultiSearchSummary | ILearningPathSummaryV2 | ILearnin const AddExistingResource = ({ onClose, resourceTypes, existingResourceIds, nodeId }: Props) => { const { t, i18n } = useTranslation(); + const { query, delayedQuery, setQuery, page, setPage } = usePaginatedQuery(); const [error, setError] = useState(""); const [loading, setLoading] = useState(false); const [selectedType, setSelectedType] = useState(RESOURCE_TYPE_SUBJECT_MATERIAL); @@ -155,26 +143,13 @@ const AddExistingResource = ({ onClose, resourceTypes, existingResourceIds, node } }; - const onSearch = async (query: string, page?: number) => { - const baseQuery = { - query, - page, - language: i18n.language, - fallback: true, - }; - if (selectedType === RESOURCE_TYPE_LEARNING_PATH) { - return await learningpathSearch({ - ...baseQuery, - verificationStatus: "CREATED_BY_NDLA", - }); - } else { - const res = await postSearch({ - ...baseQuery, - resourceTypes: [selectedType], - }); - return res ?? emptySearchResults; - } - }; + const searchQuery = useSearch({ + query: delayedQuery, + page, + language: i18n.language, + fallback: true, + resourceTypes: [selectedType], + }); const resetPastedUrlStatesWithError = (error?: string) => { setError(error ?? ""); @@ -289,17 +264,34 @@ const AddExistingResource = ({ onClose, resourceTypes, existingResourceIds, node /> )} {!pastedUrl && selectedType && ( - - idField="id" - labelField="title" - placeholder={t("form.content.relatedArticle.placeholder")} - apiAction={(query, page) => onSearch(query, page)} - onChange={(res) => setPreview(toPreview(res))} - startOpen={false} - showPagination - initialSearch={false} - label={t("form.content.relatedArticle.placeholder")} - /> + setPreview(toPreview(details.items[0]))} + items={searchQuery.data?.results ?? []} + itemToString={(item) => item.title.title} + itemToValue={(item) => item.id.toString()} + inputValue={query} + onInputValueChange={(details) => setQuery(details.inputValue)} + isSuccess={searchQuery.isSuccess} + paginationData={searchQuery.data} + onPageChange={(details) => setPage(details.page)} + renderItem={(item) => ( + + )} + > + {t("form.content.relatedArticle.placeholder")} + + )} {previewLoading ? : preview && } {error && {t(error)}}