diff --git a/CHANGELOG.md b/CHANGELOG.md index d8b7dacaf..fc36edc03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ All notable, unreleased changes to this project will be documented in this file. - Use Apollo Hooks - #254 by @dominik-zeglen - Fix disappearing products description - #259 by @dominik-zeglen - Improve mobile appearance - #240 by @benekex2 and @dominik-zeglen +- Use searches as hooks instead of components - #262 by @dominik-zeglen ## 2.0.0 diff --git a/src/collections/views/CollectionDetails.tsx b/src/collections/views/CollectionDetails.tsx index 6832343bb..589b3599c 100644 --- a/src/collections/views/CollectionDetails.tsx +++ b/src/collections/views/CollectionDetails.tsx @@ -6,6 +6,7 @@ import { FormattedMessage, useIntl } from "react-intl"; import ActionDialog from "@saleor/components/ActionDialog"; import AssignProductDialog from "@saleor/components/AssignProductDialog"; import { WindowTitle } from "@saleor/components/WindowTitle"; +import { DEFAULT_INITIAL_SEARCH_DATA, PAGINATE_BY } from "@saleor/config"; import useBulkActions from "@saleor/hooks/useBulkActions"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; @@ -13,8 +14,7 @@ import usePaginator, { createPaginationState } from "@saleor/hooks/usePaginator"; import { commonMessages } from "@saleor/intl"; -import { DEFAULT_INITIAL_SEARCH_DATA, PAGINATE_BY } from "../../config"; -import SearchProducts from "../../containers/SearchProducts"; +import useProductSearch from "@saleor/searches/useProductSearch"; import { getMutationState, maybe } from "../../misc"; import { productUrl } from "../../products/urls"; import { CollectionInput } from "../../types/globalTypes"; @@ -50,6 +50,9 @@ export const CollectionDetails: React.FC = ({ ); const paginate = usePaginator(); const intl = useIntl(); + const { search, result } = useProductSearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); const closeModal = () => navigate( @@ -284,29 +287,25 @@ export const CollectionDetails: React.FC = ({ toggle={toggle} toggleAll={toggleAll} /> - - {({ search, result }) => ( - - assignProduct.mutate({ - ...paginationState, - collectionId: id, - productIds: products.map(product => product.id) - }) - } - products={maybe(() => - result.data.search.edges - .map(edge => edge.node) - .filter(suggestedProduct => suggestedProduct.id) - )} - /> + + assignProduct.mutate({ + ...paginationState, + collectionId: id, + productIds: products.map(product => product.id) + }) + } + products={maybe(() => + result.data.search.edges + .map(edge => edge.node) + .filter(suggestedProduct => suggestedProduct.id) )} - + /> { - children: (props: { - loadMore: () => void; - search: (query: string) => void; - result: TypedQueryResult; - }) => React.ReactElement; - variables: TQueryVariables; -} - -function BaseSearch( - query: DocumentNode, - loadMoreFn: (result: TypedQueryResult) => void -) { - const Query = TypedQuery(query); - - class BaseSearchComponent extends React.Component< - BaseSearchProps, - SearchQueryVariables - > { - state: SearchQueryVariables = { - first: this.props.variables.first, - query: this.props.variables.query - }; - - search = (query: string) => { - if (query === undefined) { - this.setState({ query: "" }); - } else { - this.setState({ query }); - } - }; - - render() { - const { children, variables } = this.props; - - return ( - - {search => ( - - {result => - children({ - loadMore: () => loadMoreFn(result), - result, - search - }) - } - - )} - - ); - } - } - return BaseSearchComponent; -} - -export default BaseSearch; diff --git a/src/discounts/views/SaleDetails.tsx b/src/discounts/views/SaleDetails.tsx index 987c2557d..133f3ab26 100644 --- a/src/discounts/views/SaleDetails.tsx +++ b/src/discounts/views/SaleDetails.tsx @@ -8,6 +8,7 @@ import AssignCategoriesDialog from "@saleor/components/AssignCategoryDialog"; import AssignCollectionDialog from "@saleor/components/AssignCollectionDialog"; import AssignProductDialog from "@saleor/components/AssignProductDialog"; import { WindowTitle } from "@saleor/components/WindowTitle"; +import { DEFAULT_INITIAL_SEARCH_DATA, PAGINATE_BY } from "@saleor/config"; import useBulkActions from "@saleor/hooks/useBulkActions"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; @@ -16,12 +17,11 @@ import usePaginator, { } from "@saleor/hooks/usePaginator"; import useShop from "@saleor/hooks/useShop"; import { commonMessages, sectionNames } from "@saleor/intl"; +import useCategorySearch from "@saleor/searches/useCategorySearch"; +import useCollectionSearch from "@saleor/searches/useCollectionSearch"; +import useProductSearch from "@saleor/searches/useProductSearch"; import { categoryUrl } from "../../categories/urls"; import { collectionUrl } from "../../collections/urls"; -import { DEFAULT_INITIAL_SEARCH_DATA, PAGINATE_BY } from "../../config"; -import SearchCategories from "../../containers/SearchCategories"; -import SearchCollections from "../../containers/SearchCollections"; -import SearchProducts from "../../containers/SearchProducts"; import { decimal, getMutationState, joinDateTime, maybe } from "../../misc"; import { productUrl } from "../../products/urls"; import { DiscountValueTypeEnum, SaleType } from "../../types/globalTypes"; @@ -66,6 +66,24 @@ export const SaleDetails: React.FC = ({ id, params }) => { params.ids ); const intl = useIntl(); + const { + search: searchCategories, + result: searchCategoriesOpts + } = useCategorySearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); + const { + search: searchCollections, + result: searchCollectionsOpts + } = useCollectionSearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); + const { + search: searchProducts, + result: searchProductsOpts + } = useProductSearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); const paginationState = createPaginationState(PAGINATE_BY, params); const changeTab = (tab: SaleDetailsPageTab) => { @@ -341,116 +359,87 @@ export const SaleDetails: React.FC = ({ id, params }) => { toggle={toggle} toggleAll={toggleAll} /> - - {({ - search: searchProducts, - result: searchProductsOpts - }) => ( - - saleCataloguesAdd({ - variables: { - ...paginationState, - id, - input: { - products: products.map( - product => product.id - ) - } - } - }) - } - products={maybe(() => - searchProductsOpts.data.search.edges - .map(edge => edge.node) - .filter( - suggestedProduct => suggestedProduct.id + + saleCataloguesAdd({ + variables: { + ...paginationState, + id, + input: { + products: products.map( + product => product.id ) - )} - /> - )} - - - {({ - search: searchCategories, - result: searchCategoriesOpts - }) => ( - - searchCategoriesOpts.data.search.edges - .map(edge => edge.node) - .filter( - suggestedCategory => - suggestedCategory.id - ) - )} - confirmButtonState={assignTransitionState} - open={params.action === "assign-category"} - onFetch={searchCategories} - loading={searchCategoriesOpts.loading} - onClose={closeModal} - onSubmit={categories => - saleCataloguesAdd({ - variables: { - ...paginationState, - id, - input: { - categories: categories.map( - product => product.id - ) - } - } - }) + } } - /> + }) + } + products={maybe(() => + searchProductsOpts.data.search.edges + .map(edge => edge.node) + .filter( + suggestedProduct => suggestedProduct.id + ) )} - - - {({ - search: searchCollections, - result: searchCollectionsOpts - }) => ( - - searchCollectionsOpts.data.search.edges - .map(edge => edge.node) - .filter( - suggestedCategory => - suggestedCategory.id + /> + + searchCategoriesOpts.data.search.edges + .map(edge => edge.node) + .filter( + suggestedCategory => suggestedCategory.id + ) + )} + confirmButtonState={assignTransitionState} + open={params.action === "assign-category"} + onFetch={searchCategories} + loading={searchCategoriesOpts.loading} + onClose={closeModal} + onSubmit={categories => + saleCataloguesAdd({ + variables: { + ...paginationState, + id, + input: { + categories: categories.map( + product => product.id ) - )} - confirmButtonState={assignTransitionState} - open={params.action === "assign-collection"} - onFetch={searchCollections} - loading={searchCollectionsOpts.loading} - onClose={closeModal} - onSubmit={collections => - saleCataloguesAdd({ - variables: { - ...paginationState, - id, - input: { - collections: collections.map( - product => product.id - ) - } - } - }) + } } - /> + }) + } + /> + + searchCollectionsOpts.data.search.edges + .map(edge => edge.node) + .filter( + suggestedCategory => suggestedCategory.id + ) )} - + confirmButtonState={assignTransitionState} + open={params.action === "assign-collection"} + onFetch={searchCollections} + loading={searchCollectionsOpts.loading} + onClose={closeModal} + onSubmit={collections => + saleCataloguesAdd({ + variables: { + ...paginationState, + id, + input: { + collections: collections.map( + product => product.id + ) + } + } + }) + } + /> = ({ params.ids ); const intl = useIntl(); + const { + search: searchCategories, + result: searchCategoriesOpts + } = useCategorySearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); + const { + search: searchCollections, + result: searchCollectionsOpts + } = useCollectionSearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); + const { + search: searchProducts, + result: searchProductsOpts + } = useProductSearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); const paginationState = createPaginationState(PAGINATE_BY, params); const changeTab = (tab: VoucherDetailsPageTab) => { @@ -420,80 +438,60 @@ export const VoucherDetails: React.FC = ({ toggle={toggle} toggleAll={toggleAll} /> - - {({ - search: searchCategories, - result: searchCategoriesOpts - }) => ( - - searchCategoriesOpts.data.search.edges - .map(edge => edge.node) - .filter( - suggestedCategory => - suggestedCategory.id - ) - )} - confirmButtonState={assignTransitionState} - open={params.action === "assign-category"} - onFetch={searchCategories} - loading={searchCategoriesOpts.loading} - onClose={closeModal} - onSubmit={categories => - voucherCataloguesAdd({ - variables: { - ...paginationState, - id, - input: { - categories: categories.map( - product => product.id - ) - } - } - }) - } - /> + + searchCategoriesOpts.data.search.edges + .map(edge => edge.node) + .filter( + suggestedCategory => suggestedCategory.id + ) )} - - - {({ - search: searchCollections, - result: searchCollectionsOpts - }) => ( - - searchCollectionsOpts.data.search.edges - .map(edge => edge.node) - .filter( - suggestedCategory => - suggestedCategory.id + confirmButtonState={assignTransitionState} + open={params.action === "assign-category"} + onFetch={searchCategories} + loading={searchCategoriesOpts.loading} + onClose={closeModal} + onSubmit={categories => + voucherCataloguesAdd({ + variables: { + ...paginationState, + id, + input: { + categories: categories.map( + product => product.id ) - )} - confirmButtonState={assignTransitionState} - open={params.action === "assign-collection"} - onFetch={searchCollections} - loading={searchCollectionsOpts.loading} - onClose={closeModal} - onSubmit={collections => - voucherCataloguesAdd({ - variables: { - ...paginationState, - id, - input: { - collections: collections.map( - product => product.id - ) - } - } - }) + } } - /> + }) + } + /> + + searchCollectionsOpts.data.search.edges + .map(edge => edge.node) + .filter( + suggestedCategory => suggestedCategory.id + ) )} - + confirmButtonState={assignTransitionState} + open={params.action === "assign-collection"} + onFetch={searchCollections} + loading={searchCollectionsOpts.loading} + onClose={closeModal} + onSubmit={collections => + voucherCataloguesAdd({ + variables: { + ...paginationState, + id, + input: { + collections: collections.map( + product => product.id + ) + } + } + }) + } + /> shop.countries, [])} @@ -517,42 +515,33 @@ export const VoucherDetails: React.FC = ({ [] )} /> - - {({ - search: searchProducts, - result: searchProductsOpts - }) => ( - - voucherCataloguesAdd({ - variables: { - ...paginationState, - id, - input: { - products: products.map( - product => product.id - ) - } - } - }) - } - products={maybe(() => - searchProductsOpts.data.search.edges - .map(edge => edge.node) - .filter( - suggestedProduct => suggestedProduct.id + + voucherCataloguesAdd({ + variables: { + ...paginationState, + id, + input: { + products: products.map( + product => product.id ) - )} - /> + } + } + }) + } + products={maybe(() => + searchProductsOpts.data.search.edges + .map(edge => edge.node) + .filter( + suggestedProduct => suggestedProduct.id + ) )} - + /> { ) => Promise>; } -type UseQuery = QueryResult & +export type UseQueryResult = QueryResult & LoadMore; type UseQueryOpts = Partial<{ displayLoader: boolean; @@ -26,17 +26,17 @@ type UseQueryOpts = Partial<{ }>; type UseQueryHook = ( opts: UseQueryOpts -) => UseQuery; +) => UseQueryResult; function makeQuery( query: DocumentNode ): UseQueryHook { - function useQuery({ + function useQuery({ displayLoader, require, skip, variables - }: UseQueryOpts): UseQuery { + }: UseQueryOpts): UseQueryResult { const notify = useNotifier(); const intl = useIntl(); const [, dispatchAppState] = useAppState(); diff --git a/src/hooks/makeSearch.ts b/src/hooks/makeSearch.ts new file mode 100644 index 000000000..240274503 --- /dev/null +++ b/src/hooks/makeSearch.ts @@ -0,0 +1,57 @@ +import { DocumentNode } from "graphql"; +import { useState } from "react"; +import { QueryResult } from "react-apollo"; + +import makeQuery, { UseQueryResult } from "./makeQuery"; +import useDebounce from "./useDebounce"; + +export interface SearchVariables { + after?: string; + first: number; + query: string; +} + +export interface UseSearchResult { + loadMore: () => void; + result: QueryResult; + search: (query: string) => void; +} +export type UseSearchOpts = Partial<{ + skip: boolean; + variables: TVariables; +}>; +export type UseSearchHook = ( + opts: UseSearchOpts +) => UseSearchResult; + +function makeSearch( + query: DocumentNode, + loadMoreFn: (result: UseQueryResult) => void +): UseSearchHook { + const useSearchQuery = makeQuery(query); + + function useSearch( + opts: UseSearchOpts + ): UseSearchResult { + const [searchQuery, setSearchQuery] = useState(""); + const debouncedSearch = useDebounce(setSearchQuery); + const result = useSearchQuery({ + ...opts, + displayLoader: true, + variables: { + ...opts.variables, + query: searchQuery + } + }); + + return { + loadMore: () => loadMoreFn(result), + result, + search: debouncedSearch + }; + } + + return useSearch; +} + +export default makeSearch; diff --git a/src/containers/TopLevelSearch.tsx b/src/hooks/makeTopLevelSearch.ts similarity index 70% rename from src/containers/TopLevelSearch.tsx rename to src/hooks/makeTopLevelSearch.ts index 85a90a301..1b163be8d 100644 --- a/src/containers/TopLevelSearch.tsx +++ b/src/hooks/makeTopLevelSearch.ts @@ -1,9 +1,9 @@ import { DocumentNode } from "graphql"; import { PageInfoFragment } from "@saleor/types/PageInfoFragment"; -import BaseSearch, { SearchQueryVariables } from "./BaseSearch"; +import makeSearch, { SearchVariables, UseSearchHook } from "./makeSearch"; -export interface SearchQuery { +export interface SearchData { search: { edges: Array<{ node: any; @@ -12,11 +12,11 @@ export interface SearchQuery { }; } -function TopLevelSearch< - TQuery extends SearchQuery, - TQueryVariables extends SearchQueryVariables ->(query: DocumentNode) { - return BaseSearch(query, result => { +function makeTopLevelSearch< + TData extends SearchData, + TVariables extends SearchVariables +>(query: DocumentNode): UseSearchHook { + return makeSearch(query, result => { if (result.data.search.pageInfo.hasNextPage) { result.loadMore( (prev, next) => { @@ -44,4 +44,4 @@ function TopLevelSearch< }); } -export default TopLevelSearch; +export default makeTopLevelSearch; diff --git a/src/hooks/useDebounce.ts b/src/hooks/useDebounce.ts new file mode 100644 index 000000000..69be1e40e --- /dev/null +++ b/src/hooks/useDebounce.ts @@ -0,0 +1,19 @@ +import { useEffect, useRef } from "react"; + +export type UseDebounceFn = (...args: T[]) => void; +function useDebounce( + debounceFn: UseDebounceFn, + time = 200 +): UseDebounceFn { + const timer = useRef(null); + useEffect(() => () => clearTimeout(timer.current)); + + return (...args: T[]) => { + if (timer.current) { + clearTimeout(timer.current); + } + timer.current = setTimeout(() => debounceFn(...args), time); + }; +} + +export default useDebounce; diff --git a/src/navigation/components/MenuItemDialog/MenuItemDialog.tsx b/src/navigation/components/MenuItemDialog/MenuItemDialog.tsx index 30f2c9945..44c66ad92 100644 --- a/src/navigation/components/MenuItemDialog/MenuItemDialog.tsx +++ b/src/navigation/components/MenuItemDialog/MenuItemDialog.tsx @@ -14,13 +14,13 @@ import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import FormSpacer from "@saleor/components/FormSpacer"; -import { SearchCategories_search_edges_node } from "@saleor/containers/SearchCategories/types/SearchCategories"; -import { SearchCollections_search_edges_node } from "@saleor/containers/SearchCollections/types/SearchCollections"; -import { SearchPages_search_edges_node } from "@saleor/containers/SearchPages/types/SearchPages"; import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; import useModalDialogOpen from "@saleor/hooks/useModalDialogOpen"; import useStateFromProps from "@saleor/hooks/useStateFromProps"; import { buttonMessages, sectionNames } from "@saleor/intl"; +import { SearchCategories_search_edges_node } from "@saleor/searches/types/SearchCategories"; +import { SearchCollections_search_edges_node } from "@saleor/searches/types/SearchCollections"; +import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages"; import { UserError } from "@saleor/types"; import { getErrors, getFieldError } from "@saleor/utils/errors"; import { getMenuItemByValue, IMenu } from "@saleor/utils/menu"; diff --git a/src/navigation/views/MenuDetails/index.tsx b/src/navigation/views/MenuDetails/index.tsx index eb4f5b801..ee44bd6ee 100644 --- a/src/navigation/views/MenuDetails/index.tsx +++ b/src/navigation/views/MenuDetails/index.tsx @@ -3,14 +3,14 @@ import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; import ActionDialog from "@saleor/components/ActionDialog"; +import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; +import useCategorySearch from "@saleor/searches/useCategorySearch"; +import useCollectionSearch from "@saleor/searches/useCollectionSearch"; +import usePageSearch from "@saleor/searches/usePageSearch"; import { categoryUrl } from "../../../categories/urls"; import { collectionUrl } from "../../../collections/urls"; -import { DEFAULT_INITIAL_SEARCH_DATA } from "../../../config"; -import SearchCategories from "../../../containers/SearchCategories"; -import SearchCollections from "../../../containers/SearchCollections"; -import SearchPages from "../../../containers/SearchPages"; import { getMutationState, maybe } from "../../../misc"; import { pageUrl } from "../../../pages/urls"; import MenuDetailsPage, { @@ -59,6 +59,15 @@ const MenuDetails: React.FC = ({ id, params }) => { const navigate = useNavigator(); const notify = useNotifier(); const intl = useIntl(); + const categorySearch = useCategorySearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); + const collectionSearch = useCollectionSearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); + const pageSearch = usePageSearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); const closeModal = () => navigate( @@ -95,328 +104,267 @@ const MenuDetails: React.FC = ({ id, params }) => { }; return ( - - {pageSearch => ( - - {categorySearch => ( - - {collectionSearch => ( - - {({ data, loading, refetch }) => { - const handleQueryChange = (query: string) => { - categorySearch.search(query); - collectionSearch.search(query); - pageSearch.search(query); - }; + + {({ data, loading, refetch }) => { + const handleQueryChange = (query: string) => { + categorySearch.search(query); + collectionSearch.search(query); + pageSearch.search(query); + }; - const categories = maybe( - () => - categorySearch.result.data.search.edges.map( - edge => edge.node - ), - [] - ); + const categories = maybe( + () => categorySearch.result.data.search.edges.map(edge => edge.node), + [] + ); - const collections = maybe( - () => - collectionSearch.result.data.search.edges.map( - edge => edge.node - ), - [] - ); + const collections = maybe( + () => + collectionSearch.result.data.search.edges.map(edge => edge.node), + [] + ); - const pages = maybe( - () => - pageSearch.result.data.search.edges.map( - edge => edge.node - ), - [] - ); + const pages = maybe( + () => pageSearch.result.data.search.edges.map(edge => edge.node), + [] + ); - return ( - handleDelete(data, navigate, notify, intl)} + > + {(menuDelete, menuDeleteOpts) => ( + handleUpdate(data, notify, refetch, intl)} + > + {(menuUpdate, menuUpdateOpts) => { + const deleteState = getMutationState( + menuDeleteOpts.called, + menuDeleteOpts.loading, + maybe(() => menuDeleteOpts.data.menuDelete.errors) + ); + + const updateState = getMutationState( + menuUpdateOpts.called, + menuUpdateOpts.loading, + maybe(() => menuUpdateOpts.data.menuUpdate.errors), + maybe(() => menuUpdateOpts.data.menuItemMove.errors) + ); + + // This is a workaround to let know + // that it should clean operation stack if mutations + // were successful + const handleSubmit = async (data: MenuDetailsSubmitData) => { + try { + const result = await menuUpdate({ + variables: { + id, + moves: getMoves(data), + name: data.name, + removeIds: getRemoveIds(data) + } + }); + if (result) { + if ( + result.data.menuItemBulkDelete.errors.length > 0 || + result.data.menuItemMove.errors.length > 0 || + result.data.menuUpdate.errors.length > 0 + ) { + return false; + } + } + return true; + } catch { + return false; + } + }; + + return ( + <> + data.menu)} + onBack={() => navigate(menuListUrl())} + onDelete={() => + navigate( + menuUrl(id, { + action: "remove" + }) + ) + } + onItemAdd={() => + navigate( + menuUrl(id, { + action: "add-item" + }) + ) + } + onItemClick={handleItemClick} + onItemEdit={itemId => + navigate( + menuUrl(id, { + action: "edit-item", + id: itemId + }) + ) + } + onSubmit={handleSubmit} + saveButtonState={updateState} + /> + menuDelete({ variables: { id } })} + variant="delete" + title={intl.formatMessage({ + defaultMessage: "Delete Menu", + description: "dialog header", + id: "menuDetailsDeleteMenuHeader" + })} + > + + + {maybe(() => data.menu.name, "...")} + + ) + }} + /> + + + + - handleDelete(data, navigate, notify, intl) + handleItemCreate(data, notify, closeModal, intl) } > - {(menuDelete, menuDeleteOpts) => ( - - handleUpdate(data, notify, refetch, intl) - } - > - {(menuUpdate, menuUpdateOpts) => { - const deleteState = getMutationState( - menuDeleteOpts.called, - menuDeleteOpts.loading, - maybe( - () => menuDeleteOpts.data.menuDelete.errors - ) - ); + {(menuItemCreate, menuItemCreateOpts) => { + const handleSubmit = ( + data: MenuItemDialogFormData + ) => { + const variables: MenuItemCreateVariables = { + input: getMenuItemCreateInputData(id, data) + }; - const updateState = getMutationState( - menuUpdateOpts.called, - menuUpdateOpts.loading, - maybe( - () => menuUpdateOpts.data.menuUpdate.errors - ), - maybe( - () => menuUpdateOpts.data.menuItemMove.errors - ) - ); + menuItemCreate({ variables }); + }; - // This is a workaround to let know - // that it should clean operation stack if mutations - // were successful - const handleSubmit = async ( - data: MenuDetailsSubmitData - ) => { - try { - const result = await menuUpdate({ - variables: { - id, - moves: getMoves(data), - name: data.name, - removeIds: getRemoveIds(data) - } - }); - if (result) { - if ( - result.data.menuItemBulkDelete.errors - .length > 0 || - result.data.menuItemMove.errors.length > - 0 || - result.data.menuUpdate.errors.length > 0 - ) { - return false; - } - } - return true; - } catch { - return false; - } - }; + const formTransitionState = getMutationState( + menuItemCreateOpts.called, + menuItemCreateOpts.loading, + maybe( + () => + menuItemCreateOpts.data.menuItemCreate.errors + ) + ); - return ( - <> - data.menu)} - onBack={() => navigate(menuListUrl())} - onDelete={() => - navigate( - menuUrl(id, { - action: "remove" - }) - ) - } - onItemAdd={() => - navigate( - menuUrl(id, { - action: "add-item" - }) - ) - } - onItemClick={handleItemClick} - onItemEdit={itemId => - navigate( - menuUrl(id, { - action: "edit-item", - id: itemId - }) - ) - } - onSubmit={handleSubmit} - saveButtonState={updateState} - /> - - menuDelete({ variables: { id } }) - } - variant="delete" - title={intl.formatMessage({ - defaultMessage: "Delete Menu", - description: "dialog header", - id: "menuDetailsDeleteMenuHeader" - })} - > - - - {maybe( - () => data.menu.name, - "..." - )} - - ) - }} - /> - - + return ( + + menuItemCreateOpts.data.menuItemCreate.errors, + [] + )} + pages={pages} + loading={ + categorySearch.result.loading || + collectionSearch.result.loading + } + confirmButtonState={formTransitionState} + disabled={menuItemCreateOpts.loading} + onClose={closeModal} + onSubmit={handleSubmit} + onQueryChange={handleQueryChange} + /> + ); + }} + + + handleItemUpdate(data, id, navigate, notify, intl) + } + > + {(menuItemUpdate, menuItemUpdateOpts) => { + const handleSubmit = ( + data: MenuItemDialogFormData + ) => { + const variables: MenuItemUpdateVariables = { + id: params.id, + input: getMenuItemInputData(data) + }; - - handleItemCreate( - data, - notify, - closeModal, - intl - ) - } - > - {(menuItemCreate, menuItemCreateOpts) => { - const handleSubmit = ( - data: MenuItemDialogFormData - ) => { - const variables: MenuItemCreateVariables = { - input: getMenuItemCreateInputData( - id, - data - ) - }; + menuItemUpdate({ variables }); + }; - menuItemCreate({ variables }); - }; + const menuItem = maybe(() => + getNode( + data.menu.items, + findNode(data.menu.items, params.id) + ) + ); - const formTransitionState = getMutationState( - menuItemCreateOpts.called, - menuItemCreateOpts.loading, - maybe( - () => - menuItemCreateOpts.data - .menuItemCreate.errors - ) - ); + const formTransitionState = getMutationState( + menuItemUpdateOpts.called, + menuItemUpdateOpts.loading, + maybe( + () => + menuItemUpdateOpts.data.menuItemUpdate.errors + ) + ); - return ( - - menuItemCreateOpts.data - .menuItemCreate.errors, - [] - )} - pages={pages} - loading={ - categorySearch.result.loading || - collectionSearch.result.loading - } - confirmButtonState={ - formTransitionState - } - disabled={menuItemCreateOpts.loading} - onClose={closeModal} - onSubmit={handleSubmit} - onQueryChange={handleQueryChange} - /> - ); - }} - - - handleItemUpdate( - data, - id, - navigate, - notify, - intl - ) - } - > - {(menuItemUpdate, menuItemUpdateOpts) => { - const handleSubmit = ( - data: MenuItemDialogFormData - ) => { - const variables: MenuItemUpdateVariables = { - id: params.id, - input: getMenuItemInputData(data) - }; + const initialFormData: MenuItemDialogFormData = { + id: maybe(() => getItemId(menuItem)), + name: maybe(() => menuItem.name, "..."), + type: maybe( + () => getItemType(menuItem), + "category" + ) + }; - menuItemUpdate({ variables }); - }; - - const menuItem = maybe(() => - getNode( - data.menu.items, - findNode(data.menu.items, params.id) - ) - ); - - const formTransitionState = getMutationState( - menuItemUpdateOpts.called, - menuItemUpdateOpts.loading, - maybe( - () => - menuItemUpdateOpts.data - .menuItemUpdate.errors - ) - ); - - const initialFormData: MenuItemDialogFormData = { - id: maybe(() => getItemId(menuItem)), - name: maybe(() => menuItem.name, "..."), - type: maybe( - () => getItemType(menuItem), - "category" - ) - }; - - return ( - - menuItemUpdateOpts.data - .menuItemUpdate.errors, - [] - )} - pages={pages} - initial={initialFormData} - initialDisplayValue={getInitialDisplayValue( - menuItem - )} - loading={ - categorySearch.result.loading || - collectionSearch.result.loading - } - confirmButtonState={ - formTransitionState - } - disabled={menuItemUpdateOpts.loading} - onClose={closeModal} - onSubmit={handleSubmit} - onQueryChange={handleQueryChange} - /> - ); - }} - - - ); - }} - - )} - - ); - }} - - )} - - )} - - )} - + return ( + + menuItemUpdateOpts.data.menuItemUpdate.errors, + [] + )} + pages={pages} + initial={initialFormData} + initialDisplayValue={getInitialDisplayValue( + menuItem + )} + loading={ + categorySearch.result.loading || + collectionSearch.result.loading + } + confirmButtonState={formTransitionState} + disabled={menuItemUpdateOpts.loading} + onClose={closeModal} + onSubmit={handleSubmit} + onQueryChange={handleQueryChange} + /> + ); + }} + + + ); + }} + + )} + + ); + }} + ); }; MenuDetails.displayName = "MenuDetails"; diff --git a/src/orders/components/OrderCustomer/OrderCustomer.tsx b/src/orders/components/OrderCustomer/OrderCustomer.tsx index 0665e269a..59782696c 100644 --- a/src/orders/components/OrderCustomer/OrderCustomer.tsx +++ b/src/orders/components/OrderCustomer/OrderCustomer.tsx @@ -16,10 +16,10 @@ import SingleAutocompleteSelectField from "@saleor/components/SingleAutocomplete import Skeleton from "@saleor/components/Skeleton"; import useStateFromProps from "@saleor/hooks/useStateFromProps"; import { buttonMessages } from "@saleor/intl"; +import { SearchCustomers_search_edges_node } from "@saleor/searches/types/SearchCustomers"; import { FetchMoreProps, UserPermissionProps } from "@saleor/types"; import { PermissionEnum } from "@saleor/types/globalTypes"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; -import { SearchCustomers_search_edges_node } from "../../../containers/SearchCustomers/types/SearchCustomers"; import { customerUrl } from "../../../customers/urls"; import { createHref, maybe } from "../../../misc"; import { OrderDetails_order } from "../../types/OrderDetails"; diff --git a/src/orders/components/OrderDraftPage/OrderDraftPage.tsx b/src/orders/components/OrderDraftPage/OrderDraftPage.tsx index dbe3ea00c..d36642b84 100644 --- a/src/orders/components/OrderDraftPage/OrderDraftPage.tsx +++ b/src/orders/components/OrderDraftPage/OrderDraftPage.tsx @@ -13,8 +13,8 @@ import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; import Skeleton from "@saleor/components/Skeleton"; import { sectionNames } from "@saleor/intl"; +import { SearchCustomers_search_edges_node } from "@saleor/searches/types/SearchCustomers"; import { FetchMoreProps, UserPermissionProps } from "@saleor/types"; -import { SearchCustomers_search_edges_node } from "../../../containers/SearchCustomers/types/SearchCustomers"; import { maybe } from "../../../misc"; import { DraftOrderInput } from "../../../types/globalTypes"; import { OrderDetails_order } from "../../types/OrderDetails"; diff --git a/src/orders/fixtures.ts b/src/orders/fixtures.ts index af8a13c45..4463ec60c 100644 --- a/src/orders/fixtures.ts +++ b/src/orders/fixtures.ts @@ -1,5 +1,5 @@ +import { SearchCustomers_search_edges_node } from "@saleor/searches/types/SearchCustomers"; import { MessageDescriptor } from "react-intl"; -import { SearchCustomers_search_edges_node } from "../containers/SearchCustomers/types/SearchCustomers"; import { transformOrderStatus, transformPaymentStatus } from "../misc"; import { FulfillmentStatus, diff --git a/src/orders/queries.ts b/src/orders/queries.ts index 47a6add2f..a18c65894 100644 --- a/src/orders/queries.ts +++ b/src/orders/queries.ts @@ -1,6 +1,6 @@ import gql from "graphql-tag"; -import TopLevelSearch from "../containers/TopLevelSearch"; +import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; import { TypedQuery } from "../queries"; import { OrderDetails, OrderDetailsVariables } from "./types/OrderDetails"; import { @@ -314,7 +314,7 @@ export const searchOrderVariant = gql` } } `; -export const SearchOrderVariant = TopLevelSearch< +export const useOrderVariantSearch = makeTopLevelSearch< SearchOrderVariantType, SearchOrderVariantVariables >(searchOrderVariant); diff --git a/src/orders/views/OrderDetails/index.tsx b/src/orders/views/OrderDetails/index.tsx index 6d48bebe7..38b079ffb 100644 --- a/src/orders/views/OrderDetails/index.tsx +++ b/src/orders/views/OrderDetails/index.tsx @@ -1,10 +1,10 @@ import React from "react"; import { WindowTitle } from "@saleor/components/WindowTitle"; +import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config"; import useNavigator from "@saleor/hooks/useNavigator"; import useUser from "@saleor/hooks/useUser"; -import { DEFAULT_INITIAL_SEARCH_DATA } from "../../../config"; -import SearchCustomers from "../../../containers/SearchCustomers"; +import useCustomerSearch from "@saleor/searches/useCustomerSearch"; import { customerUrl } from "../../../customers/urls"; import { getMutationState, maybe, transformAddressToForm } from "../../../misc"; import { productUrl } from "../../../products/urls"; @@ -26,7 +26,7 @@ import OrderPaymentVoidDialog from "../../components/OrderPaymentVoidDialog"; import OrderProductAddDialog from "../../components/OrderProductAddDialog"; import OrderShippingMethodEditDialog from "../../components/OrderShippingMethodEditDialog"; import OrderOperations from "../../containers/OrderOperations"; -import { SearchOrderVariant, TypedOrderDetailsQuery } from "../../queries"; +import { TypedOrderDetailsQuery, useOrderVariantSearch } from "../../queries"; import { OrderDetails_order } from "../../types/OrderDetails"; import { orderListUrl, @@ -74,6 +74,20 @@ interface OrderDetailsProps { export const OrderDetails: React.FC = ({ id, params }) => { const navigate = useNavigator(); const { user } = useUser(); + const { + loadMore: loadMoreCustomers, + search: searchUsers, + result: users + } = useCustomerSearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); + const { + loadMore, + search: variantSearch, + result: variantSearchOpts + } = useOrderVariantSearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); return ( = ({ id, params }) => { }) ); return ( - - {({ - loadMore: loadMoreCustomers, - search: searchUsers, - result: users - }) => ( - - {orderMessages => ( - - {({ - orderAddNote, - orderCancel, - orderCreateFulfillment, - orderDraftUpdate, - orderLinesAdd, - orderLineDelete, - orderLineUpdate, - orderPaymentCapture, - orderPaymentRefund, - orderVoid, - orderShippingMethodUpdate, - orderUpdate, - orderFulfillmentCancel, - orderFulfillmentUpdateTracking, - orderDraftCancel, - orderDraftFinalize, - orderPaymentMarkAsPaid - }) => { - const finalizeTransitionState = getMutationState( - orderDraftFinalize.opts.called, - orderDraftFinalize.opts.loading, - maybe( - () => - orderDraftFinalize.opts.data.draftOrderComplete - .errors - ) - ); - return ( + + {orderMessages => ( + + {({ + orderAddNote, + orderCancel, + orderCreateFulfillment, + orderDraftUpdate, + orderLinesAdd, + orderLineDelete, + orderLineUpdate, + orderPaymentCapture, + orderPaymentRefund, + orderVoid, + orderShippingMethodUpdate, + orderUpdate, + orderFulfillmentCancel, + orderFulfillmentUpdateTracking, + orderDraftCancel, + orderDraftFinalize, + orderPaymentMarkAsPaid + }) => { + const finalizeTransitionState = getMutationState( + orderDraftFinalize.opts.called, + orderDraftFinalize.opts.loading, + maybe( + () => + orderDraftFinalize.opts.data.draftOrderComplete.errors + ) + ); + return ( + <> + {maybe(() => order.status !== OrderStatus.DRAFT) ? ( <> - {maybe(() => order.status !== OrderStatus.DRAFT) ? ( - <> - "Order #" + data.order.number - )} - /> - - orderAddNote.mutate({ - input: variables, - order: id - }) - } - onBack={() => navigate(orderListUrl())} - order={order} - shippingMethods={maybe( - () => data.order.availableShippingMethods, - [] - )} - userPermissions={maybe( - () => user.permissions, - [] - )} - onOrderCancel={() => openModal("cancel")} - onOrderFulfill={() => openModal("fulfill")} - onFulfillmentCancel={fulfillmentId => - navigate( - orderUrl(id, { - action: "cancel-fulfillment", - id: fulfillmentId - }) - ) - } - onFulfillmentTrackingNumberUpdate={fulfillmentId => - navigate( - orderUrl(id, { - action: "edit-fulfillment", - id: fulfillmentId - }) - ) - } - onPaymentCapture={() => openModal("capture")} - onPaymentVoid={() => openModal("void")} - onPaymentRefund={() => openModal("refund")} - onProductClick={id => () => - navigate(productUrl(id))} - onBillingAddressEdit={() => - openModal("edit-billing-address") - } - onShippingAddressEdit={() => - openModal("edit-shipping-address") - } - onPaymentPaid={() => openModal("mark-paid")} - onProfileView={() => - navigate(customerUrl(order.user.id)) - } - /> - - orderCancel.opts.data.orderCancel.errors - ) - )} - number={maybe(() => order.number)} - open={params.action === "cancel"} - onClose={closeModal} - onSubmit={variables => - orderCancel.mutate({ - id, - ...variables - }) - } - /> - - orderPaymentMarkAsPaid.opts.data - .orderMarkAsPaid.errors - ) - )} - onClose={closeModal} - onConfirm={() => - orderPaymentMarkAsPaid.mutate({ - id - }) - } - open={params.action === "mark-paid"} - /> - orderVoid.opts.data.orderVoid.errors - ) - )} - open={params.action === "void"} - onClose={closeModal} - onConfirm={() => orderVoid.mutate({ id })} - /> - - orderPaymentCapture.opts.data.orderCapture - .errors - ) - )} - initial={maybe(() => order.total.gross.amount)} - open={params.action === "capture"} - variant="capture" - onClose={closeModal} - onSubmit={variables => - orderPaymentCapture.mutate({ - ...variables, - id - }) - } - /> - - orderPaymentRefund.opts.data.orderRefund - .errors - ) - )} - initial={maybe(() => order.total.gross.amount)} - open={params.action === "refund"} - variant="refund" - onClose={closeModal} - onSubmit={variables => - orderPaymentRefund.mutate({ - ...variables, - id - }) - } - /> - - orderCreateFulfillment.opts.data - .orderFulfillmentCreate.errors - ) - )} - open={params.action === "fulfill"} - lines={maybe(() => order.lines, []).filter( - line => line.quantityFulfilled < line.quantity - )} - onClose={closeModal} - onSubmit={variables => - orderCreateFulfillment.mutate({ - input: { - ...variables, - lines: maybe(() => order.lines, []) - .filter( - line => - line.quantityFulfilled < - line.quantity - ) - .map((line, lineIndex) => ({ - orderLineId: line.id, - quantity: variables.lines[lineIndex] - })) - .filter(line => line.quantity > 0) - }, - order: order.id - }) - } - /> - - orderFulfillmentCancel.opts.data - .orderFulfillmentCancel.errors - ) - )} - open={params.action === "cancel-fulfillment"} - onConfirm={variables => - orderFulfillmentCancel.mutate({ - id: params.id, - input: variables - }) - } - onClose={closeModal} - /> - - orderFulfillmentUpdateTracking.opts.data - .orderFulfillmentUpdateTracking.errors - ) - )} - open={params.action === "edit-fulfillment"} - trackingNumber={maybe( - () => - data.order.fulfillments.find( - fulfillment => - fulfillment.id === params.id - ).trackingNumber - )} - onConfirm={variables => - orderFulfillmentUpdateTracking.mutate({ - id: params.id, - input: { - ...variables, - notifyCustomer: true - } - }) - } - onClose={closeModal} - /> - - ) : ( - <> - "Draft order #" + data.order.number - )} - /> - - orderAddNote.mutate({ - input: variables, - order: id - }) - } - users={maybe( - () => - users.data.search.edges.map( - edge => edge.node - ), - [] - )} - hasMore={maybe( - () => users.data.search.pageInfo.hasNextPage, - false - )} - onFetchMore={loadMoreCustomers} - fetchUsers={searchUsers} - loading={users.loading} - usersLoading={users.loading} - onCustomerEdit={data => - orderDraftUpdate.mutate({ - id, - input: data - }) - } - onDraftFinalize={() => openModal("finalize")} - onDraftRemove={() => openModal("cancel")} - onOrderLineAdd={() => - openModal("add-order-line") - } - onBack={() => navigate(orderListUrl())} - order={order} - countries={maybe( - () => data.shop.countries, - [] - ).map(country => ({ - code: country.code, - label: country.country - }))} - onProductClick={id => () => - navigate(productUrl(encodeURIComponent(id)))} - onBillingAddressEdit={() => - openModal("edit-billing-address") - } - onShippingAddressEdit={() => - openModal("edit-shipping-address") - } - onShippingMethodEdit={() => - openModal("edit-shipping") - } - onOrderLineRemove={id => - orderLineDelete.mutate({ id }) - } - onOrderLineChange={(id, data) => - orderLineUpdate.mutate({ - id, - input: data - }) - } - saveButtonBarState="default" - onProfileView={() => - navigate(customerUrl(order.user.id)) - } - userPermissions={maybe( - () => user.permissions, - [] - )} - /> - - orderDraftCancel.opts.data - .draftOrderDelete.errors - ) - )} - onClose={closeModal} - onConfirm={() => - orderDraftCancel.mutate({ id }) - } - open={params.action === "cancel"} - orderNumber={maybe(() => order.number)} - /> - - orderDraftFinalize.mutate({ id }) - } - open={params.action === "finalize"} - orderNumber={maybe(() => order.number)} - warnings={orderDraftFinalizeWarnings(order)} - /> - - orderShippingMethodUpdate.opts.data - .orderUpdateShipping.errors - ) - )} - open={params.action === "edit-shipping"} - shippingMethod={maybe( - () => order.shippingMethod.id, - "..." - )} - shippingMethods={maybe( - () => order.availableShippingMethods - )} - onClose={closeModal} - onSubmit={variables => - orderShippingMethodUpdate.mutate({ - id, - input: { - shippingMethod: variables.shippingMethod - } - }) - } - /> - - {({ - loadMore, - search: variantSearch, - result: variantSearchOpts - }) => ( - - orderLinesAdd.opts.data - .draftOrderLinesCreate.errors - ) - )} - loading={variantSearchOpts.loading} - open={params.action === "add-order-line"} - hasMore={maybe( - () => - variantSearchOpts.data.search.pageInfo - .hasNextPage - )} - products={maybe(() => - variantSearchOpts.data.search.edges.map( - edge => edge.node - ) - )} - onClose={closeModal} - onFetch={variantSearch} - onFetchMore={loadMore} - onSubmit={variants => - orderLinesAdd.mutate({ - id, - input: variants.map(variant => ({ - quantity: 1, - variantId: variant.id - })) - }) - } - /> - )} - - - )} - "Order #" + data.order.number)} + /> + + orderAddNote.mutate({ + input: variables, + order: id + }) + } + onBack={() => navigate(orderListUrl())} + order={order} + shippingMethods={maybe( + () => data.order.availableShippingMethods, + [] + )} + userPermissions={maybe(() => user.permissions, [])} + onOrderCancel={() => openModal("cancel")} + onOrderFulfill={() => openModal("fulfill")} + onFulfillmentCancel={fulfillmentId => + navigate( + orderUrl(id, { + action: "cancel-fulfillment", + id: fulfillmentId + }) + ) + } + onFulfillmentTrackingNumberUpdate={fulfillmentId => + navigate( + orderUrl(id, { + action: "edit-fulfillment", + id: fulfillmentId + }) + ) + } + onPaymentCapture={() => openModal("capture")} + onPaymentVoid={() => openModal("void")} + onPaymentRefund={() => openModal("refund")} + onProductClick={id => () => + navigate(productUrl(id))} + onBillingAddressEdit={() => + openModal("edit-billing-address") + } + onShippingAddressEdit={() => + openModal("edit-shipping-address") + } + onPaymentPaid={() => openModal("mark-paid")} + onProfileView={() => + navigate(customerUrl(order.user.id)) + } + /> + orderUpdate.opts.data.orderUpdate.errors + () => orderCancel.opts.data.orderCancel.errors ) )} - address={transformAddressToForm( - maybe(() => order.shippingAddress) + number={maybe(() => order.number)} + open={params.action === "cancel"} + onClose={closeModal} + onSubmit={variables => + orderCancel.mutate({ + id, + ...variables + }) + } + /> + + orderPaymentMarkAsPaid.opts.data + .orderMarkAsPaid.errors + ) )} + onClose={closeModal} + onConfirm={() => + orderPaymentMarkAsPaid.mutate({ + id + }) + } + open={params.action === "mark-paid"} + /> + orderVoid.opts.data.orderVoid.errors) + )} + open={params.action === "void"} + onClose={closeModal} + onConfirm={() => orderVoid.mutate({ id })} + /> + + orderPaymentCapture.opts.data.orderCapture + .errors + ) + )} + initial={maybe(() => order.total.gross.amount)} + open={params.action === "capture"} + variant="capture" + onClose={closeModal} + onSubmit={variables => + orderPaymentCapture.mutate({ + ...variables, + id + }) + } + /> + + orderPaymentRefund.opts.data.orderRefund + .errors + ) + )} + initial={maybe(() => order.total.gross.amount)} + open={params.action === "refund"} + variant="refund" + onClose={closeModal} + onSubmit={variables => + orderPaymentRefund.mutate({ + ...variables, + id + }) + } + /> + + orderCreateFulfillment.opts.data + .orderFulfillmentCreate.errors + ) + )} + open={params.action === "fulfill"} + lines={maybe(() => order.lines, []).filter( + line => line.quantityFulfilled < line.quantity + )} + onClose={closeModal} + onSubmit={variables => + orderCreateFulfillment.mutate({ + input: { + ...variables, + lines: maybe(() => order.lines, []) + .filter( + line => + line.quantityFulfilled < line.quantity + ) + .map((line, lineIndex) => ({ + orderLineId: line.id, + quantity: variables.lines[lineIndex] + })) + .filter(line => line.quantity > 0) + }, + order: order.id + }) + } + /> + + orderFulfillmentCancel.opts.data + .orderFulfillmentCancel.errors + ) + )} + open={params.action === "cancel-fulfillment"} + onConfirm={variables => + orderFulfillmentCancel.mutate({ + id: params.id, + input: variables + }) + } + onClose={closeModal} + /> + + orderFulfillmentUpdateTracking.opts.data + .orderFulfillmentUpdateTracking.errors + ) + )} + open={params.action === "edit-fulfillment"} + trackingNumber={maybe( + () => + data.order.fulfillments.find( + fulfillment => fulfillment.id === params.id + ).trackingNumber + )} + onConfirm={variables => + orderFulfillmentUpdateTracking.mutate({ + id: params.id, + input: { + ...variables, + notifyCustomer: true + } + }) + } + onClose={closeModal} + /> + + ) : ( + <> + "Draft order #" + data.order.number + )} + /> + + orderAddNote.mutate({ + input: variables, + order: id + }) + } + users={maybe( + () => + users.data.search.edges.map(edge => edge.node), + [] + )} + hasMore={maybe( + () => users.data.search.pageInfo.hasNextPage, + false + )} + onFetchMore={loadMoreCustomers} + fetchUsers={searchUsers} + loading={users.loading} + usersLoading={users.loading} + onCustomerEdit={data => + orderDraftUpdate.mutate({ + id, + input: data + }) + } + onDraftFinalize={() => openModal("finalize")} + onDraftRemove={() => openModal("cancel")} + onOrderLineAdd={() => openModal("add-order-line")} + onBack={() => navigate(orderListUrl())} + order={order} countries={maybe(() => data.shop.countries, []).map( country => ({ code: country.code, label: country.country }) )} - errors={maybe( - () => orderUpdate.opts.data.orderUpdate.errors, - [] + onProductClick={id => () => + navigate(productUrl(encodeURIComponent(id)))} + onBillingAddressEdit={() => + openModal("edit-billing-address") + } + onShippingAddressEdit={() => + openModal("edit-shipping-address") + } + onShippingMethodEdit={() => + openModal("edit-shipping") + } + onOrderLineRemove={id => + orderLineDelete.mutate({ id }) + } + onOrderLineChange={(id, data) => + orderLineUpdate.mutate({ + id, + input: data + }) + } + saveButtonBarState="default" + onProfileView={() => + navigate(customerUrl(order.user.id)) + } + userPermissions={maybe(() => user.permissions, [])} + /> + + orderDraftCancel.opts.data.draftOrderDelete + .errors + ) )} - open={params.action === "edit-shipping-address"} - variant="shipping" onClose={closeModal} - onConfirm={shippingAddress => - orderUpdate.mutate({ + onConfirm={() => orderDraftCancel.mutate({ id })} + open={params.action === "cancel"} + orderNumber={maybe(() => order.number)} + /> + orderDraftFinalize.mutate({ id })} + open={params.action === "finalize"} + orderNumber={maybe(() => order.number)} + warnings={orderDraftFinalizeWarnings(order)} + /> + + orderShippingMethodUpdate.opts.data + .orderUpdateShipping.errors + ) + )} + open={params.action === "edit-shipping"} + shippingMethod={maybe( + () => order.shippingMethod.id, + "..." + )} + shippingMethods={maybe( + () => order.availableShippingMethods + )} + onClose={closeModal} + onSubmit={variables => + orderShippingMethodUpdate.mutate({ id, input: { - shippingAddress + shippingMethod: variables.shippingMethod } }) } /> - orderUpdate.opts.data.orderUpdate.errors + () => + orderLinesAdd.opts.data.draftOrderLinesCreate + .errors ) )} - address={transformAddressToForm( - maybe(() => order.billingAddress) + loading={variantSearchOpts.loading} + open={params.action === "add-order-line"} + hasMore={maybe( + () => + variantSearchOpts.data.search.pageInfo + .hasNextPage )} - countries={maybe(() => data.shop.countries, []).map( - country => ({ - code: country.code, - label: country.country - }) + products={maybe(() => + variantSearchOpts.data.search.edges.map( + edge => edge.node + ) )} - errors={maybe( - () => orderUpdate.opts.data.orderUpdate.errors, - [] - )} - open={params.action === "edit-billing-address"} - variant="billing" onClose={closeModal} - onConfirm={billingAddress => - orderUpdate.mutate({ + onFetch={variantSearch} + onFetchMore={loadMore} + onSubmit={variants => + orderLinesAdd.mutate({ id, - input: { - billingAddress - } + input: variants.map(variant => ({ + quantity: 1, + variantId: variant.id + })) }) } /> - ); - }} - - )} - + )} + orderUpdate.opts.data.orderUpdate.errors) + )} + address={transformAddressToForm( + maybe(() => order.shippingAddress) + )} + countries={maybe(() => data.shop.countries, []).map( + country => ({ + code: country.code, + label: country.country + }) + )} + errors={maybe( + () => orderUpdate.opts.data.orderUpdate.errors, + [] + )} + open={params.action === "edit-shipping-address"} + variant="shipping" + onClose={closeModal} + onConfirm={shippingAddress => + orderUpdate.mutate({ + id, + input: { + shippingAddress + } + }) + } + /> + orderUpdate.opts.data.orderUpdate.errors) + )} + address={transformAddressToForm( + maybe(() => order.billingAddress) + )} + countries={maybe(() => data.shop.countries, []).map( + country => ({ + code: country.code, + label: country.country + }) + )} + errors={maybe( + () => orderUpdate.opts.data.orderUpdate.errors, + [] + )} + open={params.action === "edit-billing-address"} + variant="billing" + onClose={closeModal} + onConfirm={billingAddress => + orderUpdate.mutate({ + id, + input: { + billingAddress + } + }) + } + /> + + ); + }} + )} - + ); }} diff --git a/src/productTypes/components/AssignAttributeDialog/AssignAttributeDialog.tsx b/src/productTypes/components/AssignAttributeDialog/AssignAttributeDialog.tsx index afc397718..6b4f93093 100644 --- a/src/productTypes/components/AssignAttributeDialog/AssignAttributeDialog.tsx +++ b/src/productTypes/components/AssignAttributeDialog/AssignAttributeDialog.tsx @@ -30,7 +30,7 @@ import useSearchQuery from "@saleor/hooks/useSearchQuery"; import { buttonMessages } from "@saleor/intl"; import { maybe, renderCollection } from "@saleor/misc"; import { FetchMoreProps } from "@saleor/types"; -import { SearchAttributes_productType_availableAttributes_edges_node } from "../../containers/SearchAttributes/types/SearchAttributes"; +import { SearchAttributes_productType_availableAttributes_edges_node } from "../../hooks/useAvailableAttributeSearch/types/SearchAttributes"; const useStyles = makeStyles(theme => ({ actions: { diff --git a/src/productTypes/fixtures.ts b/src/productTypes/fixtures.ts index 17ef73a82..ffd35d801 100644 --- a/src/productTypes/fixtures.ts +++ b/src/productTypes/fixtures.ts @@ -1,7 +1,7 @@ import { SearchProductTypes_search_edges_node, SearchProductTypes_search_edges_node_productAttributes -} from "@saleor/containers/SearchProductTypes/types/SearchProductTypes"; +} from "@saleor/searches/types/SearchProductTypes"; import { AttributeInputTypeEnum } from "../types/globalTypes"; import { ProductTypeDetails_productType } from "./types/ProductTypeDetails"; import { ProductTypeList_productTypes_edges_node } from "./types/ProductTypeList"; diff --git a/src/productTypes/containers/SearchAttributes/index.tsx b/src/productTypes/hooks/useAvailableAttributeSearch/index.tsx similarity index 52% rename from src/productTypes/containers/SearchAttributes/index.tsx rename to src/productTypes/hooks/useAvailableAttributeSearch/index.tsx index 8f00cbf5b..6a3d7037d 100644 --- a/src/productTypes/containers/SearchAttributes/index.tsx +++ b/src/productTypes/hooks/useAvailableAttributeSearch/index.tsx @@ -1,7 +1,7 @@ import gql from "graphql-tag"; +import makeSearch from "@saleor/hooks/makeSearch"; import { pageInfoFragment } from "@saleor/queries"; -import BaseSearch from "../../../containers/BaseSearch"; import { SearchAttributes, SearchAttributesVariables @@ -37,24 +37,33 @@ export const searchAttributes = gql` } `; -export default BaseSearch( +export default makeSearch( searchAttributes, result => result.loadMore( - (prev, next) => ({ - ...prev, - productType: { - ...prev.productType, - availableAttributes: { - ...prev.productType.availableAttributes, - edges: [ - ...prev.productType.availableAttributes.edges, - ...next.productType.availableAttributes.edges - ], - pageInfo: next.productType.availableAttributes.pageInfo - } + (prev, next) => { + if ( + prev.productType.availableAttributes.pageInfo.endCursor === + next.productType.availableAttributes.pageInfo.endCursor + ) { + return prev; } - }), + + return { + ...prev, + productType: { + ...prev.productType, + availableAttributes: { + ...prev.productType.availableAttributes, + edges: [ + ...prev.productType.availableAttributes.edges, + ...next.productType.availableAttributes.edges + ], + pageInfo: next.productType.availableAttributes.pageInfo + } + } + }; + }, { after: result.data.productType.availableAttributes.pageInfo.endCursor } diff --git a/src/productTypes/containers/SearchAttributes/types/SearchAttributes.ts b/src/productTypes/hooks/useAvailableAttributeSearch/types/SearchAttributes.ts similarity index 100% rename from src/productTypes/containers/SearchAttributes/types/SearchAttributes.ts rename to src/productTypes/hooks/useAvailableAttributeSearch/types/SearchAttributes.ts diff --git a/src/productTypes/views/ProductTypeUpdate/index.tsx b/src/productTypes/views/ProductTypeUpdate/index.tsx index 73510adbd..5e01da310 100644 --- a/src/productTypes/views/ProductTypeUpdate/index.tsx +++ b/src/productTypes/views/ProductTypeUpdate/index.tsx @@ -4,6 +4,7 @@ import { FormattedMessage, useIntl } from "react-intl"; import { attributeUrl } from "@saleor/attributes/urls"; import { WindowTitle } from "@saleor/components/WindowTitle"; +import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config"; import useBulkActions from "@saleor/hooks/useBulkActions"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; @@ -19,7 +20,7 @@ import ProductTypeDetailsPage, { ProductTypeForm } from "../../components/ProductTypeDetailsPage"; import ProductTypeOperations from "../../containers/ProductTypeOperations"; -import SearchAttributes from "../../containers/SearchAttributes"; +import useAvailableAttributeSearch from "../../hooks/useAvailableAttributeSearch"; import { TypedProductTypeDetailsQuery } from "../../queries"; import { AssignAttribute } from "../../types/AssignAttribute"; import { ProductTypeDelete } from "../../types/ProductTypeDelete"; @@ -46,6 +47,12 @@ export const ProductTypeUpdate: React.FC = ({ const productAttributeListActions = useBulkActions(); const variantAttributeListActions = useBulkActions(); const intl = useIntl(); + const { loadMore, search, result } = useAvailableAttributeSearch({ + variables: { + ...DEFAULT_INITIAL_SEARCH_DATA, + id + } + }); return ( @@ -330,109 +337,55 @@ export const ProductTypeUpdate: React.FC = ({ ) }} /> - {!dataLoading && ( - - {({ search, result }) => { - const fetchMore = () => - result.loadMore( - (prev, next) => { - if ( - prev.productType.availableAttributes - .pageInfo.endCursor === - next.productType.availableAttributes - .pageInfo.endCursor - ) { - return prev; - } - return { - ...prev, - productType: { - ...prev.productType, - availableAttributes: { - ...prev.productType.availableAttributes, - edges: [ - ...prev.productType - .availableAttributes.edges, - ...next.productType - .availableAttributes.edges - ], - pageInfo: - next.productType.availableAttributes - .pageInfo - } - } - }; - }, - { - after: - result.data.productType.availableAttributes - .pageInfo.endCursor - } - ); - - return ( - <> - {Object.keys(AttributeTypeEnum).map(key => ( - - result.data.productType.availableAttributes.edges.map( - edge => edge.node + {!dataLoading && + Object.keys(AttributeTypeEnum).map(key => ( + + result.data.productType.availableAttributes.edges.map( + edge => edge.node + ) + )} + confirmButtonState={assignTransactionState} + errors={maybe( + () => + assignAttribute.opts.data.attributeAssign.errors.map( + err => err.message + ), + [] + )} + loading={result.loading} + onClose={closeModal} + onSubmit={handleAssignAttribute} + onFetch={search} + onFetchMore={loadMore} + onOpen={result.refetch} + hasMore={maybe( + () => + result.data.productType.availableAttributes + .pageInfo.hasNextPage, + false + )} + open={ + params.action === "assign-attribute" && + params.type === AttributeTypeEnum[key] + } + selected={maybe(() => params.ids, [])} + onToggle={attributeId => { + const ids = maybe(() => params.ids, []); + navigate( + productTypeUrl(id, { + ...params, + ids: ids.includes(attributeId) + ? params.ids.filter( + selectedId => selectedId !== attributeId ) - )} - confirmButtonState={assignTransactionState} - errors={maybe( - () => - assignAttribute.opts.data.attributeAssign.errors.map( - err => err.message - ), - [] - )} - loading={result.loading} - onClose={closeModal} - onSubmit={handleAssignAttribute} - onFetch={search} - onFetchMore={fetchMore} - onOpen={result.refetch} - hasMore={maybe( - () => - result.data.productType - .availableAttributes.pageInfo - .hasNextPage, - false - )} - open={ - params.action === "assign-attribute" && - params.type === AttributeTypeEnum[key] - } - selected={maybe(() => params.ids, [])} - onToggle={attributeId => { - const ids = maybe(() => params.ids, []); - navigate( - productTypeUrl(id, { - ...params, - ids: ids.includes(attributeId) - ? params.ids.filter( - selectedId => - selectedId !== attributeId - ) - : [...ids, attributeId] - }) - ); - }} - key={key} - /> - ))} - - ); - }} - - )} + : [...ids, attributeId] + }) + ); + }} + key={key} + /> + ))} data.productType.name, "...")} diff --git a/src/products/components/ProductCreatePage/ProductCreatePage.tsx b/src/products/components/ProductCreatePage/ProductCreatePage.tsx index 15bb0ca8b..af5293613 100644 --- a/src/products/components/ProductCreatePage/ProductCreatePage.tsx +++ b/src/products/components/ProductCreatePage/ProductCreatePage.tsx @@ -13,9 +13,6 @@ import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; import SeoForm from "@saleor/components/SeoForm"; import VisibilityCard from "@saleor/components/VisibilityCard"; -import { SearchCategories_search_edges_node } from "@saleor/containers/SearchCategories/types/SearchCategories"; -import { SearchCollections_search_edges_node } from "@saleor/containers/SearchCollections/types/SearchCollections"; -import { SearchProductTypes_search_edges_node_productAttributes } from "@saleor/containers/SearchProductTypes/types/SearchProductTypes"; import useDateLocalize from "@saleor/hooks/useDateLocalize"; import useFormset from "@saleor/hooks/useFormset"; import useStateFromProps from "@saleor/hooks/useStateFromProps"; @@ -25,6 +22,9 @@ import { ProductAttributeValueChoices, ProductType } from "@saleor/products/utils/data"; +import { SearchCategories_search_edges_node } from "@saleor/searches/types/SearchCategories"; +import { SearchCollections_search_edges_node } from "@saleor/searches/types/SearchCollections"; +import { SearchProductTypes_search_edges_node_productAttributes } from "@saleor/searches/types/SearchProductTypes"; import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; import { FetchMoreProps, UserError } from "../../../types"; diff --git a/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx b/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx index 0859c6d4a..7269dcec6 100644 --- a/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx +++ b/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx @@ -12,13 +12,13 @@ import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; import SeoForm from "@saleor/components/SeoForm"; import VisibilityCard from "@saleor/components/VisibilityCard"; -import { SearchCategories_search_edges_node } from "@saleor/containers/SearchCategories/types/SearchCategories"; -import { SearchCollections_search_edges_node } from "@saleor/containers/SearchCollections/types/SearchCollections"; import useDateLocalize from "@saleor/hooks/useDateLocalize"; import useFormset from "@saleor/hooks/useFormset"; import useStateFromProps from "@saleor/hooks/useStateFromProps"; import { sectionNames } from "@saleor/intl"; import { maybe } from "@saleor/misc"; +import { SearchCategories_search_edges_node } from "@saleor/searches/types/SearchCategories"; +import { SearchCollections_search_edges_node } from "@saleor/searches/types/SearchCollections"; import { FetchMoreProps, ListActions, UserError } from "@saleor/types"; import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; diff --git a/src/products/utils/data.ts b/src/products/utils/data.ts index 4c3a2eec6..fd4abe9cf 100644 --- a/src/products/utils/data.ts +++ b/src/products/utils/data.ts @@ -2,13 +2,13 @@ import { RawDraftContentState } from "draft-js"; import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField"; import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField"; -import { SearchProductTypes_search_edges_node_productAttributes } from "@saleor/containers/SearchProductTypes/types/SearchProductTypes"; import { maybe } from "@saleor/misc"; import { ProductDetails_product, ProductDetails_product_collections, ProductDetails_product_variants } from "@saleor/products/types/ProductDetails"; +import { SearchProductTypes_search_edges_node_productAttributes } from "@saleor/searches/types/SearchProductTypes"; import { ProductAttributeInput } from "../components/ProductAttributes"; import { VariantAttributeInput } from "../components/ProductVariantAttributes"; import { ProductVariant } from "../types/ProductVariant"; diff --git a/src/products/views/ProductCreate.tsx b/src/products/views/ProductCreate.tsx index fded16046..f71ef477c 100644 --- a/src/products/views/ProductCreate.tsx +++ b/src/products/views/ProductCreate.tsx @@ -2,13 +2,13 @@ import React from "react"; import { useIntl } from "react-intl"; import { WindowTitle } from "@saleor/components/WindowTitle"; -import SearchProductTypes from "@saleor/containers/SearchProductTypes"; +import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import useShop from "@saleor/hooks/useShop"; -import { DEFAULT_INITIAL_SEARCH_DATA } from "../../config"; -import SearchCategories from "../../containers/SearchCategories"; -import SearchCollections from "../../containers/SearchCollections"; +import useCategorySearch from "@saleor/searches/useCategorySearch"; +import useCollectionSearch from "@saleor/searches/useCollectionSearch"; +import useProductTypeSearch from "@saleor/searches/useProductTypeSearch"; import { decimal, getMutationState, maybe } from "../../misc"; import ProductCreatePage, { ProductCreatePageSubmitData @@ -26,174 +26,152 @@ export const ProductUpdate: React.FC = () => { const notify = useNotifier(); const shop = useShop(); const intl = useIntl(); + const { + loadMore: loadMoreCategories, + search: searchCategory, + result: searchCategoryOpts + } = useCategorySearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); + const { + loadMore: loadMoreCollections, + search: searchCollection, + result: searchCollectionOpts + } = useCollectionSearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); + const { + loadMore: loadMoreProductTypes, + search: searchProductTypes, + result: searchProductTypesOpts + } = useProductTypeSearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); const handleBack = () => navigate(productListUrl()); + const handleSuccess = (data: ProductCreate) => { + if (data.productCreate.errors.length === 0) { + notify({ + text: intl.formatMessage({ + defaultMessage: "Product created" + }) + }); + navigate(productUrl(data.productCreate.product.id)); + } else { + const attributeError = data.productCreate.errors.find( + err => err.field === "attributes" + ); + if (!!attributeError) { + notify({ text: attributeError.message }); + } + } + }; + return ( - - {({ - loadMore: loadMoreCategories, - search: searchCategory, - result: searchCategoryOpts - }) => ( - - {({ - loadMore: loadMoreCollections, - search: searchCollection, - result: searchCollectionOpts - }) => ( - - {({ - loadMore: loadMoreProductTypes, - search: searchProductTypes, - result: searchProductTypesOpts - }) => { - const handleSuccess = (data: ProductCreate) => { - if (data.productCreate.errors.length === 0) { - notify({ - text: intl.formatMessage({ - defaultMessage: "Product created" - }) - }); - navigate(productUrl(data.productCreate.product.id)); - } else { - const attributeError = data.productCreate.errors.find( - err => err.field === "attributes" - ); - if (!!attributeError) { - notify({ text: attributeError.message }); - } - } - }; + + {( + productCreate, + { + called: productCreateCalled, + data: productCreateData, + loading: productCreateDataLoading + } + ) => { + const handleSubmit = (formData: ProductCreatePageSubmitData) => { + productCreate({ + variables: { + attributes: formData.attributes.map(attribute => ({ + id: attribute.id, + values: attribute.value + })), + basePrice: decimal(formData.basePrice), + category: formData.category, + chargeTaxes: formData.chargeTaxes, + collections: formData.collections, + descriptionJson: JSON.stringify(formData.description), + isPublished: formData.isPublished, + name: formData.name, + productType: formData.productType, + publicationDate: + formData.publicationDate !== "" + ? formData.publicationDate + : null, + seo: { + description: formData.seoDescription, + title: formData.seoTitle + }, + sku: formData.sku, + stockQuantity: + formData.stockQuantity !== null ? formData.stockQuantity : 0 + } + }); + }; - return ( - - {( - productCreate, - { - called: productCreateCalled, - data: productCreateData, - loading: productCreateDataLoading - } - ) => { - const handleSubmit = ( - formData: ProductCreatePageSubmitData - ) => { - productCreate({ - variables: { - attributes: formData.attributes.map(attribute => ({ - id: attribute.id, - values: attribute.value - })), - basePrice: decimal(formData.basePrice), - category: formData.category, - chargeTaxes: formData.chargeTaxes, - collections: formData.collections, - descriptionJson: JSON.stringify( - formData.description - ), - isPublished: formData.isPublished, - name: formData.name, - productType: formData.productType, - publicationDate: - formData.publicationDate !== "" - ? formData.publicationDate - : null, - seo: { - description: formData.seoDescription, - title: formData.seoTitle - }, - sku: formData.sku, - stockQuantity: - formData.stockQuantity !== null - ? formData.stockQuantity - : 0 - } - }); - }; - - const formTransitionState = getMutationState( - productCreateCalled, - productCreateDataLoading, - maybe(() => productCreateData.productCreate.errors) - ); - return ( - <> - - shop.defaultCurrency)} - categories={maybe( - () => searchCategoryOpts.data.search.edges, - [] - ).map(edge => edge.node)} - collections={maybe( - () => searchCollectionOpts.data.search.edges, - [] - ).map(edge => edge.node)} - disabled={productCreateDataLoading} - errors={maybe( - () => productCreateData.productCreate.errors, - [] - )} - fetchCategories={searchCategory} - fetchCollections={searchCollection} - fetchProductTypes={searchProductTypes} - header={intl.formatMessage({ - defaultMessage: "New Product", - description: "page header" - })} - productTypes={maybe(() => - searchProductTypesOpts.data.search.edges.map( - edge => edge.node - ) - )} - onBack={handleBack} - onSubmit={handleSubmit} - saveButtonBarState={formTransitionState} - fetchMoreCategories={{ - hasMore: maybe( - () => - searchCategoryOpts.data.search.pageInfo - .hasNextPage - ), - loading: searchCategoryOpts.loading, - onFetchMore: loadMoreCategories - }} - fetchMoreCollections={{ - hasMore: maybe( - () => - searchCollectionOpts.data.search.pageInfo - .hasNextPage - ), - loading: searchCollectionOpts.loading, - onFetchMore: loadMoreCollections - }} - fetchMoreProductTypes={{ - hasMore: maybe( - () => - searchProductTypesOpts.data.search.pageInfo - .hasNextPage - ), - loading: searchProductTypesOpts.loading, - onFetchMore: loadMoreProductTypes - }} - /> - - ); - }} - - ); + const formTransitionState = getMutationState( + productCreateCalled, + productCreateDataLoading, + maybe(() => productCreateData.productCreate.errors) + ); + return ( + <> + + shop.defaultCurrency)} + categories={maybe( + () => searchCategoryOpts.data.search.edges, + [] + ).map(edge => edge.node)} + collections={maybe( + () => searchCollectionOpts.data.search.edges, + [] + ).map(edge => edge.node)} + disabled={productCreateDataLoading} + errors={maybe(() => productCreateData.productCreate.errors, [])} + fetchCategories={searchCategory} + fetchCollections={searchCollection} + fetchProductTypes={searchProductTypes} + header={intl.formatMessage({ + defaultMessage: "New Product", + description: "page header" + })} + productTypes={maybe(() => + searchProductTypesOpts.data.search.edges.map(edge => edge.node) + )} + onBack={handleBack} + onSubmit={handleSubmit} + saveButtonBarState={formTransitionState} + fetchMoreCategories={{ + hasMore: maybe( + () => searchCategoryOpts.data.search.pageInfo.hasNextPage + ), + loading: searchCategoryOpts.loading, + onFetchMore: loadMoreCategories }} - - )} - - )} - + fetchMoreCollections={{ + hasMore: maybe( + () => searchCollectionOpts.data.search.pageInfo.hasNextPage + ), + loading: searchCollectionOpts.loading, + onFetchMore: loadMoreCollections + }} + fetchMoreProductTypes={{ + hasMore: maybe( + () => searchProductTypesOpts.data.search.pageInfo.hasNextPage + ), + loading: searchProductTypesOpts.loading, + onFetchMore: loadMoreProductTypes + }} + /> + + ); + }} + ); }; export default ProductUpdate; diff --git a/src/products/views/ProductUpdate/ProductUpdate.tsx b/src/products/views/ProductUpdate/ProductUpdate.tsx index 33ed7c1a2..f9943b63a 100644 --- a/src/products/views/ProductUpdate/ProductUpdate.tsx +++ b/src/products/views/ProductUpdate/ProductUpdate.tsx @@ -7,6 +7,7 @@ import { FormattedMessage, useIntl } from "react-intl"; import placeholderImg from "@assets/images/placeholder255x255.png"; import ActionDialog from "@saleor/components/ActionDialog"; import { WindowTitle } from "@saleor/components/WindowTitle"; +import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config"; import useBulkActions from "@saleor/hooks/useBulkActions"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; @@ -14,9 +15,8 @@ import useShop from "@saleor/hooks/useShop"; import { commonMessages } from "@saleor/intl"; import ProductVariantCreateDialog from "@saleor/products/components/ProductVariantCreateDialog/ProductVariantCreateDialog"; import { ProductVariantBulkCreate } from "@saleor/products/types/ProductVariantBulkCreate"; -import { DEFAULT_INITIAL_SEARCH_DATA } from "../../../config"; -import SearchCategories from "../../../containers/SearchCategories"; -import SearchCollections from "../../../containers/SearchCollections"; +import useCategorySearch from "@saleor/searches/useCategorySearch"; +import useCollectionSearch from "@saleor/searches/useCollectionSearch"; import { getMutationState, maybe } from "../../../misc"; import ProductUpdatePage from "../../components/ProductUpdatePage"; import ProductUpdateOperations from "../../containers/ProductUpdateOperations"; @@ -55,6 +55,20 @@ export const ProductUpdate: React.FC = ({ id, params }) => { ); const intl = useIntl(); const shop = useShop(); + const { + loadMore: loadMoreCategories, + search: searchCategories, + result: searchCategoriesOpts + } = useCategorySearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); + const { + loadMore: loadMoreCollections, + search: searchCollections, + result: searchCollectionsOpts + } = useCollectionSearch({ + variables: DEFAULT_INITIAL_SEARCH_DATA + }); const openModal = (action: ProductUrlDialog) => navigate( @@ -64,356 +78,320 @@ export const ProductUpdate: React.FC = ({ id, params }) => { ); return ( - - {({ - loadMore: loadMoreCategories, - search: searchCategories, - result: searchCategoriesOpts - }) => ( - - {({ - loadMore: loadMoreCollections, - search: searchCollections, - result: searchCollectionsOpts - }) => ( - - {({ data, loading, refetch }) => { - const handleDelete = () => { - notify({ - text: intl.formatMessage({ - defaultMessage: "Product removed" - }) - }); - navigate(productListUrl()); - }; - const handleUpdate = (data: ProductUpdateMutationResult) => { - if (data.productUpdate.errors.length === 0) { - notify({ - text: intl.formatMessage(commonMessages.savedChanges) - }); - } else { - const attributeError = data.productUpdate.errors.find( - err => err.field === "attributes" - ); - if (!!attributeError) { - notify({ text: attributeError.message }); - } - } - }; + + {({ data, loading, refetch }) => { + const handleDelete = () => { + notify({ + text: intl.formatMessage({ + defaultMessage: "Product removed" + }) + }); + navigate(productListUrl()); + }; + const handleUpdate = (data: ProductUpdateMutationResult) => { + if (data.productUpdate.errors.length === 0) { + notify({ + text: intl.formatMessage(commonMessages.savedChanges) + }); + } else { + const attributeError = data.productUpdate.errors.find( + err => err.field === "attributes" + ); + if (!!attributeError) { + notify({ text: attributeError.message }); + } + } + }; - const handleImageCreate = (data: ProductImageCreate) => { - const imageError = data.productImageCreate.errors.find( - error => - error.field === - ("image" as keyof ProductImageCreateVariables) - ); - if (imageError) { - notify({ - text: imageError.message - }); - } - }; - const handleImageDeleteSuccess = () => - notify({ - text: intl.formatMessage(commonMessages.savedChanges) - }); - const handleVariantAdd = () => - navigate(productVariantAddUrl(id)); + const handleImageCreate = (data: ProductImageCreate) => { + const imageError = data.productImageCreate.errors.find( + error => + error.field === ("image" as keyof ProductImageCreateVariables) + ); + if (imageError) { + notify({ + text: imageError.message + }); + } + }; + const handleImageDeleteSuccess = () => + notify({ + text: intl.formatMessage(commonMessages.savedChanges) + }); + const handleVariantAdd = () => navigate(productVariantAddUrl(id)); - const handleBulkProductVariantCreate = ( - data: ProductVariantBulkCreate - ) => { - if (data.productVariantBulkCreate.errors.length === 0) { - navigate(productUrl(id), true); - refetch(); - } - }; + const handleBulkProductVariantCreate = ( + data: ProductVariantBulkCreate + ) => { + if (data.productVariantBulkCreate.errors.length === 0) { + navigate(productUrl(id), true); + refetch(); + } + }; - const handleBulkProductVariantDelete = ( - data: ProductVariantBulkDelete - ) => { - if (data.productVariantBulkDelete.errors.length === 0) { - navigate(productUrl(id), true); - reset(); - refetch(); - } - }; + const handleBulkProductVariantDelete = ( + data: ProductVariantBulkDelete + ) => { + if (data.productVariantBulkDelete.errors.length === 0) { + navigate(productUrl(id), true); + reset(); + refetch(); + } + }; - const handleVariantCreatorOpen = () => - navigate( - productUrl(id, { - ...params, - action: "create-variants" - }) - ); + const handleVariantCreatorOpen = () => + navigate( + productUrl(id, { + ...params, + action: "create-variants" + }) + ); - const product = data ? data.product : undefined; - return ( - + {({ + bulkProductVariantCreate, + bulkProductVariantDelete, + createProductImage, + deleteProduct, + deleteProductImage, + reorderProductImages, + updateProduct, + updateSimpleProduct + }) => { + const handleImageDelete = (id: string) => () => + deleteProductImage.mutate({ id }); + const handleImageEdit = (imageId: string) => () => + navigate(productImageUrl(id, imageId)); + const handleSubmit = createUpdateHandler( + product, + updateProduct.mutate, + updateSimpleProduct.mutate + ); + const handleImageUpload = createImageUploadHandler( + id, + createProductImage.mutate + ); + const handleImageReorder = createImageReorderHandler( + product, + reorderProductImages.mutate + ); + + const disableFormSave = + createProductImage.opts.loading || + deleteProduct.opts.loading || + reorderProductImages.opts.loading || + updateProduct.opts.loading || + loading; + const formTransitionState = getMutationState( + updateProduct.opts.called || updateSimpleProduct.opts.called, + updateProduct.opts.loading || updateSimpleProduct.opts.loading, + maybe(() => updateProduct.opts.data.productUpdate.errors), + maybe(() => updateSimpleProduct.opts.data.productUpdate.errors), + maybe( + () => + updateSimpleProduct.opts.data.productVariantUpdate.errors + ) + ); + const deleteTransitionState = getMutationState( + deleteProduct.opts.called, + deleteProduct.opts.loading, + maybe(() => deleteProduct.opts.data.productDelete.errors) + ); + + const bulkProductVariantDeleteTransitionState = getMutationState( + bulkProductVariantDelete.opts.called, + bulkProductVariantDelete.opts.loading, + maybe( + () => + bulkProductVariantDelete.opts.data.productVariantBulkDelete + .errors + ) + ); + + const categories = maybe( + () => searchCategoriesOpts.data.search.edges, + [] + ).map(edge => edge.node); + const collections = maybe( + () => searchCollectionsOpts.data.search.edges, + [] + ).map(edge => edge.node); + const errors = maybe( + () => updateProduct.opts.data.productUpdate.errors, + [] + ); + + return ( + <> + data.product.name)} /> + data.product.images)} + header={maybe(() => product.name)} + placeholderImage={placeholderImg} product={product} - onBulkProductVariantCreate={handleBulkProductVariantCreate} - onBulkProductVariantDelete={handleBulkProductVariantDelete} - onDelete={handleDelete} - onImageCreate={handleImageCreate} - onImageDelete={handleImageDeleteSuccess} - onUpdate={handleUpdate} - > - {({ - bulkProductVariantCreate, - bulkProductVariantDelete, - createProductImage, - deleteProduct, - deleteProductImage, - reorderProductImages, - updateProduct, - updateSimpleProduct - }) => { - const handleImageDelete = (id: string) => () => - deleteProductImage.mutate({ id }); - const handleImageEdit = (imageId: string) => () => - navigate(productImageUrl(id, imageId)); - const handleSubmit = createUpdateHandler( - product, - updateProduct.mutate, - updateSimpleProduct.mutate - ); - const handleImageUpload = createImageUploadHandler( - id, - createProductImage.mutate - ); - const handleImageReorder = createImageReorderHandler( - product, - reorderProductImages.mutate - ); - - const disableFormSave = - createProductImage.opts.loading || - deleteProduct.opts.loading || - reorderProductImages.opts.loading || - updateProduct.opts.loading || - loading; - const formTransitionState = getMutationState( - updateProduct.opts.called || - updateSimpleProduct.opts.called, - updateProduct.opts.loading || - updateSimpleProduct.opts.loading, - maybe( - () => updateProduct.opts.data.productUpdate.errors - ), - maybe( - () => - updateSimpleProduct.opts.data.productUpdate.errors - ), - maybe( - () => - updateSimpleProduct.opts.data.productVariantUpdate - .errors - ) - ); - const deleteTransitionState = getMutationState( - deleteProduct.opts.called, - deleteProduct.opts.loading, - maybe( - () => deleteProduct.opts.data.productDelete.errors - ) - ); - - const bulkProductVariantDeleteTransitionState = getMutationState( - bulkProductVariantDelete.opts.called, - bulkProductVariantDelete.opts.loading, - maybe( - () => - bulkProductVariantDelete.opts.data - .productVariantBulkDelete.errors - ) - ); - - const categories = maybe( - () => searchCategoriesOpts.data.search.edges, - [] - ).map(edge => edge.node); - const collections = maybe( - () => searchCollectionsOpts.data.search.edges, - [] - ).map(edge => edge.node); - const errors = maybe( - () => updateProduct.opts.data.productUpdate.errors, - [] - ); - - return ( - <> - data.product.name)} /> - data.product.images)} - header={maybe(() => product.name)} - placeholderImage={placeholderImg} - product={product} - variants={maybe(() => product.variants)} - onBack={() => { - navigate(productListUrl()); - }} - onDelete={() => openModal("remove")} - onProductShow={() => { - if (product) { - window.open(product.url); - } - }} - onImageReorder={handleImageReorder} - onSubmit={handleSubmit} - onVariantAdd={handleVariantAdd} - onVariantsAdd={handleVariantCreatorOpen} - onVariantShow={variantId => () => - navigate( - productVariantEditUrl(product.id, variantId) - )} - onImageUpload={handleImageUpload} - onImageEdit={handleImageEdit} - onImageDelete={handleImageDelete} - toolbar={ - - navigate( - productUrl(id, { - action: "remove-variants", - ids: listElements - }) - ) - } - > - - - } - isChecked={isSelected} - selected={listElements.length} - toggle={toggle} - toggleAll={toggleAll} - fetchMoreCategories={{ - hasMore: maybe( - () => - searchCategoriesOpts.data.search.pageInfo - .hasNextPage - ), - loading: searchCategoriesOpts.loading, - onFetchMore: loadMoreCategories - }} - fetchMoreCollections={{ - hasMore: maybe( - () => - searchCollectionsOpts.data.search.pageInfo - .hasNextPage - ), - loading: searchCollectionsOpts.loading, - onFetchMore: loadMoreCollections - }} - /> - navigate(productUrl(id), true)} - confirmButtonState={deleteTransitionState} - onConfirm={() => deleteProduct.mutate({ id })} - variant="delete" - title={intl.formatMessage({ - defaultMessage: "Delete Product", - description: "dialog header" - })} - > - - - - - navigate(productUrl(id), true)} - confirmButtonState={ - bulkProductVariantDeleteTransitionState - } - onConfirm={() => - bulkProductVariantDelete.mutate({ - ids: params.ids - }) - } - variant="delete" - title={intl.formatMessage({ - defaultMessage: "Delete Product Variants", - description: "dialog header" - })} - > - - params.ids.length), - displayQuantity: ( - - {maybe(() => params.ids.length)} - - ) - }} - /> - - - - data.product.basePrice.amount.toFixed(2) - )} - errors={maybe( - () => - bulkProductVariantCreate.opts.data - .productVariantBulkCreate.bulkProductErrors, - [] - )} - open={params.action === "create-variants"} - attributes={maybe( - () => data.product.productType.variantAttributes, - [] - )} - currencySymbol={maybe(() => shop.defaultCurrency)} - onClose={() => - navigate( - productUrl(id, { - ...params, - action: undefined - }) - ) - } - onSubmit={inputs => - bulkProductVariantCreate.mutate({ - id, - inputs - }) - } - /> - - ); + variants={maybe(() => product.variants)} + onBack={() => { + navigate(productListUrl()); }} - - ); - }} - - )} - - )} - + onDelete={() => openModal("remove")} + onProductShow={() => { + if (product) { + window.open(product.url); + } + }} + onImageReorder={handleImageReorder} + onSubmit={handleSubmit} + onVariantAdd={handleVariantAdd} + onVariantsAdd={handleVariantCreatorOpen} + onVariantShow={variantId => () => + navigate(productVariantEditUrl(product.id, variantId))} + onImageUpload={handleImageUpload} + onImageEdit={handleImageEdit} + onImageDelete={handleImageDelete} + toolbar={ + + navigate( + productUrl(id, { + action: "remove-variants", + ids: listElements + }) + ) + } + > + + + } + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + fetchMoreCategories={{ + hasMore: maybe( + () => + searchCategoriesOpts.data.search.pageInfo.hasNextPage + ), + loading: searchCategoriesOpts.loading, + onFetchMore: loadMoreCategories + }} + fetchMoreCollections={{ + hasMore: maybe( + () => + searchCollectionsOpts.data.search.pageInfo.hasNextPage + ), + loading: searchCollectionsOpts.loading, + onFetchMore: loadMoreCollections + }} + /> + navigate(productUrl(id), true)} + confirmButtonState={deleteTransitionState} + onConfirm={() => deleteProduct.mutate({ id })} + variant="delete" + title={intl.formatMessage({ + defaultMessage: "Delete Product", + description: "dialog header" + })} + > + + + + + navigate(productUrl(id), true)} + confirmButtonState={bulkProductVariantDeleteTransitionState} + onConfirm={() => + bulkProductVariantDelete.mutate({ + ids: params.ids + }) + } + variant="delete" + title={intl.formatMessage({ + defaultMessage: "Delete Product Variants", + description: "dialog header" + })} + > + + params.ids.length), + displayQuantity: ( + {maybe(() => params.ids.length)} + ) + }} + /> + + + + data.product.basePrice.amount.toFixed(2) + )} + errors={maybe( + () => + bulkProductVariantCreate.opts.data + .productVariantBulkCreate.bulkProductErrors, + [] + )} + open={params.action === "create-variants"} + attributes={maybe( + () => data.product.productType.variantAttributes, + [] + )} + currencySymbol={maybe(() => shop.defaultCurrency)} + onClose={() => + navigate( + productUrl(id, { + ...params, + action: undefined + }) + ) + } + onSubmit={inputs => + bulkProductVariantCreate.mutate({ + id, + inputs + }) + } + /> + + ); + }} + + ); + }} + ); }; export default ProductUpdate; diff --git a/src/containers/SearchCategories/types/SearchCategories.ts b/src/searches/types/SearchCategories.ts similarity index 100% rename from src/containers/SearchCategories/types/SearchCategories.ts rename to src/searches/types/SearchCategories.ts diff --git a/src/containers/SearchCollections/types/SearchCollections.ts b/src/searches/types/SearchCollections.ts similarity index 100% rename from src/containers/SearchCollections/types/SearchCollections.ts rename to src/searches/types/SearchCollections.ts diff --git a/src/containers/SearchCustomers/types/SearchCustomers.ts b/src/searches/types/SearchCustomers.ts similarity index 100% rename from src/containers/SearchCustomers/types/SearchCustomers.ts rename to src/searches/types/SearchCustomers.ts diff --git a/src/containers/SearchPages/types/SearchPages.ts b/src/searches/types/SearchPages.ts similarity index 100% rename from src/containers/SearchPages/types/SearchPages.ts rename to src/searches/types/SearchPages.ts diff --git a/src/containers/SearchProductTypes/types/SearchProductTypes.ts b/src/searches/types/SearchProductTypes.ts similarity index 84% rename from src/containers/SearchProductTypes/types/SearchProductTypes.ts rename to src/searches/types/SearchProductTypes.ts index 2aaf2fe5e..300ebc329 100644 --- a/src/containers/SearchProductTypes/types/SearchProductTypes.ts +++ b/src/searches/types/SearchProductTypes.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { AttributeInputTypeEnum } from "./../../../types/globalTypes"; +import { AttributeInputTypeEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL query operation: SearchProductTypes @@ -22,7 +22,9 @@ export interface SearchProductTypes_search_edges_node_productAttributes { slug: string | null; name: string | null; valueRequired: boolean; - values: (SearchProductTypes_search_edges_node_productAttributes_values | null)[] | null; + values: + | (SearchProductTypes_search_edges_node_productAttributes_values | null)[] + | null; } export interface SearchProductTypes_search_edges_node { @@ -30,7 +32,9 @@ export interface SearchProductTypes_search_edges_node { id: string; name: string; hasVariants: boolean; - productAttributes: (SearchProductTypes_search_edges_node_productAttributes | null)[] | null; + productAttributes: + | (SearchProductTypes_search_edges_node_productAttributes | null)[] + | null; } export interface SearchProductTypes_search_edges { diff --git a/src/containers/SearchProducts/types/SearchProducts.ts b/src/searches/types/SearchProducts.ts similarity index 100% rename from src/containers/SearchProducts/types/SearchProducts.ts rename to src/searches/types/SearchProducts.ts diff --git a/src/containers/SearchServiceAccount/types/SearchServiceAccount.ts b/src/searches/types/SearchServiceAccount.ts similarity index 100% rename from src/containers/SearchServiceAccount/types/SearchServiceAccount.ts rename to src/searches/types/SearchServiceAccount.ts diff --git a/src/containers/SearchCategories/index.tsx b/src/searches/useCategorySearch.ts similarity index 78% rename from src/containers/SearchCategories/index.tsx rename to src/searches/useCategorySearch.ts index cdaebb8b1..2958bbf77 100644 --- a/src/containers/SearchCategories/index.tsx +++ b/src/searches/useCategorySearch.ts @@ -1,7 +1,7 @@ import gql from "graphql-tag"; +import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; import { pageInfoFragment } from "@saleor/queries"; -import TopLevelSearch from "../TopLevelSearch"; import { SearchCategories, SearchCategoriesVariables @@ -24,6 +24,6 @@ export const searchCategories = gql` } `; -export default TopLevelSearch( +export default makeTopLevelSearch( searchCategories ); diff --git a/src/containers/SearchCollections/index.tsx b/src/searches/useCollectionSearch.ts similarity index 75% rename from src/containers/SearchCollections/index.tsx rename to src/searches/useCollectionSearch.ts index 2ceafcb46..b3ca07df4 100644 --- a/src/containers/SearchCollections/index.tsx +++ b/src/searches/useCollectionSearch.ts @@ -1,7 +1,7 @@ import gql from "graphql-tag"; +import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; import { pageInfoFragment } from "@saleor/queries"; -import TopLevelSearch from "../TopLevelSearch"; import { SearchCollections, SearchCollectionsVariables @@ -24,6 +24,7 @@ export const searchCollections = gql` } `; -export default TopLevelSearch( - searchCollections -); +export default makeTopLevelSearch< + SearchCollections, + SearchCollectionsVariables +>(searchCollections); diff --git a/src/containers/SearchCustomers/index.ts b/src/searches/useCustomerSearch.ts similarity index 78% rename from src/containers/SearchCustomers/index.ts rename to src/searches/useCustomerSearch.ts index 0164f7826..bd046f0ab 100644 --- a/src/containers/SearchCustomers/index.ts +++ b/src/searches/useCustomerSearch.ts @@ -1,7 +1,7 @@ import gql from "graphql-tag"; +import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; import { pageInfoFragment } from "@saleor/queries"; -import TopLevelSearch from "../TopLevelSearch"; import { SearchCustomers, SearchCustomersVariables @@ -24,6 +24,6 @@ export const searchCustomers = gql` } `; -export default TopLevelSearch( +export default makeTopLevelSearch( searchCustomers ); diff --git a/src/containers/SearchPages/index.tsx b/src/searches/usePageSearch.ts similarity index 76% rename from src/containers/SearchPages/index.tsx rename to src/searches/usePageSearch.ts index bd6ce287e..75eebbde0 100644 --- a/src/containers/SearchPages/index.tsx +++ b/src/searches/usePageSearch.ts @@ -1,7 +1,7 @@ import gql from "graphql-tag"; +import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; import { pageInfoFragment } from "@saleor/queries"; -import TopLevelSearch from "../TopLevelSearch"; import { SearchPages, SearchPagesVariables } from "./types/SearchPages"; export const searchPages = gql` @@ -21,4 +21,6 @@ export const searchPages = gql` } `; -export default TopLevelSearch(searchPages); +export default makeTopLevelSearch( + searchPages +); diff --git a/src/containers/SearchProducts/index.tsx b/src/searches/useProductSearch.ts similarity index 80% rename from src/containers/SearchProducts/index.tsx rename to src/searches/useProductSearch.ts index ce86cb09b..1e2ae7fcd 100644 --- a/src/containers/SearchProducts/index.tsx +++ b/src/searches/useProductSearch.ts @@ -1,7 +1,7 @@ import gql from "graphql-tag"; +import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; import { pageInfoFragment } from "@saleor/queries"; -import TopLevelSearch from "../TopLevelSearch"; import { SearchProducts, SearchProductsVariables @@ -27,6 +27,6 @@ export const searchProducts = gql` } `; -export default TopLevelSearch( +export default makeTopLevelSearch( searchProducts ); diff --git a/src/containers/SearchProductTypes/index.tsx b/src/searches/useProductTypeSearch.ts similarity index 82% rename from src/containers/SearchProductTypes/index.tsx rename to src/searches/useProductTypeSearch.ts index 6adf1ef5a..60517f670 100644 --- a/src/containers/SearchProductTypes/index.tsx +++ b/src/searches/useProductTypeSearch.ts @@ -1,7 +1,7 @@ import gql from "graphql-tag"; +import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; import { pageInfoFragment } from "@saleor/queries"; -import TopLevelSearch from "../TopLevelSearch"; import { SearchProductTypes, SearchProductTypesVariables @@ -41,6 +41,7 @@ export const searchProductTypes = gql` } `; -export default TopLevelSearch( - searchProductTypes -); +export default makeTopLevelSearch< + SearchProductTypes, + SearchProductTypesVariables +>(searchProductTypes); diff --git a/src/containers/SearchServiceAccount/index.tsx b/src/searches/useServiceAccountSearch.ts similarity index 86% rename from src/containers/SearchServiceAccount/index.tsx rename to src/searches/useServiceAccountSearch.ts index dd8cfa60f..3b3ed11d8 100644 --- a/src/containers/SearchServiceAccount/index.tsx +++ b/src/searches/useServiceAccountSearch.ts @@ -1,7 +1,7 @@ import gql from "graphql-tag"; +import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch"; import { pageInfoFragment } from "@saleor/queries"; -import TopLevelSearch from "../TopLevelSearch"; import { SearchServiceAccount, SearchServiceAccountVariables @@ -28,7 +28,7 @@ export const searchServiceAccount = gql` } `; -export default TopLevelSearch< +export default makeTopLevelSearch< SearchServiceAccount, SearchServiceAccountVariables >(searchServiceAccount); diff --git a/src/storybook/__snapshots__/Stories.test.ts.snap b/src/storybook/__snapshots__/Stories.test.ts.snap index 21cc3a558..9c231db02 100644 --- a/src/storybook/__snapshots__/Stories.test.ts.snap +++ b/src/storybook/__snapshots__/Stories.test.ts.snap @@ -125505,6 +125505,7 @@ exports[`Storyshots Views / Webhooks / Create webhook default 1`] = ` class="MuiInputBase-input-id MuiOutlinedInput-input-id" name="name" type="text" + value="" />