From 1e703d8746d4496b03ddd275708660662791be9c Mon Sep 17 00:00:00 2001 From: Tom Raithel Date: Wed, 1 Mar 2017 23:31:25 +0100 Subject: [PATCH] Add search component to overview --- js/components/PageOverview.js | 66 +++++++++++++++++++++++++++-------- js/components/Search.js | 11 ++++++ styles/components/search.css | 35 +++++++++++++++++++ 3 files changed, 97 insertions(+), 15 deletions(-) create mode 100644 js/components/Search.js create mode 100644 styles/components/search.css diff --git a/js/components/PageOverview.js b/js/components/PageOverview.js index b2025c8..4941360 100644 --- a/js/components/PageOverview.js +++ b/js/components/PageOverview.js @@ -4,18 +4,25 @@ import HeadlineGroup from './HeadlineGroup'; import HeroHeadline from './HeroHeadline'; import Badge from './Badge'; import Link from './Link'; +import Search from './Search'; import Fadeable from './Fadeable'; import { groupByFirstLetter } from '../../common/model'; import { translate } from '../../common/config'; const rings = ['all', 'assess', 'trial', 'hold', 'adopt']; +const containsSearchTerm = (text = '', term = '') => { + // TODO search refinement + return text.trim().toLocaleLowerCase().indexOf(term.trim().toLocaleLowerCase()) !== -1; +} + class PageOverview extends React.Component { constructor(...args) { super(...args); this.state = { ring: rings[0], + search: '', }; } @@ -32,16 +39,38 @@ class PageOverview extends React.Component { return this.state.ring === ringName; } + itemMatchesRing = (item) => { + return this.state.ring === 'all' || item.ring === this.state.ring; + }; + + itemMatchesSearch = (item) => { + return this.state.search.trim() === '' || + containsSearchTerm(item.title, this.state.search) || + containsSearchTerm(item.body, this.state.search) || + containsSearchTerm(item.info, this.state.search); + }; + + isItemVisible = (item) => { + return this.itemMatchesRing(item) && this.itemMatchesSearch(item); + }; + getFilteredAndGroupedItems() { const groups = groupByFirstLetter(this.props.items); const groupsFiltered = groups.map(group => ({ ...group, - items: group.items.filter(item => this.state.ring === 'all' || item.ring === this.state.ring), + items: group.items.filter(this.isItemVisible), })); const nonEmptyGroups = groupsFiltered.filter(group => group.items.length > 0); return nonEmptyGroups; } + handleSearchTermChange = (value) => { + this.setState({ + ...this.state, + search: value, + }); + }; + render() { const groups = this.getFilteredAndGroupedItems(); @@ -51,20 +80,27 @@ class PageOverview extends React.Component { Technologies Overview
-
- { - rings.map(ringName => ( -
- - {ringName} - -
- )) - } +
+
+ +
+
+
+ { + rings.map(ringName => ( +
+ + {ringName} + +
+ )) + } +
+
diff --git a/js/components/Search.js b/js/components/Search.js new file mode 100644 index 0000000..0e5f116 --- /dev/null +++ b/js/components/Search.js @@ -0,0 +1,11 @@ +import React from 'react'; +import classNames from 'classnames'; + +export default function Search({ value, onChange }) { + return ( +
+ { onChange(e.target.value); }} className="search__field" placeholder="Search" /> + +
+ ); +} diff --git a/styles/components/search.css b/styles/components/search.css new file mode 100644 index 0000000..733c9d9 --- /dev/null +++ b/styles/components/search.css @@ -0,0 +1,35 @@ +.search { + box-sizing: border-box; + width: 600px; + height: 50px; + position: relative; + + &__field { + height: 100%; + width: 100%; + padding: 10px 20px 10px 50px; + background: #3A444A; + display: block; + border: none; + color: var(--color-white); + font-size: 16px; + line-height: 1; + font-family: 'DIN'; + font-weight: normal; + + &::placeholder { + color: var(--color-gray-normal); + } + + &:focus { + outline: none; + background: #2F393F; + } + } + + &__icon { + position: absolute; + top: 14px; + left: 14px; + } +}