From f7a4a1f83b9b1f7c2c4958663fd7830af599d5c6 Mon Sep 17 00:00:00 2001 From: Luis Sousa Date: Mon, 25 Oct 2021 10:49:31 -0300 Subject: [PATCH 1/5] add specification filter --- react/ProductSpecification.tsx | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/react/ProductSpecification.tsx b/react/ProductSpecification.tsx index e7737db..5d7e864 100644 --- a/react/ProductSpecification.tsx +++ b/react/ProductSpecification.tsx @@ -3,16 +3,35 @@ import { Specification } from 'vtex.product-context' import { useProductSpecificationGroup } from './ProductSpecificationGroup' -const ProductSpecificationGroup: FC = ({ children }) => { +interface ProductSpecificationGroupProps { + filter?: { + type: 'hide' | 'show' + specificationNames: string[] + } +} + + +const ProductSpecificationGroup: FC = ({ children, filter= {type: 'hide', specificationNames: []} }) => { const group = useProductSpecificationGroup() if (!group) { return null } + + let specifications = group.specifications; + + if (filter.specificationNames?.length > 0 && filter.type == 'show') { + specifications = specifications.filter((specification) => + filter.specificationNames.includes(specification.originalName) ) + } + if (filter.specificationNames?.length > 0 && filter.type == 'hide') { + specifications = specifications.filter((specification) => + !filter.specificationNames.includes(specification.originalName) ) + } return ( <> - {group.specifications.map((specification, index) => ( + {specifications.map((specification, index) => ( {children} From fa8f9eb5b86adaa9458adc906c16cc2d5967de3e Mon Sep 17 00:00:00 2001 From: Luis Sousa Date: Mon, 25 Oct 2021 10:58:01 -0300 Subject: [PATCH 2/5] add documentation --- docs/README.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index ec846a7..801c7b7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -150,7 +150,20 @@ You also can use other blocks to wrap the blocks provided by the Product Specifi | Prop name | Type | Description | Default value | | --------------------- | ---------- | --------------------- | ------------- | | `specificationGroups` | `[string]` | Array of specification group names to be hidden or shown (according to what is defined in the `type` property) by the `product-specification-group` block. | `undefined` | -| `type` | `enum` | Whether the specification group names passed to the `specificationGroups` prop should be displayed or hidden on the UI. Possible values are: `hide` (hides specification groups declared in the `specificationGroups` prop) or `show` (only shows the specification groups declared in the `specificationGroups` prop). | `undefined` | +| `type` | `enum` | Whether the specification group names passed to the `specificationGroups` prop should be displayed or hidden on the UI. Possible values are: `hide` (hides specification groups declared in the `specificationGroups` prop) or `show` (only shows the specification groups declared in the `specificationGroups` prop). | `hide` | + +### `product-specification` props + +| Prop name | Type | Description | Default value | +| --------- | -------- | ----------------------------------------------------------- | ------------- | +| `filter` | `object` | Filters the specifications that should be displayed by the block. | `undefined` | + +- **`filter` object:** + +| Prop name | Type | Description | Default value | +| --------------------- | ---------- | --------------------- | ------------- | +| `specificationNames` | `[string]` | Array of specification group names to be hidden or shown (according to what is defined in the `type` property) by the `product-specification-group` block. | `undefined` | +| `type` | `enum` | Whether the specification group names passed to the `specificationNames` prop should be displayed or hidden on the UI. Possible values are: `hide` (hides specification groups declared in the `specificationNames` prop) or `show` (only shows the specification groups declared in the `specificationNames` prop). | `hide` | #### `product-specification-text` props From e7333203eb290b4a5fcef7031a13b8394674cde6 Mon Sep 17 00:00:00 2001 From: IncognitaDev Date: Mon, 25 Oct 2021 19:40:30 -0300 Subject: [PATCH 3/5] Update react/ProductSpecification.tsx Co-authored-by: Igor Brasileiro --- react/ProductSpecification.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/react/ProductSpecification.tsx b/react/ProductSpecification.tsx index 5d7e864..ae63421 100644 --- a/react/ProductSpecification.tsx +++ b/react/ProductSpecification.tsx @@ -20,7 +20,7 @@ const ProductSpecificationGroup: FC = ({ childre let specifications = group.specifications; - if (filter.specificationNames?.length > 0 && filter.type == 'show') { + if (filter.specificationNames?.length > 0 && filter.type === 'show') { specifications = specifications.filter((specification) => filter.specificationNames.includes(specification.originalName) ) } From 0ac390c410feddb69e177bea90dcb53fbdd940b2 Mon Sep 17 00:00:00 2001 From: IncognitaDev Date: Mon, 25 Oct 2021 19:40:37 -0300 Subject: [PATCH 4/5] Update react/ProductSpecification.tsx Co-authored-by: Igor Brasileiro --- react/ProductSpecification.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/react/ProductSpecification.tsx b/react/ProductSpecification.tsx index ae63421..1475589 100644 --- a/react/ProductSpecification.tsx +++ b/react/ProductSpecification.tsx @@ -24,7 +24,7 @@ const ProductSpecificationGroup: FC = ({ childre specifications = specifications.filter((specification) => filter.specificationNames.includes(specification.originalName) ) } - if (filter.specificationNames?.length > 0 && filter.type == 'hide') { + if (filter.specificationNames?.length > 0 && filter.type === 'hide') { specifications = specifications.filter((specification) => !filter.specificationNames.includes(specification.originalName) ) } From 3d771dd8f2d72015f1fd1f6c2cd6b8969d37b372 Mon Sep 17 00:00:00 2001 From: Luis Sousa Date: Wed, 27 Oct 2021 01:16:24 -0300 Subject: [PATCH 5/5] WIP: fix mutability --- react/ProductSpecification.tsx | 20 +++++++++----------- react/package.json | 2 +- react/utils/filterSpecifications.ts | 18 ++++++++++++++++++ react/yarn.lock | 7 +------ 4 files changed, 29 insertions(+), 18 deletions(-) create mode 100644 react/utils/filterSpecifications.ts diff --git a/react/ProductSpecification.tsx b/react/ProductSpecification.tsx index 1475589..acfb9b1 100644 --- a/react/ProductSpecification.tsx +++ b/react/ProductSpecification.tsx @@ -2,6 +2,7 @@ import React, { FC, useContext } from 'react' import { Specification } from 'vtex.product-context' import { useProductSpecificationGroup } from './ProductSpecificationGroup' +import { filterSpecification, identityNoop } from './utils/filterSpecifications' interface ProductSpecificationGroupProps { filter?: { @@ -11,23 +12,20 @@ interface ProductSpecificationGroupProps { } -const ProductSpecificationGroup: FC = ({ children, filter= {type: 'hide', specificationNames: []} }) => { +const ProductSpecificationGroup: FC = ({ children, filter = {type: 'show', specificationNames: []} }) => { const group = useProductSpecificationGroup() if (!group) { return null } - let specifications = group.specifications; - - if (filter.specificationNames?.length > 0 && filter.type === 'show') { - specifications = specifications.filter((specification) => - filter.specificationNames.includes(specification.originalName) ) - } - if (filter.specificationNames?.length > 0 && filter.type === 'hide') { - specifications = specifications.filter((specification) => - !filter.specificationNames.includes(specification.originalName) ) - } + const specifications = filterSpecification({ + specifications: group.specifications, + filters: { + hide: filter.type === 'show' ? (specification: string) => filter.specificationNames.includes(specification) : identityNoop, + show: filter.type === 'hide' ? (specification: string) => !filter.specificationNames.includes(specification) : identityNoop + } + }) return ( <> diff --git a/react/package.json b/react/package.json index 9232447..b442086 100644 --- a/react/package.json +++ b/react/package.json @@ -20,7 +20,7 @@ "@vtex/tsconfig": "^0.4.4", "apollo-cache-inmemory": "^1.6.5", "graphql": "^14.6.0", - "typescript": "3.8.3", + "typescript": "3.9.7", "vtex.css-handles": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.css-handles@0.4.2/public/@types/vtex.css-handles", "vtex.render-runtime": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.111.1/public/@types/vtex.render-runtime" } diff --git a/react/utils/filterSpecifications.ts b/react/utils/filterSpecifications.ts new file mode 100644 index 0000000..ba9d624 --- /dev/null +++ b/react/utils/filterSpecifications.ts @@ -0,0 +1,18 @@ +import { Specification } from "vtex.product-context" + +type noopFunction = (x: T) => T +export const identityNoop = (x: T) => x // type the generics better, if possible. + +type specificationFilterFunction = (specificationName: string) => boolean + +interface UseFilterSpecification { + specifications: Array + filters: { + show: specificationFilterFunction | noopFunction , + hide: specificationFilterFunction | noopFunction, + } +} + +export const filterSpecification = ({ specifications, filters: { show, hide } }: UseFilterSpecification) =>{ + return specifications.filter(({ originalName }) => show(originalName) && hide(originalName)) +} \ No newline at end of file diff --git a/react/yarn.lock b/react/yarn.lock index 75293d6..72ac7b4 100644 --- a/react/yarn.lock +++ b/react/yarn.lock @@ -5282,12 +5282,7 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typescript@3.8.3: - version "3.8.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061" - integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w== - -typescript@^3.9.7: +typescript@3.9.7, typescript@^3.9.7: version "3.9.7" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa" integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==