Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Category Panel Component #141

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added

- Add `CategoryPanel` component.

## [3.12.11] - 2019-03-29
### Fixed
Expand Down
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ Now, you can change the behavior of the search result block that is in the store
"not-found",
"breadcrumb",
"order-by",
"total-products"
"total-products",
"category-panel"
],
"props": {
"querySchema": {
Expand All @@ -65,7 +66,8 @@ Now, you can change the behavior of the search result block that is in the store
"hiddenFilters": []
}
},
"pagination": "show-more"
"pagination": "show-more",
"quantityOfItemsPerRow": 4
}
},
```
Expand All @@ -81,7 +83,8 @@ When implementing this app as a block, various inner blocks may be available. Th
"breadcrumb",
"filter-navigator",
"total-products",
"order-by"
"order-by",
"category-panel"
],
"required": [
"gallery"
Expand Down Expand Up @@ -112,6 +115,7 @@ Through the Storefront, you can change the search-result behavior and interface.
| `querySchema` | `QuerySchema` | Query made when there's no context | N/A |
| `hiddenFacets` | `HiddenFacets` | Indicates which facets will be hidden | N/A |
| `pagination` | `Enum` | Pagination type (values: 'show-more' or 'infinite-scroll') | `infinity-scroll` |
| `quantityOfItemsPerRow` | `Enum` | Number of cards per row in category panel (values: 2 or 4) | 4 |

QuerySchema

Expand Down Expand Up @@ -178,6 +182,8 @@ Below, we describe the namespaces that are defined in the search-result.
| `filter` | Filter option container | [FilterOptionTemplate](/react/components/FilterOptionTemplate.js) |
| `resultGallery` | Gallery result container | [SearchResult](/react/components/SearchResult.js) |
| `border` | Order by container border | [SearchResult](/react/components/SearchResult.js) |
| `categoryPanelHeaderRow` | The main container of category panel header | [CategoryPanel](/react/CategoryPanel.js) |
| `categoryPanelItemRow` | The main container of category panel row | [CategoryPanel](/react/CategoryPanel.js) |
| `gallery` | The main container of gallery | [Gallery](/react/Gallery.js) |
| `filterPopupButton` | Filter pop-up button | [FilterSideBar](/react/components/FilterSideBar.js), [Popup](/react/components/Popup.js) |
| `accordionFilter` | Accordion filter container | [AccordionFilterContainer](/react/components/AccordionFilterContainer.js) |
Expand Down
2 changes: 2 additions & 0 deletions messages/context.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
"editor.search-result.hiddenFacets.specificationFilters.hideAll": "editor.search-result.hiddenFacets.specificationFilters.hideAll",
"editor.search-result.hiddenFacets.specificationFilters.hiddenFilter": "editor.search-result.hiddenFacets.specificationFilters.hiddenFilter",
"editor.search-result.hiddenFacets.specificationFilters.hiddenFilter.name": "editor.search-result.hiddenFacets.specificationFilters.hiddenFilter.name",
"editor.search-result.show-category-panel.title": "editor.search-result.show-category-panel.title",
"editor.search-result.quantity-of-items-per-row.title": "editor.search-result.quantity-of-items-per-row.title",
"layoutModeSwitcher.inline": "layoutModeSwitcher.inline",
"layoutModeSwitcher.small": "layoutModeSwitcher.small",
"layoutModeSwitcher.normal": "layoutModeSwitcher.normal",
Expand Down
2 changes: 2 additions & 0 deletions messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
"editor.search-result.hiddenFacets.specificationFilters.hideAll": "Hide all the Specifications filters",
"editor.search-result.hiddenFacets.specificationFilters.hiddenFilter": "Hidden Specification filter",
"editor.search-result.hiddenFacets.specificationFilters.hiddenFilter.name": "Hidden Specification filter name",
"editor.search-result.show-category-panel.title": "Show Category Panel",
"editor.search-result.quantity-of-items-per-row.title": "Number of Categories per Row",
"layoutModeSwitcher.inline": "Line",
"layoutModeSwitcher.small": "Small",
"layoutModeSwitcher.normal": "Normal",
Expand Down
2 changes: 2 additions & 0 deletions messages/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
"editor.search-result.hiddenFacets.specificationFilters.hideAll": "Ocultar todos los filtros de especificaciones",
"editor.search-result.hiddenFacets.specificationFilters.hiddenFilter": "Filtro de Especificaciones oculto",
"editor.search-result.hiddenFacets.specificationFilters.hiddenFilter.name": "Nombre del filtro de Especificaciones oculto",
"editor.search-result.show-category-panel.title": "Mostrar panel de categorías",
"editor.search-result.quantity-of-items-per-row.title": "Número de categorías por fila",
"layoutModeSwitcher.inline": "En línea",
"layoutModeSwitcher.small": "Pequeño",
"layoutModeSwitcher.normal": "Normal",
Expand Down
2 changes: 2 additions & 0 deletions messages/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
"editor.search-result.hiddenFacets.specificationFilters.hideAll": "Ocultar todos os filtros de Especificações",
"editor.search-result.hiddenFacets.specificationFilters.hiddenFilter": "Filtro de Especificacões oculto",
"editor.search-result.hiddenFacets.specificationFilters.hiddenFilter.name": "Nome do filtro de Especificações oculto",
"editor.search-result.show-category-panel.title": "Mostrar painel de categorias",
"editor.search-result.quantity-of-items-per-row.title": "Número de categorias por linha",
"layoutModeSwitcher.inline": "Na linha",
"layoutModeSwitcher.small": "Pequeno",
"layoutModeSwitcher.normal": "Normal",
Expand Down
100 changes: 100 additions & 0 deletions react/CategoryPanel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import React, { Component, Fragment } from 'react'
import classNames from 'classnames'
import PropTypes from 'prop-types'
import { Link, withRuntimeContext } from 'vtex.render-runtime'
sahanljc marked this conversation as resolved.
Show resolved Hide resolved
import { facetOptionShape } from './constants/propTypes'
import searchResult from './searchResult.css'
import CategoriesHighlights from 'vtex.store-components/CategoriesHighlights'

class CategoryPanel extends Component {
sahanljc marked this conversation as resolved.
Show resolved Hide resolved
static propTypes = {
sahanljc marked this conversation as resolved.
Show resolved Hide resolved
/** Category tree */
tree: PropTypes.arrayOf(facetOptionShape),
/** Number of category filters to be shown */
noOfCategories: PropTypes.number,
/** Number of categories per row */
quantityOfItemsPerRow: PropTypes.number,
}

static defaultProps = {
sahanljc marked this conversation as resolved.
Show resolved Hide resolved
tree: [],
noOfCategories: 1000,
quantityOfItemsPerRow: 4,
}

renderCategoryShelf = (
category,
noOfChildren,
quantityOfItemsPerRow,
mobile = false
) => {
const categoriesHighlighted = category.Children.slice(0, noOfChildren).map(
child => ({
id: child.Id,
name: child.Name,
to: child.Link,
})
)
const headerClasses = classNames(
searchResult.categoryPanelHeaderRow,
'flex flex-row flex-wrap items-stretch pa3 bn',
sahanljc marked this conversation as resolved.
Show resolved Hide resolved
{
mh4: !mobile,
sahanljc marked this conversation as resolved.
Show resolved Hide resolved
}
)
const itemClasses = classNames(
searchResult.categoryPanelItemRow,
'flex flex-row flex-wrap items-stretch pa3 bn',
{
mh4: !mobile,
sahanljc marked this conversation as resolved.
Show resolved Hide resolved
}
)
let i = 0
const items = []
for (i = 0; i < categoriesHighlighted.length; i += quantityOfItemsPerRow) {
items.push(categoriesHighlighted.slice(i, i + quantityOfItemsPerRow))
}
return (
<Fragment key={`parent-fragment-${category.Id}`}>
<div className={headerClasses}>
sahanljc marked this conversation as resolved.
Show resolved Hide resolved
<h3 className="t-heading-3">
<Link to={category.Link}>{category.Name}</Link>
</h3>
</div>
{items.length > 0 &&
items.map((item, index) => (
<div key={`category-row-${index}`} className={itemClasses}>
<CategoriesHighlights
categoriesHighlighted={item}
showCategoriesHighlighted={true}
quantityOfItems={quantityOfItemsPerRow}
/>
</div>
))}
{category.Children.map(child => {
if (child.Children && child.Children.length > 0) {
return this.renderCategoryShelf(child, noOfChildren, quantityOfItemsPerRow, mobile)
}
})}
</Fragment>
)
}

render() {
const { tree, noOfCategories, quantityOfItemsPerRow } = this.props

return (
<div>
{tree.map(category => {
return this.renderCategoryShelf(
category,
noOfCategories,
quantityOfItemsPerRow
)
})}
</div>
)
}
}

export default withRuntimeContext(CategoryPanel)
10 changes: 10 additions & 0 deletions react/__mocks__/categoriesTree.js
Original file line number Diff line number Diff line change
@@ -1,54 +1,64 @@
export default [
{
Id: 1,
Name: 'Eletrônicos',
Link: '/Eletronicos',
Quantity: 0,
Children: [
{
Id: 2,
Name: 'Smartphones',
Link: '/Eletronicos/Smartphones',
Quantity: 0,
},
{
Id: 3,
Name: 'Videogames',
Link: '/Eletronicos/Videogames',
Quantity: 0,
},
{
Id: 4,
Name: 'TVs',
Link: '/Eletronicos/TVs',
Quantity: 0,
},
],
},
{
Id: 5,
Name: 'Livros',
Link: '/Livros',
Quantity: 0,
Children: [
{
Id: 6,
Name: 'HQs e Mangas',
Link: '/Livros/HQs e Mangas',
Quantity: 0,
},
],
},
{
Id: 7,
Name: 'Roupas',
Link: '/Roupas',
Quantity: 0,
Children: [
{
Id: 8,
Name: 'Blusas',
Link: '/Roupas/Blusas',
Quantity: 0,
},
{
Id: 9,
Name: 'Calças',
Link: '/Roupas/Calcas',
Quantity: 0,
},
{
Id: 10,
Name: 'Moletom',
Link: '/Roupas/Moletom',
Quantity: 0,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React, { Component } from 'react'

class CategoriesHighlights extends Component {
render() {
return <div>CategoriesHighlights</div>
}
}

export default CategoriesHighlights
30 changes: 30 additions & 0 deletions react/__tests__/CategoryPanel.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* eslint-env jest */
import React from 'react'
import { render } from 'test-utils'

import categoriesTree from 'categoriesTree'

import CategoryPanel from '../CategoryPanel'

describe('<CategoryPanel />', () => {
const renderComponent = customProps => {
const props = {
tree: categoriesTree,
...customProps,
}

return render(<CategoryPanel {...props} />)
}

it('should match snapshot with 4 items per row', () => {
const { asFragment } = renderComponent()

expect(asFragment()).toMatchSnapshot()
})

it('should match snapshot with 2 items per row', () => {
const { asFragment } = renderComponent({ quantityOfItemsPerRow: 2 })

expect(asFragment()).toMatchSnapshot()
})
})
Loading