Updating search functionality setup
This commit is contained in:
parent
1beebf9b9b
commit
b9dc338c6d
|
@ -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 (
|
||||
<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-left">
|
||||
{isSearchActive &&
|
||||
(<RelatedInterviewsList
|
||||
data={Data}
|
||||
data={InterviewsData}
|
||||
toggleSingleInterview={this.toggleSingleInterview}
|
||||
/>)
|
||||
}
|
||||
</div>
|
||||
<div className="browse-content-right">
|
||||
{isSearchActive ? <SearchResults /> :
|
||||
{isSearchActive ? (
|
||||
<SearchResults
|
||||
data={searchResults}
|
||||
toggleSingleInterview={this.toggleSingleInterview}
|
||||
/>) :
|
||||
(
|
||||
<React.Fragment>
|
||||
<InterviewsList
|
||||
data={Data}
|
||||
data={InterviewsData}
|
||||
isInterviewsListModalOpen={isInterviewsListModalOpen}
|
||||
toggleSingleInterview={this.toggleSingleInterview}
|
||||
toggleInterviewsListModal={this.toggleInterviewsListModal}
|
||||
/>
|
||||
<TopicsList />
|
||||
<ProjectsList />
|
||||
<TopicsList setSearchTerm={this.setSearchTerm} />
|
||||
<ProjectsList setSearchTerm={this.setSearchTerm} />
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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 => (
|
||||
<div className="projects-list">
|
||||
<h4>Projects</h4>
|
||||
<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>
|
||||
</div>
|
||||
);
|
||||
|
||||
ProjectsList.propTypes = {
|
||||
setSearchTerm: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default ProjectsList;
|
||||
|
|
|
@ -6,20 +6,34 @@ const SearchBar = props => (
|
|||
<div className="search-bar">
|
||||
<div className="container">
|
||||
<h3>Browse Archives</h3>
|
||||
<input
|
||||
className="search-input"
|
||||
type="search"
|
||||
placeholder="Search archives"
|
||||
value={props.term}
|
||||
onChange={props.onInputChange}
|
||||
/>
|
||||
<form className="search-form">
|
||||
<input
|
||||
className="search-input"
|
||||
type="search"
|
||||
placeholder="Search archives"
|
||||
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>
|
||||
);
|
||||
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,40 @@
|
|||
import React from 'react';
|
||||
import { PropTypes } from 'prop-types';
|
||||
import './style.scss';
|
||||
|
||||
const SearchResults = () => (
|
||||
<div className="search-results">
|
||||
<p>Search results go here</p>
|
||||
</div>
|
||||
);
|
||||
const SearchResults = (props) => {
|
||||
if (!props.data) {
|
||||
return <div>Loading...</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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 => (
|
||||
<div className="topics-list">
|
||||
<h4>Topics</h4>
|
||||
<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>
|
||||
</div>
|
||||
);
|
||||
|
||||
TopicsList.propTypes = {
|
||||
setSearchTerm: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default TopicsList;
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue