Add product type filter

This commit is contained in:
dominik-zeglen 2020-01-16 14:49:06 +01:00
parent 0a58c3a5e1
commit 3bdd0dab6f
6 changed files with 154 additions and 26 deletions

View file

@ -15,6 +15,7 @@ export enum ProductFilterKeys {
collections = "collections",
status = "status",
price = "price",
productType = "productType",
stock = "stock"
}
@ -22,6 +23,7 @@ export interface ProductListFilterOpts {
categories: FilterOpts<string[]> & AutocompleteFilterOpts;
collections: FilterOpts<string[]> & AutocompleteFilterOpts;
price: FilterOpts<MinMax>;
productType: FilterOpts<string[]> & AutocompleteFilterOpts;
status: FilterOpts<ProductStatus>;
stockStatus: FilterOpts<StockAvailability>;
}
@ -147,6 +149,24 @@ export function createFilterStructure(
}
),
active: opts.collections.active
},
{
...createAutocompleteField(
ProductFilterKeys.productType,
intl.formatMessage(sectionNames.productTypes),
opts.productType.value,
opts.productType.displayValues,
true,
opts.productType.choices,
{
hasMore: opts.productType.hasMore,
initialSearch: "",
loading: opts.productType.loading,
onFetchMore: opts.productType.onFetchMore,
onSearchChange: opts.productType.onSearchChange
}
),
active: opts.productType.active
}
];
}

View file

@ -215,8 +215,12 @@ export const fragmentVariant = gql`
`;
const initialProductFilterDataQuery = gql`
query InitialProductFilterData($categories: [ID!], $collections: [ID!]) {
categories(first: 20, filter: { ids: $categories }) {
query InitialProductFilterData(
$categories: [ID!]
$collections: [ID!]
$productTypes: [ID!]
) {
categories(first: 100, filter: { ids: $categories }) {
edges {
node {
id
@ -224,7 +228,15 @@ const initialProductFilterDataQuery = gql`
}
}
}
collections(first: 20, filter: { ids: $collections }) {
collections(first: 100, filter: { ids: $collections }) {
edges {
node {
id
name
}
}
}
productTypes(first: 100, filter: { ids: $productTypes }) {
edges {
node {
id

View file

@ -38,12 +38,30 @@ export interface InitialProductFilterData_collections {
edges: InitialProductFilterData_collections_edges[];
}
export interface InitialProductFilterData_productTypes_edges_node {
__typename: "ProductType";
id: string;
name: string;
}
export interface InitialProductFilterData_productTypes_edges {
__typename: "ProductTypeCountableEdge";
node: InitialProductFilterData_productTypes_edges_node;
}
export interface InitialProductFilterData_productTypes {
__typename: "ProductTypeCountableConnection";
edges: InitialProductFilterData_productTypes_edges[];
}
export interface InitialProductFilterData {
categories: InitialProductFilterData_categories | null;
collections: InitialProductFilterData_collections | null;
productTypes: InitialProductFilterData_productTypes | null;
}
export interface InitialProductFilterDataVariables {
categories?: string[] | null;
collections?: string[] | null;
productTypes?: string[] | null;
}

View file

@ -33,7 +33,8 @@ export enum ProductListUrlFiltersEnum {
}
export enum ProductListUrlFiltersWithMultipleValues {
categories = "categories",
collections = "collections"
collections = "collections",
productTypes = "productTypes"
}
export type ProductListUrlFilters = Filters<ProductListUrlFiltersEnum> &
FiltersWithMultipleValues<ProductListUrlFiltersWithMultipleValues>;

View file

@ -32,6 +32,7 @@ import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandl
import createFilterHandlers from "@saleor/utils/handlers/filterHandlers";
import useCategorySearch from "@saleor/searches/useCategorySearch";
import useCollectionSearch from "@saleor/searches/useCollectionSearch";
import useProductTypeSearch from "@saleor/searches/useProductTypeSearch";
import ProductListPage from "../../components/ProductListPage";
import {
TypedProductBulkDeleteMutation,
@ -81,17 +82,34 @@ export const ProductList: React.FC<ProductListProps> = ({ params }) => {
);
const intl = useIntl();
const { data: initialFilterData } = useInitialProductFilterDataQuery({
skip: !(!!params.categories || !!params.collections),
skip: !(
!!params.categories ||
!!params.collections ||
!!params.productTypes
),
variables: {
categories: params.categories,
collections: params.collections
collections: params.collections,
productTypes: params.productTypes
}
});
const searchCategories = useCategorySearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
variables: {
...DEFAULT_INITIAL_SEARCH_DATA,
first: 5
}
});
const searchCollections = useCollectionSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
variables: {
...DEFAULT_INITIAL_SEARCH_DATA,
first: 5
}
});
const searchProductTypes = useProductTypeSearch({
variables: {
...DEFAULT_INITIAL_SEARCH_DATA,
first: 5
}
});
React.useEffect(
@ -191,6 +209,13 @@ export const ProductList: React.FC<ProductListProps> = ({ params }) => {
[]
),
search: searchCollections
},
{
initial: maybe(
() => initialFilterData.productTypes.edges.map(edge => edge.node),
[]
),
search: searchProductTypes
}
);

View file

@ -11,12 +11,17 @@ import {
} from "@saleor/searches/types/SearchCategories";
import {
InitialProductFilterData_categories_edges_node,
InitialProductFilterData_collections_edges_node
InitialProductFilterData_collections_edges_node,
InitialProductFilterData_productTypes_edges_node
} from "@saleor/products/types/InitialProductFilterData";
import {
SearchCollections,
SearchCollectionsVariables
} from "@saleor/searches/types/SearchCollections";
import {
SearchProductTypes,
SearchProductTypesVariables
} from "@saleor/searches/types/SearchProductTypes";
import { IFilterElement } from "../../../components/Filter";
import {
ProductFilterInput,
@ -29,7 +34,8 @@ import {
getMinMaxQueryParam,
getSingleEnumValueQueryParam,
dedupeFilter,
getMultipleValueQueryParam
getMultipleValueQueryParam,
getSingleValueQueryParam
} from "../../../utils/filters";
import {
ProductListUrlFilters,
@ -49,6 +55,10 @@ export function getFilterOpts(
collections: {
initial: InitialProductFilterData_collections_edges_node[];
search: UseSearchResult<SearchCollections, SearchCollectionsVariables>;
},
productTypes: {
initial: InitialProductFilterData_productTypes_edges_node[];
search: UseSearchResult<SearchProductTypes, SearchProductTypesVariables>;
}
): ProductListFilterOpts {
return {
@ -62,14 +72,16 @@ export function getFilterOpts(
})),
[]
),
displayValues: maybe(
displayValues: !!params.categories
? maybe(
() =>
categories.initial.map(category => ({
label: category.name,
value: category.id
})),
[]
),
)
: [],
hasMore: maybe(
() => categories.search.result.data.search.pageInfo.hasNextPage,
false
@ -90,14 +102,16 @@ export function getFilterOpts(
})),
[]
),
displayValues: maybe(
displayValues: !!params.collections
? maybe(
() =>
collections.initial.map(category => ({
label: category.name,
value: category.id
})),
[]
),
)
: undefined,
hasMore: maybe(
() => collections.search.result.data.search.pageInfo.hasNextPage,
false
@ -119,6 +133,36 @@ export function getFilterOpts(
min: maybe(() => params.priceFrom, "0")
}
},
productType: {
active: !!params.productTypes,
choices: maybe(
() =>
productTypes.search.result.data.search.edges.map(edge => ({
label: edge.node.name,
value: edge.node.id
})),
[]
),
displayValues: !!params.productTypes
? maybe(
() =>
productTypes.initial.map(productType => ({
label: productType.name,
value: productType.id
})),
[]
)
: [],
hasMore: maybe(
() => productTypes.search.result.data.search.pageInfo.hasNextPage,
false
),
initialSearch: "",
loading: productTypes.search.result.loading,
onFetchMore: productTypes.search.loadMore,
onSearchChange: productTypes.search.search,
value: maybe(() => dedupeFilter(params.productTypes), [])
},
status: {
active: maybe(() => params.status !== undefined, false),
value: maybe(() => findValueInEnum(params.status, ProductStatus))
@ -144,6 +188,8 @@ export function getFilterVariables(
gte: parseFloat(params.priceFrom),
lte: parseFloat(params.priceTo)
}),
productType:
params.productTypes !== undefined ? params.productTypes[0] : null,
search: params.query,
stockAvailability:
params.stockStatus !== undefined
@ -177,6 +223,12 @@ export function getFilterQueryParam(
ProductListUrlFiltersEnum.priceTo
);
case ProductFilterKeys.productType:
return getMultipleValueQueryParam(
filter,
ProductListUrlFiltersWithMultipleValues.productTypes
);
case ProductFilterKeys.status:
return getSingleEnumValueQueryParam(
filter,