Commit be308275 authored by Andrew Hrdy's avatar Andrew Hrdy
Browse files

Merge branch 'searchbar-to-navbar'

parents dd9ca46c 886e2c9a
Pipeline #1894 passed with stage
in 1 minute and 44 seconds
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
"build-css": "node-sass-chokidar src/styles/ -o src/styles/build", "build-css": "node-sass-chokidar src/styles/ -o src/styles/build",
"watch-css": "node-sass-chokidar src/styles/ -o src/styles/build --watch --recursive", "watch-css": "node-sass-chokidar src/styles/ -o src/styles/build --watch --recursive",
"start-js": "react-scripts start", "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-js": "react-scripts build",
"build": "npm-run-all build-css build-js", "build": "npm-run-all build-css build-js",
"test": "react-scripts test --env=jsdom", "test": "react-scripts test --env=jsdom",
......
...@@ -5,6 +5,7 @@ export const SET_FACILITIES = 'SET_FACILITIES'; ...@@ -5,6 +5,7 @@ export const SET_FACILITIES = 'SET_FACILITIES';
export const GET_FACILITIES = 'GET_FACILITIES'; export const GET_FACILITIES = 'GET_FACILITIES';
export const SET_SELECTED_FACILITY = 'SET_SELECTED_FACILITY'; export const SET_SELECTED_FACILITY = 'SET_SELECTED_FACILITY';
export const SET_SEARCH_TERM = 'SET_SEARCH_TERM'; 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 ADD_FAVORITE_FACILITY = 'ADD_FAVORITE_FACILITY';
export const REMOVE_FAVORITE_FACILITY = 'REMOVE_FAVORITE_FACILITY'; export const REMOVE_FAVORITE_FACILITY = 'REMOVE_FAVORITE_FACILITY';
export const SET_ALL_FAVORITES = 'SET_ALL_FAVORITES'; export const SET_ALL_FAVORITES = 'SET_ALL_FAVORITES';
......
...@@ -2,6 +2,7 @@ import { ...@@ -2,6 +2,7 @@ import {
ADD_FAVORITE_FACILITY, ADD_FAVORITE_FACILITY,
REMOVE_FAVORITE_FACILITY, REMOVE_FAVORITE_FACILITY,
SET_SEARCH_TERM, SET_SEARCH_TERM,
SET_CAMPUS_REGION,
TOGGLE_SIDEBAR, TOGGLE_SIDEBAR,
TOGGLE_SIDEBAR_MAP, TOGGLE_SIDEBAR_MAP,
SET_ALL_FAVORITES, SET_SELECTED_FACILITY, SET_SIDEBAR SET_ALL_FAVORITES, SET_SELECTED_FACILITY, SET_SIDEBAR
...@@ -13,9 +14,7 @@ export const toggleSidebar = () => ({ ...@@ -13,9 +14,7 @@ export const toggleSidebar = () => ({
export const setSidebar = (setOpen) => ({ export const setSidebar = (setOpen) => ({
type: SET_SIDEBAR, type: SET_SIDEBAR,
setOpen, setOpen
}); });
export const toggleSidebarMap = () => ({ export const toggleSidebarMap = () => ({
...@@ -32,6 +31,11 @@ export const setSearchTerm = (term) => ({ ...@@ -32,6 +31,11 @@ export const setSearchTerm = (term) => ({
term, term,
}); });
export const setCampusRegion = (campusRegion) => ({
type: SET_CAMPUS_REGION,
campusRegion
});
export const addFavoriteFacility = slug => ({ export const addFavoriteFacility = slug => ({
type: ADD_FAVORITE_FACILITY, type: ADD_FAVORITE_FACILITY,
slug slug
...@@ -45,6 +49,6 @@ export const removeFavoriteFacility = slug => ({ ...@@ -45,6 +49,6 @@ export const removeFavoriteFacility = slug => ({
export const setAllFavorites = (favorites) => ({ export const setAllFavorites = (favorites) => ({
type: SET_ALL_FAVORITES, type: SET_ALL_FAVORITES,
favorites, favorites,
}) });
...@@ -5,6 +5,7 @@ import Typography from 'material-ui/Typography'; ...@@ -5,6 +5,7 @@ import Typography from 'material-ui/Typography';
import Button from 'material-ui/Button'; import Button from 'material-ui/Button';
import IconButton from 'material-ui/IconButton'; import IconButton from 'material-ui/IconButton';
import MenuIcon from 'material-ui-icons/Menu'; import MenuIcon from 'material-ui-icons/Menu';
import SearchBar from '../containers/SearchBar';
import classNames from 'classnames' import classNames from 'classnames'
class CustomAppBar extends React.Component { class CustomAppBar extends React.Component {
...@@ -12,7 +13,8 @@ class CustomAppBar extends React.Component { ...@@ -12,7 +13,8 @@ class CustomAppBar extends React.Component {
constructor(props) { constructor(props) {
super(); super();
this.state = { this.state = {
isAppBarExpanded: false isAppBarExpanded: false,
isSearchExpanded: false,
}; };
this.toggleExpand = this.toggleExpand.bind(this); this.toggleExpand = this.toggleExpand.bind(this);
...@@ -26,12 +28,15 @@ class CustomAppBar extends React.Component { ...@@ -26,12 +28,15 @@ class CustomAppBar extends React.Component {
render() { render() {
return (<div> 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'}> <Toolbar className={'app-bar-tool-bar'}>
<img src={require('../images/SRCT_square.svg')} className={'app-bar-logo'}/> <img src={require('../images/SRCT_square.svg')} className={'app-bar-logo'}/>
<Typography type="title" className={classNames('app-bar-title', 'app-bar-text-color')}> <Typography type="title" className={classNames('app-bar-title', 'app-bar-text-color')}>
What's Open What's Open
</Typography> </Typography>
<SearchBar onSearchExpand={() => this.setState({isSearchExpanded: true})}
onSearchCollapse={() => this.setState({isSearchExpanded: false})}/>
<IconButton onClick={this.toggleExpand} aria-label="Menu" <IconButton onClick={this.toggleExpand} aria-label="Menu"
className={classNames('app-bar-menu-button', 'app-bar-text-color')}> className={classNames('app-bar-menu-button', 'app-bar-text-color')}>
<MenuIcon/> <MenuIcon/>
......
import React from 'react' import React from 'react'
import {withStyles} from 'material-ui/styles';
import FacilityCard from '../containers/FacilityCard' import FacilityCard from '../containers/FacilityCard'
import Grid from 'material-ui/Grid'; import Grid from 'material-ui/Grid';
const CardContainer = ({searchTerm, facilities}) => { const CardContainer = ({searchTerm, campusRegion, facilities}) => {
const filterCards = (facility) => { const filterCards = (facility) => {
const lsearchTerm = searchTerm.toLowerCase() if (facility.facility_location.campus_region.toLowerCase() !== campusRegion.toLowerCase()) {
const name = facility.facility_name.toLowerCase() return false;
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
} }
return name.includes(lsearchTerm) || hasTag
} const lSearchTerm = searchTerm.toLowerCase();
// console.log(facilities) 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 ( return (
<Grid container className={'card-container-root'} spacing={24} justify={'center'} alignItems={'flex-end'}> <Grid container className={'card-container-root'} spacing={24} justify={'center'} alignItems={'flex-end'}>
{facilities.filter(filterCards).map(item =>{ {facilities.filter(filterCards).map(item => {
return( return (
<Grid key={item.slug} item> <Grid key={item.slug} item>
<FacilityCard facility={item} facilities={facilities}/> <FacilityCard facility={item} facilities={facilities}/>
</Grid> </Grid>
...@@ -32,6 +40,6 @@ const CardContainer = ({searchTerm, facilities}) => { ...@@ -32,6 +40,6 @@ const CardContainer = ({searchTerm, facilities}) => {
})} })}
</Grid> </Grid>
) )
} };
export default CardContainer; export default CardContainer;
\ No newline at end of file
...@@ -5,11 +5,9 @@ import AppBar from '../components/AppBar'; ...@@ -5,11 +5,9 @@ import AppBar from '../components/AppBar';
import Sidebar from '../components/Sidebar'; import Sidebar from '../components/Sidebar';
import {getFacilities, setFacilities,sortByFavorites} from '../actions/api'; import {getFacilities, setFacilities,sortByFavorites} from '../actions/api';
import CardContainer from '../components/CardContainer'; import CardContainer from '../components/CardContainer';
import SearchBar from './SearchBar';
import KeyboardArrowLeft from 'material-ui-icons/KeyboardArrowLeft'; import KeyboardArrowLeft from 'material-ui-icons/KeyboardArrowLeft';
import KeyboardArrowRight from 'material-ui-icons/KeyboardArrowRight'; import KeyboardArrowRight from 'material-ui-icons/KeyboardArrowRight';
class Layout extends React.Component { class Layout extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
...@@ -39,16 +37,15 @@ class Layout extends React.Component { ...@@ -39,16 +37,15 @@ class Layout extends React.Component {
}; };
render() { 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 ( return (
<div className={'layout-root'}> <div className={'layout-root'}>
<AppBar isOpen={false} handleMenuClick={() => { <AppBar isOpen={false} handleMenuClick={() => {
}}/> }}/>
<div className={'layout-container'}> <div className={'layout-container'}>
<div className={'layout-main-content'}> <div className={'layout-main-content'}>
<SearchBar suggestions={{}}/>
<div className={'layout-card-container'}> <div className={'layout-card-container'}>
<CardContainer styles={'layout-card-container'} searchTerm={searchTerm} <CardContainer styles={'layout-card-container'} searchTerm={searchTerm} campusRegion={campusRegion}
facilities={facilities} /> facilities={facilities} />
</div> </div>
</div> </div>
...@@ -66,6 +63,7 @@ function mapStateToProps(state) { ...@@ -66,6 +63,7 @@ function mapStateToProps(state) {
facilities: state.facilities.data, facilities: state.facilities.data,
favorites: state.ui.favorites, favorites: state.ui.favorites,
searchTerm: state.ui.search.term, searchTerm: state.ui.search.term,
campusRegion: state.ui.search.campusRegion,
isLoading: state.facilities.isLoading, isLoading: state.facilities.isLoading,
selectedFacility: state.ui.selectedFacility, selectedFacility: state.ui.selectedFacility,
isSidebarOpen: state.ui.sidebar.isOpen, isSidebarOpen: state.ui.sidebar.isOpen,
......
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; 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 {connect} from 'react-redux';
import {setSearchTerm} from '../actions/ui'; import {setSearchTerm, setCampusRegion} from '../actions/ui';
import Search from 'material-ui-icons/Search' 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 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 { class SearchBar extends React.Component {
constructor(props) {
super(props);
this.state = {
isFocused: false,
isMobileOpen: false,
value: '',
campus: 'fairfax'
};
}
handleChange = (e) => { handleChange = (e) => {
this.setState({ this.setState({
value: e.target.value, 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() { render() {
return ( 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 <Input
placeholder="names, locations, etc" placeholder="Name, Location, etc."
disableUnderline disableUnderline
fullWidth className={'search-bar-input'}
autoFocus
className={'search-bar-no-suggest-input'}
onChange={this.handleChange} onChange={this.handleChange}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
inputProps={{ inputProps={{
'aria-label': 'Description', 'aria-label': 'Search Bar',
}} }}
inputRef={el => this.inputElement = el}
value={this.state.value}
/> />
<div className={'search-bar-right-search-container'}> <IconButton onClick={this.clear} disableRipple className={'search-bar-close-btn'}>
<Search className={'search-bar-search-icon'}/> <CloseIcon/>
</div> </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> </Paper>
); );
} }
} }
export default connect(null, {setSearchTerm})(SearchBar); SearchBar.propTypes = {
\ No newline at end of file onSearchExpand: PropTypes.func,
onSearchCollapse: PropTypes.func
};
export default connect(null, {setSearchTerm, setCampusRegion})(SearchBar);
\ No newline at end of file
html{ html{
width:100%; width:100%;
height: 100%; height: 100%;
overflow:hidden;
} }
body { body {
width: 100%; width: 100%;
......
import { import {
TOGGLE_SIDEBAR, SET_SELECTED_FACILITY, SET_SEARCH_TERM, SET_FILTERED_LIST, 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, ADD_FAVORITE_FACILITY, REMOVE_FAVORITE_FACILITY, SET_ALL_FAVORITES, TOGGLE_SIDEBAR_MAP, SET_SIDEBAR,
} from '../actions/action-types' } from '../actions/action-types'
const selectedFacility = (state = {}, action) => { const selectedFacility = (state = {}, action) => {
...@@ -37,8 +37,9 @@ const sidebar = (state=sidebarDefault,action) => { ...@@ -37,8 +37,9 @@ const sidebar = (state=sidebarDefault,action) => {
}; };
const searchbarState = { const searchbarState = {
term:'', term: '',
filteredList:[], campusRegion: 'fairfax',
filteredList: [],
}; };
const filterList = (state) =>{ const filterList = (state) =>{
...@@ -50,6 +51,10 @@ const search = (state=searchbarState,facilities=[],action) =>{ ...@@ -50,6 +51,10 @@ const search = (state=searchbarState,facilities=[],action) =>{
return Object.assign({},state,{ return Object.assign({},state,{
term:action.term, term:action.term,
}); });
case SET_CAMPUS_REGION:
return Object.assign({}, state, {
campusRegion: action.campusRegion
});
default: default:
return state; return state;
} }
......
@import '../variables';
.app-bar { .app-bar {
background-color: white !important; background-color: white !important;
box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.2) !important; box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.2) !important;
...@@ -21,7 +23,7 @@ ...@@ -21,7 +23,7 @@
color: #354052; color: #354052;
} }
@media screen and (max-width: 600px) { @media screen and (max-width: map-get($breakpoints, lg) - 1px) {
.app-bar-link-button { .app-bar-link-button {
display: block !important; display: block !important;
padding: 0 !important; padding: 0 !important;
...@@ -46,4 +48,10 @@ ...@@ -46,4 +48,10 @@
flex-basis: 100%; flex-basis: 100%;
transition: ease-in-out 2s; 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 { .card-container-root {
margin: 0; margin: 0;
padding-top:32px;
width: 100%; width: 100%;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
......
...@@ -34,6 +34,11 @@ ...@@ -34,6 +34,11 @@
@include transition(300ms cubic-bezier(0.820, 0.165, 0.340, 0.930)); @include transition(300ms cubic-bezier(0.820, 0.165, 0.340, 0.930));
} }
.sidebar-root::-webkit-scrollbar {
display: none;
}
.card-container-offset-open{ .card-container-offset-open{
flex: 1 0 400px; flex: 1 0 400px;
...@@ -78,12 +83,15 @@ ...@@ -78,12 +83,15 @@
width: 100%; width: 100%;
} }
.sidebar-scroll{ .sidebar-scroll{
height:calc(100% - 220px - 116px - 32px); height:calc(100% - 220px - 116px - 32px) !important;
overflow-y: auto; overflow-y: auto;
} }
@media screen and (max-width: map-get($breakpoints, lg) - 1px) { @media screen and (max-width: map-get($breakpoints, lg) - 1px) {
.sidebar-root { .sidebar-root {
display: none !important; display: none !important;
} }
.card-container-offset{
display: none !important;
}
} }
\ No newline at end of file
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
flex: 1 1 100%; flex: 1 1 100%;
height: 100%; height: 100%;
width: 100%; width: 100%;
padding-top: 16px; // padding-top: 32px;
} }
.layout-sidebar-toggle-container { .layout-sidebar-toggle-container {
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
}