Add product type filter
This commit is contained in:
parent
0a58c3a5e1
commit
3bdd0dab6f
6 changed files with 154 additions and 26 deletions
|
@ -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
|
||||
}
|
||||
];
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -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(
|
||||
() =>
|
||||
categories.initial.map(category => ({
|
||||
label: category.name,
|
||||
value: category.id
|
||||
})),
|
||||
[]
|
||||
),
|
||||
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(
|
||||
() =>
|
||||
collections.initial.map(category => ({
|
||||
label: category.name,
|
||||
value: category.id
|
||||
})),
|
||||
[]
|
||||
),
|
||||
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,
|
||||
|
|
Loading…
Reference in a new issue