-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* started on scaffold * completed how does it work page, added it to navlink and how it works section on the home page * removed unused import from routes * resolving conflicts from new merges * resolve more conflicts * Upgrade react packages to latest * Remove deprecated react-router-redux package * Added to nav bar * Reverse react-router packages to previous versions * Update react-google-maps withScriptjs import statement * Fix react-modal accessibility issue * Remove --browser chrome from cypress script * Move to SFC, cleanup typo in routing * changed navbar to not fluid to remove horizontal content overflow/scrolling on mobile * WIP: Steps component (without animations) * small firebase typo fixes * added cypress tests and AutoSuggestInput(partial functionality) for steps component * added vertical option for Steps on homepage and progress bars * added basic step sliding animations with react-spring * added animations to recycling rate bars * updated recycling info section * fixed centering on steps slider component * updated styles on HeroCTA and Homepage * added HeroCTA to tenant focused secondary homepage * moved search bar from inside sliding steps component to below it * made height of sliding steps component responsive to currently visible/active step content height * set steps component default to hide internal prev/next buttons, added custom external buttons using a ref in HowItWorks(tenant homepage) page for improved visibility * made next step's selector oscillate colors between yellow and green to make interactivity clear to users * added autoSlide and autoSlideDelay options to steps component that automate sliding through the steps until a user clicks on a step navigation button * more responsive font sizes for text over skyline image * minor style changes to search bar section of tenant homepage * remove RecyclingInfo component from homepage * changed default autoSlideDelay on steps component to 4 seconds * changed content of first step on homepage vertical steps slider * fixed memory leak error by clearing intervals in steps component * updated cypress tests for the how it works page * refactored/removed some cypress tests to pass with new wireframe updates to UI * refactored tenant or property manager choice on home page to be its own component, minor style change to buttons, and pointed property manager button link to manager-resources page * set autoFocus to false on AutoSuggestInput component search bar so that the tenant homepage doesn't automatically scroll to the bottom on every visit * removed unnecessary package-lock.json file that must have been accidentally committed to the deprecated how-does-it-work branch a long while ago * removed unnecessary imports causing warnings that don't allow travis ci tests to pass * fixing many travis ci warnings/errors * fixing many travis ci warnings/errors * hopefully last fixes for travis ci errors * made steps component nav buttons accessible by keyboard, removed some more unused imports/vars * removed deprecated SectionSlice component * moved Steps component nav buttons to separate component: StepsMainNav * made step selector buttons use semantic <button> tags instead of divs * cleaning up and refactoring Steps component to not use refs anti-pattern and be more reusable * more cleaning: destructuring props, binding this with es6 arrow functions instead of .bind(this)
- Loading branch information
Showing
50 changed files
with
1,957 additions
and
273 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { Row, Col } from 'react-bootstrap'; | ||
|
||
const Banner = props => ( | ||
<Row className="banner-row"> | ||
<Col xs={12}> | ||
<div className="banner-content">{props.children}</div> | ||
</Col> | ||
</Row> | ||
); | ||
|
||
Banner.propTypes = { | ||
children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired | ||
}; | ||
|
||
export default Banner; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,59 +1,17 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { Grid, Row, Col, Button } from 'react-bootstrap'; | ||
import AutoSuggestInput from './AutoSuggestInput'; | ||
import { Grid } from 'react-bootstrap'; | ||
|
||
const HeroCTA = ({ | ||
openMap, | ||
firebaseSearchAddressFlow, | ||
clearInitialSearchResults, | ||
firebaseCampaigns, | ||
router | ||
}) => ( | ||
const HeroCTA = () => ( | ||
<Grid fluid> | ||
<div className="tinted" /> | ||
<Row className="hero-wrapper"> | ||
<Col className="hero-page-header" xs={12}> | ||
<div className="hero-wrapper"> | ||
<div className="hero-page-header"> | ||
<div className="opacity-div"> | ||
<h1>NEED RECYCLING?</h1> | ||
<h2 className="font-italic">Recruit, Request, Recycle</h2> | ||
<Row> | ||
<Col xs={10} xsOffset={1}> | ||
<h3> | ||
We have a mission to change Denver's low recycling rate by making it easy for you | ||
and your neighbors to petition your landlord for recyling for your building. | ||
</h3> | ||
</Col> | ||
</Row> | ||
<h1>NEED RECYCLING IN YOUR APARTMENT OR CONDO?</h1> | ||
<div className="font-italic">Recruit, Request, Recycle</div> | ||
</div> | ||
</Col> | ||
</Row> | ||
<Row> | ||
<Col xs={12} className="hero-search"> | ||
<form> | ||
<AutoSuggestInput | ||
firebaseSearchAddressFlow={firebaseSearchAddressFlow} | ||
clearInitialSearchResults={clearInitialSearchResults} | ||
firebaseCampaigns={firebaseCampaigns} | ||
router={router} | ||
/> | ||
<div className="text-center"> | ||
<Button className="map-btn" bsStyle="as-link" onClick={openMap}> | ||
Explore Nearby Campaigns | ||
</Button> | ||
</div> | ||
</form> | ||
</Col> | ||
</Row> | ||
</div> | ||
</div> | ||
</Grid> | ||
); | ||
|
||
HeroCTA.propTypes = { | ||
openMap: PropTypes.func.isRequired, | ||
clearInitialSearchResults: PropTypes.func.isRequired, | ||
firebaseCampaigns: PropTypes.shape({}).isRequired, | ||
firebaseSearchAddressFlow: PropTypes.func.isRequired, | ||
router: PropTypes.shape({}).isRequired | ||
}; | ||
|
||
export default HeroCTA; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { Grid, Row, Col } from 'react-bootstrap'; | ||
import { connect } from 'react-redux'; | ||
import AutoSuggestInput from '../AutoSuggestInput'; | ||
import { | ||
firebaseSearchAddressFlow, | ||
clearInitialSearchResults | ||
} from '../../redux/actions/firebaseInitialSearch'; | ||
|
||
// import screenShot from '../../images/screen-shot.png'; | ||
// import list from '../../images/list.png'; | ||
// import letter from '../../images/letter.png'; | ||
// import smallList from '../../images/small-list.png'; | ||
// import guideline1 from '../../images/guildline1.png'; | ||
// import guideline2 from '../../images/guideline2.png'; | ||
|
||
import HeroCTA from '../HeroCTA'; | ||
import Steps from './Steps'; | ||
import Footer from '../Footer/Footer'; | ||
import HowItWorksStepHeaderContent from './HowItWorksStepHeaderContent'; | ||
import HowItWorksStepContent from './HowItWorksStepContent'; | ||
|
||
const stepsData = [ | ||
{ | ||
title: 'Create or Join a Campaign', | ||
icon: <i className="fa fa-bullhorn how-icon" />, | ||
prevStepBtn: <i className="fa fa-angle-left" style={{ fontSize: '5rem' }} />, | ||
nextStepBtn: <i className="fa fa-angle-right" style={{ fontSize: '5rem' }} />, | ||
content: [ | ||
{ h3: 'Start by searching for your condo or apartment building address' }, | ||
{ | ||
p: | ||
`Enter your condo or apartment building address in the search bar below to find out${' '}` + | ||
`if there is a recycling campaign already active for your building. Then, follow${' '}` + | ||
`the on screen instructions to either create a brand new campaign or sign the${' '}` + | ||
'online petition for an existing one.' | ||
} | ||
] | ||
}, | ||
{ | ||
title: 'Recruit Your Neighbors', | ||
icon: <i className="fa fa-users how-icon" />, | ||
prevStepBtn: <i className="fa fa-angle-left" style={{ fontSize: '5rem' }} />, | ||
nextStepBtn: <i className="fa fa-angle-right" style={{ fontSize: '5rem' }} />, | ||
content: [ | ||
{ h3: 'Power in Numbers' }, | ||
{ | ||
p: | ||
`Now it's time to spread the word about your building's new recycling campaign to${' '}` + | ||
`your neighbors. Gathering signatures from your fellow tenants let's your landlord${' '}` + | ||
'know just how important recycling services are to your community!' | ||
}, | ||
{ h3: 'Tools' }, | ||
{ | ||
ul: [ | ||
{ | ||
li: | ||
`Print and post this petition in a public space in your apartment building, such${' '}` + | ||
'as a laundry or mail room.' | ||
} | ||
] | ||
} | ||
] | ||
}, | ||
{ | ||
title: 'Request Recyling From Your Landlord', | ||
icon: <i className="fa fa-comment how-icon" />, | ||
prevStepBtn: <i className="fa fa-angle-left" style={{ fontSize: '5rem' }} />, | ||
nextStepBtn: <i className="fa fa-angle-right" style={{ fontSize: '5rem' }} />, | ||
content: [ | ||
{ | ||
p: | ||
`Submit the letter to your landlord along with the petition signatures. If${' '}` + | ||
'possible, bring other neighbors along; there is great strength in numbers.' | ||
} | ||
] | ||
}, | ||
{ | ||
title: 'Recycle!', | ||
icon: <i className="fa fa-recycle how-icon" />, | ||
prevStepBtn: <i className="fa fa-angle-left" style={{ fontSize: '5rem' }} />, | ||
nextStepBtn: <i className="fa fa-angle-right" style={{ fontSize: '5rem' }} />, | ||
content: [ | ||
{ | ||
p: | ||
`Congratulations for getting recycling services for your building! Best practice${' '}` + | ||
`shows that posting guidelines will help your neighbors recycle correctly. When a${' '}` + | ||
`recycling bin is too contaminated your complex will either be given 1 week to${' '}` + | ||
`clean out the recycling bin or be charged extra to take it to a landfill as trash.${' '}` + | ||
`Common contaminants in the recycing bin include plastic bags because they jam up${' '}` + | ||
`the machine and disposable ware such as red solo cups, disposable cutlery and${' '}` + | ||
'disposable plates.' | ||
} | ||
] | ||
} | ||
]; | ||
|
||
const HowItWorks = props => { | ||
let currentStep = 0; | ||
if (props.location.state && props.location.action === 'PUSH') { | ||
currentStep = props.location.state.currentStep; | ||
} | ||
|
||
const steps = stepsData.map((stepData, index) => ({ | ||
headerContent: ( | ||
<HowItWorksStepHeaderContent | ||
title={stepData.title} | ||
icon={stepData.icon} | ||
stepIndex={index} | ||
priority={2} | ||
stacked | ||
/> | ||
), | ||
content: <HowItWorksStepContent content={stepData.content} />, | ||
prevStepBtn: stepData.prevStepBtn, | ||
nextStepBtn: stepData.nextStepBtn | ||
})); | ||
|
||
return ( | ||
<div className="how-it-works-container"> | ||
<HeroCTA /> | ||
<div className="how-it-works-banner"> | ||
<div> | ||
<h1 className="blue-color" style={{ marginLeft: '1em' }}> | ||
Follow these easy steps! | ||
</h1> | ||
</div> | ||
</div> | ||
|
||
<Steps pulseNextStep currentStep={currentStep} steps={steps} /> | ||
|
||
<Grid className="search-container"> | ||
<Row> | ||
<Col xs={12} md={10} mdOffset={1}> | ||
<h3 className="call-to-action">Ready? Enter your address!</h3> | ||
</Col> | ||
</Row> | ||
<Row> | ||
<Col xs={12} md={10} mdOffset={1}> | ||
<div style={{ textAlign: 'center' }}> | ||
Start a campaign to bring recycling to your property! Search your address below to get | ||
started. | ||
</div> | ||
</Col> | ||
</Row> | ||
<Row> | ||
<Col xs={12} md={10} mdOffset={1}> | ||
<AutoSuggestInput | ||
firebaseSearchAddressFlow={props.firebaseSearchAddressFlow} | ||
clearInitialSearchResults={props.clearInitialSearchResults} | ||
router={props.router} | ||
/> | ||
</Col> | ||
</Row> | ||
</Grid> | ||
|
||
<Footer /> | ||
</div> | ||
); | ||
}; | ||
|
||
HowItWorks.defaultProps = { | ||
location: { | ||
state: { | ||
currentStep: 0 | ||
} | ||
} | ||
}; | ||
|
||
HowItWorks.propTypes = { | ||
router: PropTypes.shape({}).isRequired, | ||
location: PropTypes.shape({ | ||
state: PropTypes.shape({ | ||
currentStep: PropTypes.number | ||
}), | ||
action: PropTypes.string.isRequired | ||
}).isRequired, | ||
firebaseSearchAddressFlow: PropTypes.func.isRequired, | ||
clearInitialSearchResults: PropTypes.func.isRequired | ||
}; | ||
|
||
export default connect( | ||
null, | ||
{ | ||
firebaseSearchAddressFlow, | ||
clearInitialSearchResults | ||
} | ||
)(HowItWorks); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { Row, Col, Grid } from 'react-bootstrap'; | ||
|
||
const buildContents = (content, lvl) => { | ||
const result = []; | ||
for (let i = 0; i < content.length; i += 1) { | ||
const keys = Object.keys(content[i]); | ||
if (keys && keys[0]) { | ||
const DynamicTag = `${keys[0]}`; | ||
const value = content[i][DynamicTag]; | ||
if (React.isValidElement(value) || typeof value !== 'object') { | ||
result.push( | ||
<DynamicTag key={`step-content-${keys[0]}-lvl-${lvl}-component-${i}`}>{value}</DynamicTag> | ||
); | ||
} else if (Array.isArray(value)) { | ||
const newElem = ( | ||
<DynamicTag key={`step-content-${keys[0]}-lvl-${lvl}-component-${i}`}> | ||
{buildContents(value, lvl + 1)} | ||
</DynamicTag> | ||
); | ||
result.push(newElem); | ||
} | ||
} | ||
} | ||
return result; | ||
}; | ||
|
||
const HowItWorksStepContent = ({ content }) => { | ||
const result = buildContents(content, 0); | ||
return ( | ||
<Grid> | ||
<Row> | ||
<Col xs={12} md={10} mdOffset={1}> | ||
<div className="how-it-works-step-content-wrapper">{result}</div> | ||
</Col> | ||
</Row> | ||
</Grid> | ||
); | ||
}; | ||
|
||
HowItWorksStepContent.propTypes = { | ||
content: PropTypes.arrayOf(PropTypes.shape({})).isRequired | ||
}; | ||
|
||
export default HowItWorksStepContent; |
29 changes: 29 additions & 0 deletions
29
client/src/components/HowItWorks/HowItWorksStepHeaderContent.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
const HowItWorksStepHeaderContent = ({ title, icon, stepIndex, priority, stacked }) => { | ||
const classes = stacked ? 'step-header-content stacked' : 'step-header-content'; | ||
const HeaderTag = `h${priority}`; | ||
return ( | ||
<div className={classes}> | ||
{icon} | ||
<HeaderTag>{`${stepIndex + 1}. ${title}`}</HeaderTag> | ||
</div> | ||
); | ||
}; | ||
|
||
HowItWorksStepHeaderContent.defaultProps = { | ||
icon: null, | ||
stacked: true, | ||
priority: 2 | ||
}; | ||
|
||
HowItWorksStepHeaderContent.propTypes = { | ||
title: PropTypes.string.isRequired, | ||
icon: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), | ||
stepIndex: PropTypes.number.isRequired, | ||
priority: PropTypes.number, | ||
stacked: PropTypes.bool | ||
}; | ||
|
||
export default HowItWorksStepHeaderContent; |
Oops, something went wrong.