diff --git a/src/actions/search.js b/src/actions/search.js
new file mode 100644
index 0000000..54c5f23
--- /dev/null
+++ b/src/actions/search.js
@@ -0,0 +1,22 @@
+import { TOGGLE_SEARCHBAR, SEARCH_PRODUCTS, IS_SEARCHING } from './types';
+import axios from 'axios';
+
+export const toggleSearchbar = () => (dispatch) => {
+ dispatch({ type: TOGGLE_SEARCHBAR });
+};
+
+export const searchProducts = (searchInput) => async (dispatch) => {
+ const { data } = await axios.get('http://localhost:5005/data/all');
+
+ const filteredData = data.filter((obj) =>
+ Object.keys(obj).some((key) =>
+ obj[key].toLowerCase().includes(searchInput.toLowerCase())
+ )
+ );
+
+ dispatch({ type: SEARCH_PRODUCTS, payload: filteredData });
+};
+
+export const searchStateToggle = () => (dispatch) => {
+ dispatch({ type: IS_SEARCHING });
+};
diff --git a/src/actions/types.js b/src/actions/types.js
index 4036d6b..921254d 100644
--- a/src/actions/types.js
+++ b/src/actions/types.js
@@ -10,3 +10,6 @@ export const AUTH_ERROR = 'AUTH_ERROR';
export const REGISTER_FAIL = 'REGISTER_FAIL';
export const LOGIN_SUCCESS = 'LOGIN_SUCCESS';
export const LOGIN_FAIL = 'LOGIN_FAIL';
+export const TOGGLE_SEARCHBAR = 'TOGGLE_SEARCHBAR';
+export const SEARCH_PRODUCTS = 'SEARCH_PRODUCTS';
+export const IS_SEARCHING = 'IS_SEARCHING';
diff --git a/src/components/App.js b/src/components/App.js
index 7c92aba..7ff68e5 100644
--- a/src/components/App.js
+++ b/src/components/App.js
@@ -62,6 +62,7 @@ class App extends React.Component {
render() {
// Grab counter from redux state
// const counter = useSelector(state => state.isLogged);
+ const { isSearching, searchResults } = this.props;
return (
{/* {this.counter}
@@ -70,9 +71,15 @@ class App extends React.Component {
- {this.state.data.map((info) => (
-
- ))}
+ {isSearching && searchResults.length === 0 &&
No matches!
}
+
+ {isSearching
+ ? searchResults.map((info) => (
+
+ ))
+ : this.state.data.map((info) => (
+
+ ))}
@@ -80,8 +87,13 @@ class App extends React.Component {
}
}
+const mapStateToProps = (state) => ({
+ isSearching: state.searchProducts.isSearching,
+ searchResults: state.searchProducts.searchResults,
+});
+
const mapDispatchToProps = {
loadUser,
};
-export default connect(null, mapDispatchToProps)(App);
+export default connect(mapStateToProps, mapDispatchToProps)(App);
diff --git a/src/components/NavbarUserUtils/navbarUserUtils.component.jsx b/src/components/NavbarUserUtils/navbarUserUtils.component.jsx
index 1becd8a..e8867c4 100644
--- a/src/components/NavbarUserUtils/navbarUserUtils.component.jsx
+++ b/src/components/NavbarUserUtils/navbarUserUtils.component.jsx
@@ -3,36 +3,70 @@ import React from 'react';
import './navbarUserUtils.styles.css';
//icons
-import searchIcon from '../../assets/search-icon.svg';
import cartIcon from '../../assets/cart.svg';
+//components
import LoginModal from '../LoginModal/LoginModal';
+import SearchBar from '../SearchBar/searchBar.component';
+
+//redux
import { connect } from 'react-redux';
import { toggleModal } from '../../actions/modalDisplay';
import { signOutUser } from '../../actions/isLogged';
-const NavbarUserUtils = ({ toggleModal, authorized, signOutUser }) => {
- return (
-
-
-

- {authorized === false ? (
-
- Log In
-
- ) : (
-
- Log out
-
- )}
-

-
- );
-};
+class NavbarUserUtils extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ searchInput: '',
+ };
+ }
+
+ onChange = (event) => {
+ const { name, value } = event.target;
+ this.setState({ [name]: value });
+ };
+
+ onSubmit = (event) => {
+ event.preventDefault();
+ const { searchInput } = this.state;
+ const { searchProducts, searchStateToggle } = this.props;
+ searchProducts(searchInput);
+ searchStateToggle();
+ };
+
+ initSearch = (event) => {
+ const { toggleSearchbar } = this.props;
+ this.onSubmit(event);
+ toggleSearchbar();
+ };
+
+ render() {
+ const { toggleModal, authorized, signOutUser } = this.props;
+
+ return (
+
+
+
+
+ {authorized === false ? (
+
+ Log In
+
+ ) : (
+
+ Log out
+
+ )}
+

+
+ );
+ }
+}
const mapStateToProps = (state) => {
return {
@@ -40,6 +74,7 @@ const mapStateToProps = (state) => {
};
};
-export default connect(mapStateToProps, { toggleModal, signOutUser })(
- NavbarUserUtils
-);
+export default connect(mapStateToProps, {
+ toggleModal,
+ signOutUser,
+})(NavbarUserUtils);
diff --git a/src/components/NavbarUserUtils/navbarUserUtils.styles.css b/src/components/NavbarUserUtils/navbarUserUtils.styles.css
index 747b07d..f9e7893 100644
--- a/src/components/NavbarUserUtils/navbarUserUtils.styles.css
+++ b/src/components/NavbarUserUtils/navbarUserUtils.styles.css
@@ -1,7 +1,7 @@
.navbar-user-utils-icon {
margin: 0;
display: inline;
- padding: 10px;
+ padding: 20px;
}
.navbar-user-utils-icon:hover {
@@ -11,5 +11,7 @@
.navbar-user-utils {
display: flex;
+ flex-direction: row;
justify-content: flex-end;
+ max-height: 65px;
}
diff --git a/src/components/SearchBar/searchBar.component.jsx b/src/components/SearchBar/searchBar.component.jsx
new file mode 100644
index 0000000..f870091
--- /dev/null
+++ b/src/components/SearchBar/searchBar.component.jsx
@@ -0,0 +1,97 @@
+import React, { Fragment } from 'react';
+
+import './searchBar.styles.css';
+
+//icons
+import searchIcon from '../../assets/search-icon.svg';
+
+import { connect } from 'react-redux';
+import {
+ toggleSearchbar,
+ searchProducts,
+ searchStateToggle,
+} from '../../actions/search';
+
+class SearchBar extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ searchInput: '',
+ };
+ }
+
+ onChange = (event) => {
+ const { name, value } = event.target;
+ this.setState({ [name]: value });
+ };
+
+ onSubmit = (event) => {
+ event.preventDefault();
+ const { searchInput } = this.state;
+ const { searchProducts, searchStateToggle } = this.props;
+ searchProducts(searchInput);
+ searchStateToggle();
+ };
+
+ initSearch = (event) => {
+ const { toggleSearchbar } = this.props;
+ this.onSubmit(event);
+ toggleSearchbar();
+ };
+
+ render() {
+ const { toggleSearchbar, displaySearchbar } = this.props;
+ const { searchInput } = this.state;
+ return (
+
+ {displaySearchbar ? (
+
+
+
+

+
+
+ ) : (
+

+ )}
+
+ );
+ }
+}
+
+const mapStateToProps = (state) => {
+ return {
+ displaySearchbar: state.searchProducts.displaySearchbar,
+ };
+};
+
+export default connect(mapStateToProps, {
+ toggleSearchbar,
+ searchProducts,
+ searchStateToggle,
+})(SearchBar);
diff --git a/src/components/SearchBar/searchBar.styles.css b/src/components/SearchBar/searchBar.styles.css
new file mode 100644
index 0000000..656eef8
--- /dev/null
+++ b/src/components/SearchBar/searchBar.styles.css
@@ -0,0 +1,65 @@
+.navbar-user-utils-icon {
+ margin: 0;
+ display: inline;
+ padding: 20px;
+}
+
+.navbar-user-utils {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-end;
+ max-height: 65px;
+}
+
+.searchForm {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-end;
+ max-width: 400px;
+}
+
+.searchSelector {
+ background-color: #b7b7b7;
+ border-radius: 12px 0px 0px 12px;
+ height: 43px;
+ width: auto;
+ font-size: 1rem;
+ text-align: center;
+ color: #707070;
+ border: 0px;
+ padding-right: 5px;
+
+ /* arrow */
+ -moz-appearance: none;
+ -webkit-appearance: none;
+ appearance: none;
+ background-image: linear-gradient(45deg, transparent 50%, gray 50%),
+ linear-gradient(135deg, gray 50%, transparent 50%),
+ linear-gradient(to right, #ccc, #ccc);
+ background-position: calc(100% - 20px) calc(1em + 2px),
+ calc(100% - 15px) calc(1em + 2px), calc(100% - 2.5em) 0.5em;
+ background-size: 5px 5px, 5px 5px, 0px 1.5em;
+ background-repeat: no-repeat;
+}
+
+.searchInput {
+ width: 300px;
+ height: 40px;
+ border: 0px;
+}
+
+.graySearch {
+ background-color: #b7b7b7;
+ max-height: 100%;
+ height: 43px;
+ border-radius: 0px 12px 12px 0px;
+ transform: translateY(10px);
+}
+
+.searchIcon {
+ padding: 10px 20px 20px 10px;
+}
+
+.submit {
+ display: none;
+}
diff --git a/src/reducers/index.js b/src/reducers/index.js
index f2777e5..a998f8c 100644
--- a/src/reducers/index.js
+++ b/src/reducers/index.js
@@ -1,12 +1,14 @@
import counterReducer from './Counter';
import loggedReducer from './isLogged';
import modalReducer from './modalDisplay';
+import productSearchReducer from './searchProducts';
import { combineReducers } from 'redux';
const allReducers = combineReducers({
counter: counterReducer,
isLogged: loggedReducer,
modalDisplay: modalReducer,
+ searchProducts: productSearchReducer,
});
export default allReducers;
diff --git a/src/reducers/searchProducts.js b/src/reducers/searchProducts.js
new file mode 100644
index 0000000..3f47076
--- /dev/null
+++ b/src/reducers/searchProducts.js
@@ -0,0 +1,28 @@
+import {
+ TOGGLE_SEARCHBAR,
+ SEARCH_PRODUCTS,
+ IS_SEARCHING,
+} from '../actions/types';
+
+const initialState = {
+ displaySearchbar: false,
+ searchResults: [],
+ isSearching: false,
+};
+
+const searchProducts = (state = initialState, action) => {
+ const { type, payload } = action;
+
+ switch (type) {
+ case TOGGLE_SEARCHBAR:
+ return { ...state, displaySearchbar: !state.displaySearchbar };
+ case SEARCH_PRODUCTS:
+ return { ...state, searchResults: [...payload] };
+ case IS_SEARCHING:
+ return { ...state, isSearching: true };
+ default:
+ return { ...state };
+ }
+};
+
+export default searchProducts;