Updating search functionality setup

This commit is contained in:
Sharyn 2018-07-09 16:29:57 +02:00
parent 1beebf9b9b
commit b9dc338c6d
8 changed files with 210 additions and 35 deletions

View File

@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import _ from 'lodash';
import RelatedInterviewsList from '../interviews/relatedInterviewsList'; import RelatedInterviewsList from '../interviews/relatedInterviewsList';
import InterviewsList from '../interviews/interviewsList'; import InterviewsList from '../interviews/interviewsList';
import SingleInterview from '../interviews/singleInterview'; import SingleInterview from '../interviews/singleInterview';
@ -6,7 +7,7 @@ import TopicsList from '../topicsList';
import ProjectsList from '../projectsList'; import ProjectsList from '../projectsList';
import SearchBar from '../searchBar'; import SearchBar from '../searchBar';
import SearchResults from '../searchResults'; import SearchResults from '../searchResults';
import Data from '../../data/archives/interviews'; import InterviewsData from '../../data/archives/interviews';
import './style.scss'; import './style.scss';
class BrowseArchives extends React.Component { class BrowseArchives extends React.Component {
@ -15,18 +16,24 @@ class BrowseArchives extends React.Component {
this.state = { this.state = {
term: '', term: '',
searchResults: [],
isSingleInterviewModalOpen: false, isSingleInterviewModalOpen: false,
isInterviewsListModalOpen: false, isInterviewsListModalOpen: false,
activeSingleInterviewId: 1, activeSingleInterviewId: 1,
isSearchActive: false, isSearchActive: false,
}; };
this.onInputChange = this.onInputChange.bind(this); this.onSearchInputChange = this.onSearchInputChange.bind(this);
this.toggleSingleInterview = this.toggleSingleInterview.bind(this); this.toggleSingleInterview = this.toggleSingleInterview.bind(this);
this.toggleInterviewsListModal = this.toggleInterviewsListModal.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({ this.setState({
term: event.target.value, term: event.target.value,
isSearchActive: true, isSearchActive: true,
@ -35,15 +42,42 @@ class BrowseArchives extends React.Component {
if (event.target.value.length === 0) { if (event.target.value.length === 0) {
this.setState({ isSearchActive: false }); 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 { activeSingleInterviewId } = this.state;
const selectedInterview = Data.find(item => item.id === activeSingleInterviewId); const selectedInterview = InterviewsData.find(item => item.id === activeSingleInterviewId);
return selectedInterview; return selectedInterview;
} }
toggleInterviewsListModal() { setSearchTerm = (event) => {
this.setState({
term: event.target.innerText,
isSearchActive: true,
});
}
clearSearchInput = () => {
this.setState({
isSearchActive: false,
term: '',
});
}
toggleInterviewsListModal = () => {
const { isInterviewsListModalOpen } = this.state; const { isInterviewsListModalOpen } = this.state;
this.setState({ this.setState({
@ -52,13 +86,19 @@ class BrowseArchives extends React.Component {
}); });
} }
toggleSingleInterview(event) { toggleSingleInterview = (event) => {
const { isSingleInterviewModalOpen, isInterviewsListModalOpen } = this.state; const { isSingleInterviewModalOpen, isInterviewsListModalOpen } = this.state;
let clickedInterview = event.target;
while (clickedInterview.id === '') {
clickedInterview = clickedInterview.parentNode;
}
const clickedSingleInterviewId = clickedInterview.id;
this.setState({ this.setState({
isInterviewsListModalOpen: !isInterviewsListModalOpen, isInterviewsListModalOpen: !isInterviewsListModalOpen,
isSingleInterviewModalOpen: !isSingleInterviewModalOpen, isSingleInterviewModalOpen: !isSingleInterviewModalOpen,
activeSingleInterviewId: Number(event.target.id), activeSingleInterviewId: Number(clickedSingleInterviewId),
}); });
} }
@ -69,32 +109,42 @@ class BrowseArchives extends React.Component {
isSearchActive, isSearchActive,
activeSingleInterviewId, activeSingleInterviewId,
term, term,
searchResults,
} = this.state; } = this.state;
return ( return (
<div className="browse-wrap"> <div className="browse-wrap">
<SearchBar onInputChange={this.onInputChange} term={term} /> <SearchBar
onSearchInputChange={this.onSearchInputChange}
clearSearchInput={this.clearSearchInput}
isSearchActive={isSearchActive}
term={term}
/>
<div className="browse-content-wrap container"> <div className="browse-content-wrap container">
<div className="browse-content-left"> <div className="browse-content-left">
{isSearchActive && {isSearchActive &&
(<RelatedInterviewsList (<RelatedInterviewsList
data={Data} data={InterviewsData}
toggleSingleInterview={this.toggleSingleInterview} toggleSingleInterview={this.toggleSingleInterview}
/>) />)
} }
</div> </div>
<div className="browse-content-right"> <div className="browse-content-right">
{isSearchActive ? <SearchResults /> : {isSearchActive ? (
<SearchResults
data={searchResults}
toggleSingleInterview={this.toggleSingleInterview}
/>) :
( (
<React.Fragment> <React.Fragment>
<InterviewsList <InterviewsList
data={Data} data={InterviewsData}
isInterviewsListModalOpen={isInterviewsListModalOpen} isInterviewsListModalOpen={isInterviewsListModalOpen}
toggleSingleInterview={this.toggleSingleInterview} toggleSingleInterview={this.toggleSingleInterview}
toggleInterviewsListModal={this.toggleInterviewsListModal} toggleInterviewsListModal={this.toggleInterviewsListModal}
/> />
<TopicsList /> <TopicsList setSearchTerm={this.setSearchTerm} />
<ProjectsList /> <ProjectsList setSearchTerm={this.setSearchTerm} />
</React.Fragment> </React.Fragment>
) )
} }

View File

@ -1,14 +1,26 @@
import React from 'react'; import React from 'react';
import { PropTypes } from 'prop-types';
import Data from '../../data/archives/projects'; import Data from '../../data/archives/projects';
import './style.scss'; import './style.scss';
export default () => ( const ProjectsList = props => (
<div className="projects-list"> <div className="projects-list">
<h4>Projects</h4> <h4>Projects</h4>
<ul> <ul>
{ {
Data.map(project => <li key={project}><span>{ project }</span></li>) Data.map(project => (
// eslint-disable-next-line
<li key={project} onClick={props.setSearchTerm}>
<span>{ project }</span>
</li>
))
} }
</ul> </ul>
</div> </div>
); );
ProjectsList.propTypes = {
setSearchTerm: PropTypes.func.isRequired,
};
export default ProjectsList;

View File

@ -6,20 +6,34 @@ const SearchBar = props => (
<div className="search-bar"> <div className="search-bar">
<div className="container"> <div className="container">
<h3>Browse Archives</h3> <h3>Browse Archives</h3>
<input <form className="search-form">
className="search-input" <input
type="search" className="search-input"
placeholder="Search archives" type="search"
value={props.term} placeholder="Search archives"
onChange={props.onInputChange} value={props.term}
/> onChange={props.onSearchInputChange}
/>
{ props.isSearchActive && (
// eslint-disable-next-line
<span
className="search-clear-button"
onClick={props.clearSearchInput}
>
Clear search
</span>
)
}
</form>
</div> </div>
</div> </div>
); );
SearchBar.propTypes = { SearchBar.propTypes = {
term: PropTypes.string.isRequired, term: PropTypes.string.isRequired,
onInputChange: PropTypes.func.isRequired, isSearchActive: PropTypes.bool.isRequired,
} onSearchInputChange: PropTypes.func.isRequired,
clearSearchInput: PropTypes.func.isRequired,
};
export default SearchBar; export default SearchBar;

View File

@ -13,17 +13,40 @@
} }
} }
.search-form {
position: relative;
bottom: calculateRem(-24);
}
.search-input { .search-input {
width: 100%; width: 100%;
height: calculateRem(48); height: calculateRem(48);
border: 5px solid #efefef; border: 5px solid #efefef;
padding: calculateRem(12); padding: calculateRem(12) calculateRem(100) calculateRem(12) calculateRem(12);
font-size: calculateRem(16); font-size: calculateRem(16);
position: relative;
bottom: calculateRem(-24);
&:focus, &:focus,
&:active { &:active {
outline: none; 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;
}
}

View File

@ -1,10 +1,40 @@
import React from 'react'; import React from 'react';
import { PropTypes } from 'prop-types';
import './style.scss'; import './style.scss';
const SearchResults = () => ( const SearchResults = (props) => {
<div className="search-results"> if (!props.data) {
<p>Search results go here</p> return <div>Loading...</div>;
</div> }
);
return (
<div className="search-results">
<ul>
{ props.data.map(interview => (
// eslint-disable-next-line
<li
id={interview.id}
key={interview.id}
onClick={props.toggleSingleInterview}
>
<h3>{ interview.name }</h3>
<h5>1) Question goes here</h5>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce hendrerit dolor quis
ante mollis fringilla. <span>Lorem</span> ipsum dolor sit amet, consectetur adipiscing
elit.
</p>
</li>
))
}
</ul>
</div>
);
};
SearchResults.propTypes = {
data: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
toggleSingleInterview: PropTypes.func.isRequired,
};
export default SearchResults; export default SearchResults;

View File

@ -2,4 +2,37 @@
.search-results { .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;
}
}
}
}
} }

View File

@ -1,14 +1,26 @@
import React from 'react'; import React from 'react';
import { PropTypes } from 'prop-types';
import Data from '../../data/archives/topics'; import Data from '../../data/archives/topics';
import './style.scss'; import './style.scss';
export default () => ( const TopicsList = props => (
<div className="topics-list"> <div className="topics-list">
<h4>Topics</h4> <h4>Topics</h4>
<ul> <ul>
{ {
Data.map(topic => <li key={topic}><span>{ topic }</span></li>) Data.map(topic => (
// eslint-disable-next-line
<li key={topic} onClick={props.setSearchTerm}>
<span>{ topic }</span>
</li>
))
} }
</ul> </ul>
</div> </div>
); );
TopicsList.propTypes = {
setSearchTerm: PropTypes.func.isRequired,
};
export default TopicsList;

View File

@ -38,6 +38,7 @@
"dependencies": { "dependencies": {
"@zeit/next-sass": "^0.2.0", "@zeit/next-sass": "^0.2.0",
"html-react-parser": "^0.4.5", "html-react-parser": "^0.4.5",
"lodash": "^4.17.10",
"next": "^6.0.3", "next": "^6.0.3",
"node-sass": "^4.9.0", "node-sass": "^4.9.0",
"prop-types": "^15.6.1", "prop-types": "^15.6.1",