Commit be308275 authored by Andrew Hrdy's avatar Andrew Hrdy

Merge branch 'searchbar-to-navbar'

parents dd9ca46c 886e2c9a
......@@ -35,7 +35,7 @@
"build-css": "node-sass-chokidar src/styles/ -o src/styles/build",
"watch-css": "node-sass-chokidar src/styles/ -o src/styles/build --watch --recursive",
"start-js": "react-scripts start",
"start": "npm-run-all -p watch-css start-js",
"start": "npm-run-all -p build-css watch-css start-js",
"build-js": "react-scripts build",
"build": "npm-run-all build-css build-js",
"test": "react-scripts test --env=jsdom",
......
......@@ -5,6 +5,7 @@ export const SET_FACILITIES = 'SET_FACILITIES';
export const GET_FACILITIES = 'GET_FACILITIES';
export const SET_SELECTED_FACILITY = 'SET_SELECTED_FACILITY';
export const SET_SEARCH_TERM = 'SET_SEARCH_TERM';
export const SET_CAMPUS_REGION = 'SET_CAMPUS_REGION';
export const ADD_FAVORITE_FACILITY = 'ADD_FAVORITE_FACILITY';
export const REMOVE_FAVORITE_FACILITY = 'REMOVE_FAVORITE_FACILITY';
export const SET_ALL_FAVORITES = 'SET_ALL_FAVORITES';
......
......@@ -2,6 +2,7 @@ import {
ADD_FAVORITE_FACILITY,
REMOVE_FAVORITE_FACILITY,
SET_SEARCH_TERM,
SET_CAMPUS_REGION,
TOGGLE_SIDEBAR,
TOGGLE_SIDEBAR_MAP,
SET_ALL_FAVORITES, SET_SELECTED_FACILITY, SET_SIDEBAR
......@@ -13,9 +14,7 @@ export const toggleSidebar = () => ({
export const setSidebar = (setOpen) => ({
type: SET_SIDEBAR,
setOpen,
setOpen
});
export const toggleSidebarMap = () => ({
......@@ -32,6 +31,11 @@ export const setSearchTerm = (term) => ({
term,
});
export const setCampusRegion = (campusRegion) => ({
type: SET_CAMPUS_REGION,
campusRegion
});
export const addFavoriteFacility = slug => ({
type: ADD_FAVORITE_FACILITY,
slug
......@@ -45,6 +49,6 @@ export const removeFavoriteFacility = slug => ({
export const setAllFavorites = (favorites) => ({
type: SET_ALL_FAVORITES,
favorites,
})
});
......@@ -5,6 +5,7 @@ import Typography from 'material-ui/Typography';
import Button from 'material-ui/Button';
import IconButton from 'material-ui/IconButton';
import MenuIcon from 'material-ui-icons/Menu';
import SearchBar from '../containers/SearchBar';
import classNames from 'classnames'
class CustomAppBar extends React.Component {
......@@ -12,7 +13,8 @@ class CustomAppBar extends React.Component {
constructor(props) {
super();
this.state = {
isAppBarExpanded: false
isAppBarExpanded: false,
isSearchExpanded: false,
};
this.toggleExpand = this.toggleExpand.bind(this);
......@@ -26,12 +28,15 @@ class CustomAppBar extends React.Component {
render() {
return (<div>
<AppBar position="absolute" className={'app-bar'}>
<AppBar position="absolute"
className={classNames('app-bar', this.state.isSearchExpanded && 'app-bar-search-expanded')}>
<Toolbar className={'app-bar-tool-bar'}>
<img src={require('../images/SRCT_square.svg')} className={'app-bar-logo'}/>
<Typography type="title" className={classNames('app-bar-title', 'app-bar-text-color')}>
What's Open
</Typography>
<SearchBar onSearchExpand={() => this.setState({isSearchExpanded: true})}
onSearchCollapse={() => this.setState({isSearchExpanded: false})}/>
<IconButton onClick={this.toggleExpand} aria-label="Menu"
className={classNames('app-bar-menu-button', 'app-bar-text-color')}>
<MenuIcon/>
......
import React from 'react'
import {withStyles} from 'material-ui/styles';
import FacilityCard from '../containers/FacilityCard'
import Grid from 'material-ui/Grid';
const CardContainer = ({searchTerm, facilities}) => {
const CardContainer = ({searchTerm, campusRegion, facilities}) => {
const filterCards = (facility) => {
const lsearchTerm = searchTerm.toLowerCase()
const name = facility.facility_name.toLowerCase()
const tags = facility.facility_product_tags
tags.forEach((tag) =>{
return tag.toLowerCase()
})
let hasTag = true;
let index = tags.findIndex((tag) =>{
return tag.includes(lsearchTerm)
})
if(index === -1){
hasTag = false
if (facility.facility_location.campus_region.toLowerCase() !== campusRegion.toLowerCase()) {
return false;
}
return name.includes(lsearchTerm) || hasTag
}
// console.log(facilities)
const lSearchTerm = searchTerm.toLowerCase();
const facilityName = facility.facility_name.toLowerCase();
const facilityLocation = facility.facility_location.building.toLowerCase();
const facilityCategory = facility.facility_category.name.toLowerCase();
const facilityTags = facility.facility_product_tags;
facilityTags.forEach((tag) => {
return tag.toLowerCase()
});
let index = facilityTags.findIndex((tag) => {
return tag.includes(lSearchTerm)
});
const hasTag = index !== -1;
return facilityName.includes(lSearchTerm) || facilityLocation.includes(lSearchTerm) ||
facilityCategory.includes(lSearchTerm) || hasTag;
};
return (
<Grid container className={'card-container-root'} spacing={24} justify={'center'} alignItems={'flex-end'}>
{facilities.filter(filterCards).map(item =>{
return(
{facilities.filter(filterCards).map(item => {
return (
<Grid key={item.slug} item>
<FacilityCard facility={item} facilities={facilities}/>
</Grid>
......@@ -32,6 +40,6 @@ const CardContainer = ({searchTerm, facilities}) => {
})}
</Grid>
)
}
};
export default CardContainer;
\ No newline at end of file
......@@ -5,11 +5,9 @@ import AppBar from '../components/AppBar';
import Sidebar from '../components/Sidebar';
import {getFacilities, setFacilities,sortByFavorites} from '../actions/api';
import CardContainer from '../components/CardContainer';
import SearchBar from './SearchBar';
import KeyboardArrowLeft from 'material-ui-icons/KeyboardArrowLeft';
import KeyboardArrowRight from 'material-ui-icons/KeyboardArrowRight';
class Layout extends React.Component {
constructor(props) {
super(props);
......@@ -39,16 +37,15 @@ class Layout extends React.Component {
};
render() {
const {isSidebarOpen, isSidebarMapOpen, toggleSidebar, toggleSidebarMap, getFacilities, selectedFacility,facilities,searchTerm,sortByFavorites,favorites} = this.props;
const {isSidebarOpen, isSidebarMapOpen, toggleSidebar, toggleSidebarMap, getFacilities, selectedFacility, facilities, searchTerm, campusRegion, sortByFavorites, favorites} = this.props;
return (
<div className={'layout-root'}>
<AppBar isOpen={false} handleMenuClick={() => {
}}/>
<div className={'layout-container'}>
<div className={'layout-main-content'}>
<SearchBar suggestions={{}}/>
<div className={'layout-card-container'}>
<CardContainer styles={'layout-card-container'} searchTerm={searchTerm}
<CardContainer styles={'layout-card-container'} searchTerm={searchTerm} campusRegion={campusRegion}
facilities={facilities} />
</div>
</div>
......@@ -66,6 +63,7 @@ function mapStateToProps(state) {
facilities: state.facilities.data,
favorites: state.ui.favorites,
searchTerm: state.ui.search.term,
campusRegion: state.ui.search.campusRegion,
isLoading: state.facilities.isLoading,
selectedFacility: state.ui.selectedFacility,
isSidebarOpen: state.ui.sidebar.isOpen,
......
import React from 'react';
import PropTypes from 'prop-types';
import Paper from 'material-ui/Paper';
import {withStyles} from 'material-ui/styles';
import {compose} from 'redux';
import {connect} from 'react-redux';
import {setSearchTerm} from '../actions/ui';
import Search from 'material-ui-icons/Search'
import {setSearchTerm, setCampusRegion} from '../actions/ui';
import SearchIcon from 'material-ui-icons/Search';
import CloseIcon from 'material-ui-icons/Close';
import ArrowBackIcon from 'material-ui-icons/ArrowBack';
import IconButton from 'material-ui/IconButton';
import Input from 'material-ui/Input';
import Paper from 'material-ui/Paper';
import {MenuItem} from 'material-ui/Menu';
import Select from 'material-ui/Select';
import {FormControl} from 'material-ui/Form';
import classNames from 'classnames';
class SearchBar extends React.Component {
constructor(props) {
super(props);
this.state = {
isFocused: false,
isMobileOpen: false,
value: '',
campus: 'fairfax'
};
}
handleChange = (e) => {
this.setState({
value: e.target.value,
});
this.props.setSearchTerm(e.target.value)
this.props.setSearchTerm(e.target.value);
};
handleRegionChange = (e) => {
this.setState({
campus: e.target.value
});
this.props.setCampusRegion(e.target.value);
};
handleFocus = () => {
this.setState({
isFocused: true
});
};
handleBlur = () => {
this.setState({
isFocused: false
});
};
handleMobileExpand = () => {
this.setState({
isMobileOpen: true
});
this.props.onSearchExpand();
this.inputElement.focus();
};
handleMobileCollapse = () => {
this.setState({
isMobileOpen: false
});
this.props.onSearchCollapse();
};
clear = () => {
this.setState({
value: ''
});
this.props.setSearchTerm('');
};
render() {
return (
<Paper className={'search-bar-paper-background'} elevation={3}>
<Paper className={classNames('search-bar-paper-background', this.state.isFocused && 'search-bar-focus',
this.state.value && 'search-bar-has-value', this.state.isMobileOpen && 'search-bar-mobile-open')}>
<IconButton onClick={this.handleMobileExpand} disableRipple className={'search-bar-search-btn'}>
<SearchIcon className={'search-bar-search-icon'}/>
</IconButton>
<IconButton onClick={this.handleMobileCollapse} disableRipple className={'search-bar-back-btn'}>
<ArrowBackIcon className={'search-bar-back-icon'}/>
</IconButton>
<Input
placeholder="names, locations, etc"
placeholder="Name, Location, etc."
disableUnderline
fullWidth
autoFocus
className={'search-bar-no-suggest-input'}
className={'search-bar-input'}
onChange={this.handleChange}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
inputProps={{
'aria-label': 'Description',
'aria-label': 'Search Bar',
}}
inputRef={el => this.inputElement = el}
value={this.state.value}
/>
<div className={'search-bar-right-search-container'}>
<Search className={'search-bar-search-icon'}/>
</div>
<IconButton onClick={this.clear} disableRipple className={'search-bar-close-btn'}>
<CloseIcon/>
</IconButton>
<FormControl className={'search-bar-campus-control'}>
<Select
value={this.state.campus}
onChange={this.handleRegionChange}>
<MenuItem value={'fairfax'}>Fairfax</MenuItem>
<MenuItem value={'arlington'}>Arlington</MenuItem>
<MenuItem value={'prince william county science and technology'}>Prince William</MenuItem>
<MenuItem value={'mason korea'}>Korea</MenuItem>
</Select>
</FormControl>
</Paper>
);
}
}
export default connect(null, {setSearchTerm})(SearchBar);
\ No newline at end of file
SearchBar.propTypes = {
onSearchExpand: PropTypes.func,
onSearchCollapse: PropTypes.func
};
export default connect(null, {setSearchTerm, setCampusRegion})(SearchBar);
\ No newline at end of file
html{
width:100%;
height: 100%;
overflow:hidden;
}
body {
width: 100%;
......
import {
TOGGLE_SIDEBAR, SET_SELECTED_FACILITY, SET_SEARCH_TERM, SET_FILTERED_LIST,
ADD_FAVORITE_FACILITY, REMOVE_FAVORITE_FACILITY, SET_ALL_FAVORITES, TOGGLE_SIDEBAR_MAP, SET_SIDEBAR,
TOGGLE_SIDEBAR, SET_SELECTED_FACILITY, SET_SEARCH_TERM, SET_CAMPUS_REGION,
ADD_FAVORITE_FACILITY, REMOVE_FAVORITE_FACILITY, SET_ALL_FAVORITES, TOGGLE_SIDEBAR_MAP, SET_SIDEBAR,
} from '../actions/action-types'
const selectedFacility = (state = {}, action) => {
......@@ -37,8 +37,9 @@ const sidebar = (state=sidebarDefault,action) => {
};
const searchbarState = {
term:'',
filteredList:[],
term: '',
campusRegion: 'fairfax',
filteredList: [],
};
const filterList = (state) =>{
......@@ -50,6 +51,10 @@ const search = (state=searchbarState,facilities=[],action) =>{
return Object.assign({},state,{
term:action.term,
});
case SET_CAMPUS_REGION:
return Object.assign({}, state, {
campusRegion: action.campusRegion
});
default:
return state;
}
......
@import '../variables';
.app-bar {
background-color: white !important;
box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.2) !important;
......@@ -21,7 +23,7 @@
color: #354052;
}
@media screen and (max-width: 600px) {
@media screen and (max-width: map-get($breakpoints, lg) - 1px) {
.app-bar-link-button {
display: block !important;
padding: 0 !important;
......@@ -46,4 +48,10 @@
flex-basis: 100%;
transition: ease-in-out 2s;
}
.app-bar-search-expanded {
.app-bar-logo, .app-bar-title, .app-bar-menu-button, .app-bar-link-container {
display: none !important;
}
}
}
\ No newline at end of file
.card-container-root {
margin: 0;
padding-top:32px;
width: 100%;
display: flex;
flex-wrap: wrap;
......
......@@ -34,6 +34,11 @@
@include transition(300ms cubic-bezier(0.820, 0.165, 0.340, 0.930));
}
.sidebar-root::-webkit-scrollbar {
display: none;
}
.card-container-offset-open{
flex: 1 0 400px;
......@@ -78,12 +83,15 @@
width: 100%;
}
.sidebar-scroll{
height:calc(100% - 220px - 116px - 32px);
overflow-y: auto;
height:calc(100% - 220px - 116px - 32px) !important;
overflow-y: auto;
}
@media screen and (max-width: map-get($breakpoints, lg) - 1px) {
.sidebar-root {
display: none !important;
}
.card-container-offset{
display: none !important;
}
}
\ No newline at end of file
......@@ -21,7 +21,7 @@
flex: 1 1 100%;
height: 100%;
width: 100%;
padding-top: 16px;
// padding-top: 32px;
}
.layout-sidebar-toggle-container {
......@@ -52,7 +52,7 @@
}
.layout-card-container {
height: calc(100% - 70px);
height: 100%;
overflow-y: auto;
overflow-x: hidden;
}
......@@ -61,4 +61,5 @@
.layout-sidebar-toggle-container {
display: none;
}
}
\ No newline at end of file
@import '../_variables.scss';
.search-bar-paper-background {
height: 54px;
max-width: 600px;
width: 90%;
height: 44px;
width: 400px;
display: flex;
margin: 0 auto 16px auto;
border-radius: 4px !important;
background-color: rgba(0, 0, 0, 0.04) !important;
box-shadow: none !important;
}
.search-bar-right-search-container {
height: 100%;
display: flex;
align-items: center;
margin: 0 8px;
.search-bar-search-btn {
width: 44px !important;
height: 44px !important;
cursor: default !important;
}
.search-bar-back-btn {
display: none !important;
}
.search-bar-search-icon {
.search-bar-search-icon, .search-bar-arrow-icon {
display: block;
color: rgba(0,0,0,0.54);
}
.search-bar-no-suggest-input {
.search-bar-arrow-icon {
display: none !important;
}
.search-bar-input {
display: flex !important;
align-items: center !important;
margin-left: 8px !important;
width: 100%
}
.search-bar-close-btn {
width: 44px !important;
height: 44px !important;
display: none !important;
}
.search-bar-campus-control {
width: 150px;
justify-content: center;
}
.search-bar-has-value {
.search-bar-close-btn {
display: inline-flex !important;
}
}
@media screen and (min-width: map-get($breakpoints, lg)) {
.search-bar-paper-background {
&.search-bar-focus {
background-color: rgba(255, 255, 255, 1) !important;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.24) !important;
border: 1px solid rgba(0,0,0,0.15);
}
}
.search-bar-input {
transition: ease-in-out width 250ms;
}
}
@media screen and (max-width: map-get($breakpoints, lg) - 1px) {
.search-bar-paper-background {
background-color: rgba(255, 255, 255, 1) !important;
width: auto !important;
&.search-bar-mobile-open {
height: 100% !important;
width: 100% !important;
}
}
.search-bar-input {
width: 0 !important;
}
.search-bar-campus-control {
display: none !important;
}
.search-bar-mobile-open {
.search-bar-input {
width: 100% !important;
}
.search-bar-campus-control {
display: inline-flex !important;
}
.search-bar-search-btn {
display: none !important;
}
.search-bar-back-btn {
display: inline-flex !important;
width: 56px !important;
height: 56px !important;
}
.search-bar-close-btn {
width: 56px !important;
height: 56px !important;
}
}
}
\ No newline at end of file
......@@ -16,3 +16,4 @@
@import './containers/facilityCard';
@import './containers/layout';
@import './containers/searchBar';
......@@ -101,6 +101,10 @@ acorn@^5.0.0, acorn@^5.1.0, acorn@^5.2.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.2.1.tgz#317ac7821826c22c702d66189ab8359675f135d7"
add-px-to-style@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/add-px-to-style/-/add-px-to-style-1.0.0.tgz#d0c135441fa8014a8137904531096f67f28f263a"
address@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/address/-/address-1.0.2.tgz#480081e82b587ba319459fef512f516fe03d58af"
......@@ -2157,6 +2161,14 @@ dom-converter@~0.1:
dependencies:
utila "~0.3"
dom-css@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/dom-css/-/dom-css-2.1.0.tgz#fdbc2d5a015d0a3e1872e11472bbd0e7b9e6a202"
dependencies:
add-px-to-style "1.0.0"
prefix-style "2.0.1"
to-camel-case "1.0.0"
dom-helpers@^3.2.0, dom-helpers@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.2.1.tgz#3203e07fed217bd1f424b019735582fc37b2825a"
......@@ -3592,6 +3604,10 @@ inquirer@^0.12.0:
strip-ansi "^3.0.0"
through "^2.3.6"
install@^0.10.2:
version "0.10.2"
resolved "https://registry.yarnpkg.com/install/-/install-0.10.2.tgz#f1f71902797e5a900069fb9ab80c94055025ffdc"
internal-ip@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-1.2.0.tgz#ae9fbf93b984878785d50a8de1b356956058cf5c"
......@@ -5752,6 +5768,10 @@ postcss@^6.0.1, postcss@^6.0.2:
source-map "^0.6.1"
supports-color "^4.4.0"
prefix-style@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/prefix-style/-/prefix-style-2.0.1.tgz#66bba9a870cfda308a5dc20e85e9120932c95a06"