From b9dc338c6d596879538c03db4a91b4cda541f0e3 Mon Sep 17 00:00:00 2001 From: Sharyn Date: Mon, 9 Jul 2018 16:29:57 +0200 Subject: [PATCH] Updating search functionality setup --- components/browseArchives/index.js | 78 +++++++++++++++++++++++------ components/projectsList/index.js | 16 +++++- components/searchBar/index.js | 32 ++++++++---- components/searchBar/style.scss | 29 +++++++++-- components/searchResults/index.js | 40 +++++++++++++-- components/searchResults/style.scss | 33 ++++++++++++ components/topicsList/index.js | 16 +++++- package.json | 1 + 8 files changed, 210 insertions(+), 35 deletions(-) diff --git a/components/browseArchives/index.js b/components/browseArchives/index.js index 48d0f44..99594a6 100644 --- a/components/browseArchives/index.js +++ b/components/browseArchives/index.js @@ -1,4 +1,5 @@ import React from 'react'; +import _ from 'lodash'; import RelatedInterviewsList from '../interviews/relatedInterviewsList'; import InterviewsList from '../interviews/interviewsList'; import SingleInterview from '../interviews/singleInterview'; @@ -6,7 +7,7 @@ import TopicsList from '../topicsList'; import ProjectsList from '../projectsList'; import SearchBar from '../searchBar'; import SearchResults from '../searchResults'; -import Data from '../../data/archives/interviews'; +import InterviewsData from '../../data/archives/interviews'; import './style.scss'; class BrowseArchives extends React.Component { @@ -15,18 +16,24 @@ class BrowseArchives extends React.Component { this.state = { term: '', + searchResults: [], isSingleInterviewModalOpen: false, isInterviewsListModalOpen: false, activeSingleInterviewId: 1, isSearchActive: false, }; - this.onInputChange = this.onInputChange.bind(this); + this.onSearchInputChange = this.onSearchInputChange.bind(this); this.toggleSingleInterview = this.toggleSingleInterview.bind(this); this.toggleInterviewsListModal = this.toggleInterviewsListModal.bind(this); + this.setSearchTerm = this.setSearchTerm.bind(this); + this.clearSearchInput = this.clearSearchInput.bind(this); } - onInputChange(event) { + onSearchInputChange = (event) => { + const { term } = this.state; + const getSearchResults = _.debounce(() => { this.getSearchResults(term); }, 500); + this.setState({ term: event.target.value, isSearchActive: true, @@ -35,15 +42,42 @@ class BrowseArchives extends React.Component { if (event.target.value.length === 0) { this.setState({ isSearchActive: false }); } + + // Throttle search result frequency with debounce + getSearchResults(term); } - getSelectedInterview() { + getSearchResults = (term) => { + // Edit function to do actual search based on term and update searchResults with dynamic data + // eslint-disable-next-line + console.log(`Get search results array based on searching for: ${term}`); + + this.setState({ + searchResults: InterviewsData, + }); + } + + getSelectedInterview = () => { const { activeSingleInterviewId } = this.state; - const selectedInterview = Data.find(item => item.id === activeSingleInterviewId); + const selectedInterview = InterviewsData.find(item => item.id === activeSingleInterviewId); return selectedInterview; } - toggleInterviewsListModal() { + setSearchTerm = (event) => { + this.setState({ + term: event.target.innerText, + isSearchActive: true, + }); + } + + clearSearchInput = () => { + this.setState({ + isSearchActive: false, + term: '', + }); + } + + toggleInterviewsListModal = () => { const { isInterviewsListModalOpen } = this.state; this.setState({ @@ -52,13 +86,19 @@ class BrowseArchives extends React.Component { }); } - toggleSingleInterview(event) { + toggleSingleInterview = (event) => { const { isSingleInterviewModalOpen, isInterviewsListModalOpen } = this.state; + let clickedInterview = event.target; + while (clickedInterview.id === '') { + clickedInterview = clickedInterview.parentNode; + } + const clickedSingleInterviewId = clickedInterview.id; + this.setState({ isInterviewsListModalOpen: !isInterviewsListModalOpen, isSingleInterviewModalOpen: !isSingleInterviewModalOpen, - activeSingleInterviewId: Number(event.target.id), + activeSingleInterviewId: Number(clickedSingleInterviewId), }); } @@ -69,32 +109,42 @@ class BrowseArchives extends React.Component { isSearchActive, activeSingleInterviewId, term, + searchResults, } = this.state; return (
- +
{isSearchActive && () }
- {isSearchActive ? : + {isSearchActive ? ( + ) : ( - - + + ) } diff --git a/components/projectsList/index.js b/components/projectsList/index.js index ec57547..9428cf9 100644 --- a/components/projectsList/index.js +++ b/components/projectsList/index.js @@ -1,14 +1,26 @@ import React from 'react'; +import { PropTypes } from 'prop-types'; import Data from '../../data/archives/projects'; import './style.scss'; -export default () => ( +const ProjectsList = props => (

Projects

    { - Data.map(project =>
  • { project }
  • ) + Data.map(project => ( + // eslint-disable-next-line +
  • + { project } +
  • + )) }
); + +ProjectsList.propTypes = { + setSearchTerm: PropTypes.func.isRequired, +}; + +export default ProjectsList; diff --git a/components/searchBar/index.js b/components/searchBar/index.js index c76cae8..2f22815 100644 --- a/components/searchBar/index.js +++ b/components/searchBar/index.js @@ -6,20 +6,34 @@ const SearchBar = props => (

Browse Archives

- +
+ + { props.isSearchActive && ( + // eslint-disable-next-line + + Clear search + + ) + } +
); SearchBar.propTypes = { term: PropTypes.string.isRequired, - onInputChange: PropTypes.func.isRequired, -} + isSearchActive: PropTypes.bool.isRequired, + onSearchInputChange: PropTypes.func.isRequired, + clearSearchInput: PropTypes.func.isRequired, +}; export default SearchBar; diff --git a/components/searchBar/style.scss b/components/searchBar/style.scss index 951caf9..9329126 100644 --- a/components/searchBar/style.scss +++ b/components/searchBar/style.scss @@ -13,17 +13,40 @@ } } +.search-form { + position: relative; + bottom: calculateRem(-24); +} + .search-input { width: 100%; height: calculateRem(48); border: 5px solid #efefef; - padding: calculateRem(12); + padding: calculateRem(12) calculateRem(100) calculateRem(12) calculateRem(12); font-size: calculateRem(16); - position: relative; - bottom: calculateRem(-24); &:focus, &:active { outline: none; } } + +.search-clear-button { + position: absolute; + top: 10%; + right: calculateRem(4); + height: 80%; + border: 0; + padding: 0 calculateRem(16); + cursor: pointer; + font-size: calculateRem(14); + background-color: #fff; + display: flex; + align-items: center; + + &:focus, + &:active { + outline: none; + } +} + diff --git a/components/searchResults/index.js b/components/searchResults/index.js index 4f4e8fa..50e85e1 100644 --- a/components/searchResults/index.js +++ b/components/searchResults/index.js @@ -1,10 +1,40 @@ import React from 'react'; +import { PropTypes } from 'prop-types'; import './style.scss'; -const SearchResults = () => ( -
-

Search results go here

-
-); +const SearchResults = (props) => { + if (!props.data) { + return
Loading...
; + } + + return ( +
+
    + { props.data.map(interview => ( + // eslint-disable-next-line +
  • +

    { interview.name }

    +
    1) Question goes here
    +

    + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce hendrerit dolor quis + ante mollis fringilla. Lorem ipsum dolor sit amet, consectetur adipiscing + elit. +

    +
  • + )) + } +
+
+ ); +}; + +SearchResults.propTypes = { + data: PropTypes.arrayOf(PropTypes.shape({})).isRequired, + toggleSingleInterview: PropTypes.func.isRequired, +}; export default SearchResults; diff --git a/components/searchResults/style.scss b/components/searchResults/style.scss index ec52cca..fc3a431 100644 --- a/components/searchResults/style.scss +++ b/components/searchResults/style.scss @@ -2,4 +2,37 @@ .search-results { + li { + margin-bottom: calculateRem(32); + cursor: pointer; + + h3 { + font-size: calculateRem(18); + margin-bottom: calculateRem(8); + } + + h5 { + font-size: calculateRem(16); + margin-bottom: calculateRem(8); + } + + p { + font-size: calculateRem(14); + + span { + position: relative; + + &::before { + content: ''; + position: absolute; + top: -10%; + left: -15%; + height: 120%; + width: 130%; + background-color: #efefef; + z-index: -1; + } + } + } + } } diff --git a/components/topicsList/index.js b/components/topicsList/index.js index 298b322..be2d4bc 100644 --- a/components/topicsList/index.js +++ b/components/topicsList/index.js @@ -1,14 +1,26 @@ import React from 'react'; +import { PropTypes } from 'prop-types'; import Data from '../../data/archives/topics'; import './style.scss'; -export default () => ( +const TopicsList = props => (

Topics

    { - Data.map(topic =>
  • { topic }
  • ) + Data.map(topic => ( + // eslint-disable-next-line +
  • + { topic } +
  • + )) }
); + +TopicsList.propTypes = { + setSearchTerm: PropTypes.func.isRequired, +}; + +export default TopicsList; diff --git a/package.json b/package.json index 85a434b..8c15527 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "dependencies": { "@zeit/next-sass": "^0.2.0", "html-react-parser": "^0.4.5", + "lodash": "^4.17.10", "next": "^6.0.3", "node-sass": "^4.9.0", "prop-types": "^15.6.1",