Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Loading animations and update error handling #14

Merged
merged 6 commits into from
Nov 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 27 additions & 7 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,53 @@ import styled from 'styled-components/macro'
import useUserLocation from './hooks/useUserLocation'
import MainPage from './MainPage'
import ResultPage from './ResultPage'
import ErrorPage from './ErrorPage'
import LoadingPage from './LoadingPage'

function App() {
const {
userPlace,
setUserPlace,
countyData,
errorMessage,
setErrorMessage,
isDataLoading,
isCountyDataLoaded,
resetSearch,
showMainPage,
setSearchOrigin,
} = useUserLocation()

return (
<AppStyled>
<Switch>
<Route exact path="/">
<MainPage
userPlace={userPlace}
setUserPlace={setUserPlace}
errorMessage={errorMessage}
isCountyDataLoaded={isCountyDataLoaded}
isDataLoading={isDataLoading}
resetSearch={resetSearch}
setSearchOrigin={setSearchOrigin}
/>
</Route>

<Route path="/:id">
<ResultPage
setUserPlace={setUserPlace}
countyData={countyData}
isCountyDataLoaded={isCountyDataLoaded}
<Route path="/s/:id">
{isDataLoading ? (
<LoadingPage />
) : (
<ResultPage
setUserPlace={setUserPlace}
countyData={countyData}
isCountyDataLoaded={isCountyDataLoaded}
/>
)}
</Route>

<Route path="/error">
<ErrorPage
setErrorMessage={setErrorMessage}
showMainPage={showMainPage}
/>
</Route>
</Switch>
Expand All @@ -41,4 +61,4 @@ const AppStyled = styled.div`
max-width: 375px;
`

export default App
export default App
34 changes: 34 additions & 0 deletions src/ErrorPage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import styled from 'styled-components/macro'
import Button from './components/Button'

function ErrorPage({ setErrorMessage, showMainPage }) {
function resetError() {
setErrorMessage('')
showMainPage()
}

return (
<ErrorPageStyled>
<section className="result-wrapper">
<h3>Sorry, Daten konnten nicht geladen werden.</h3>
<span>Probiere eine neue Suche!</span>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may want to set the styling in "result-wrapper" class to get rid of the span?

Copy link
Owner Author

@JulianBlohm JulianBlohm Nov 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, but have to stick with the span, cause don't want the whole text in the result wrapper being font-weight: 300.

</section>
<section className="information-wrapper">
<Button onClick={resetError}>Neue Suche</Button>
</section>
</ErrorPageStyled>
)
}

const ErrorPageStyled = styled.div`
.result-wrapper {
padding: 37px;
background: var(--red);
color: var(--silver);
}

.information-wrapper {
margin: 0 18px;
}
`
export default ErrorPage
18 changes: 18 additions & 0 deletions src/LoadingPage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import styled from 'styled-components/macro'
import LoadingSpinner from './components/LoadingSpinner'

function LoadingPage() {
return (
<LoadingContainer>
<LoadingSpinner />
</LoadingContainer>
)
}

const LoadingContainer = styled.div`
height: 100vh;
display: grid;
place-items: center;
`

export default LoadingPage
41 changes: 24 additions & 17 deletions src/MainPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,40 @@ import { useEffect } from 'react'
import styled from 'styled-components/macro'
import Form from './components/Form'


function MainPage({setUserPlace, errorMessage, isCountyDataLoaded, resetSearch}) {

useEffect(() => {isCountyDataLoaded && resetSearch()}, [])
function MainPage({
userPlace,
setUserPlace,
errorMessage,
isDataLoading,
resetSearch,
setSearchOrigin,
}) {
useEffect(() => {
userPlace && resetSearch()
}, [])

return (
<MainPageStyled>
<h1>Bin ich in einem Covid-19 Hotspot?</h1>
<Form
<Form
setUserPlace={setUserPlace}
errorMessage={errorMessage}
>
</Form>
</MainPageStyled>
isDataLoading={isDataLoading}
setSearchOrigin={setSearchOrigin}
/>
</MainPageStyled>
)
}

const MainPageStyled = styled.div`
padding: 10px;
display: grid;
grid-gap: 20px;
background: #F5F5F7;
padding: 10px;
display: grid;
grid-gap: 20px;
background: var(--silver);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice to work with variablen. You might think about it work with main oder primary in the naming. So it's a little bit clearer what kind it is.


h1 {
margin: 100px 0;
}
h1 {
margin: 100px 0;
}
`


export default MainPage
export default MainPage
135 changes: 64 additions & 71 deletions src/ResultPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,98 +2,91 @@ import { useState, useEffect } from 'react'
import { Link, useParams } from 'react-router-dom'
import styled from 'styled-components/macro'
import Button from './components/Button'
import ExternalLink from './components/ExternalLink'

function ResultPage({setUserPlace, countyData, isCountyDataLoaded}) {

function ResultPage({ setUserPlace, countyData, isCountyDataLoaded }) {
const [countyClassification, setCountyClassification] = useState('')

let { id } = useParams()

useEffect(() => classifyCountyIncidence(), [countyData])
useEffect(() => {!isCountyDataLoaded && setUserPlace(id)}, [id])
useEffect(() => {
!isCountyDataLoaded && setUserPlace(id)
}, [id])

function classifyCountyIncidence() {
if(countyData.incidence > 35) {
if (countyData.incidence > 35) {
setCountyClassification('county-class-red')
} else {
setCountyClassification('county-class-green')}
setCountyClassification('county-class-green')
}
}

return (
<ResultPageStyled>
{isCountyDataLoaded ? (
<>
<section className={countyClassification + " result-wrapper"}>
{countyData.incidence > 35 ?
<h2> {countyData.countyName} ist ein Covid-19 Hotspot.</h2> :
<h2> {countyData.countyName} ist kein Covid-19 Hotspot.</h2>
}
<h3>Die 7-Tage-Inzidenz <br/> liegt bei {countyData.incidence}. </h3>
<span>Daten vom {countyData.last_update}</span>
</section>
<section className="information-wrapper">
<a href="https://www.bundesregierung.de/breg-de/themen/coronavirus/corona-bundeslaender-1745198">
<Button text="Regeln der Bundesländer"/>
</a>
<a href="https://www.bundesregierung.de/breg-de/themen/coronavirus/corona-massnahmen-1734724">
<Button text="FAQ Bundesregierung.de"/>
</a>
<Link to="/"><Button text="Neue Suche"/></Link>
</section>
</>
) : (
<>
<section className="county-class-red result-wrapper">
<h3>Sorry, Daten konnten nicht geladen werden.</h3>
<span>Probiere eine neue Suche!</span>
</section>
<section className="information-wrapper">
<Link to="/"><Button text="Neue Suche"/></Link>
</section>
</>
{isCountyDataLoaded && (
<>
<section
className={countyClassification + ' result-wrapper'}
>
{countyData.incidence > 35 ? (
<h2>
{countyData.countyName} ist ein Covid-19
Hotspot.
</h2>
) : (
<h2>
{countyData.countyName} ist kein Covid-19
Hotspot.
</h2>
)}
<h3>
Die 7-Tage-Inzidenz <br /> liegt bei{' '}
{countyData.incidence}.
</h3>
<span>Daten vom {countyData.last_update}</span>
</section>
<section className="information-wrapper">
<ExternalLink
target="_blank"
href="https://www.bundesregierung.de/breg-de/themen/coronavirus/corona-bundeslaender-1745198"
>
Regeln der Bundesländer
</ExternalLink>
<ExternalLink
target="_blank"
href="https://www.bundesregierung.de/breg-de/themen/coronavirus/corona-massnahmen-1734724"
>
FAQ Bundesregierung.de
</ExternalLink>
<Link to="/">
<Button>Neue Suche</Button>
</Link>
</section>
</>
)}
</ResultPageStyled>
)
}

const ResultPageStyled = styled.div`
.result-wrapper {
padding: 37px;
}

h2 {
margin-bottom: 46px;
font-size: 32px;
}

h3 {
margin-bottom: 41px;
line-height: 1.5;
font-size: 26px;
}

span {
font-weight: 300;
}

a {
text-decoration: none;
}

.result-wrapper {
padding: 37px;
}

.county-class-red {
background: var(--red);
color: var(--silver);
}
.county-class-red {
background: var(--red);
color: var(--silver);
}

.county-class-green {
background: var(--green);
color: var(--silver);
}
.county-class-green {
background: var(--green);
color: var(--silver);
}

.information-wrapper {
margin: 0 18px;
}
.information-wrapper {
margin: 0 18px;
}
`

export default ResultPage
export default ResultPage
43 changes: 13 additions & 30 deletions src/components/Button.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,16 @@
import styled from 'styled-components/macro'
import PropTypes from 'prop-types'

function Button({text, onClick}) {

return (
<>
<ButtonStyled onClick={onClick}>{text}</ButtonStyled>
</>
)
}

const ButtonStyled = styled.button`
border: none;
background: var(--button);
color: white;
width: 100%;
display: flex;
height: 48px;
justify-content: center;
align-items: center;
font-size: 1rem;
border-radius: 5px;
margin: 20px 0 ;
cursor: pointer;
export default styled.button`
border: none;
background: ${(props) => (props.disabled ? 'var(--gray)' : 'var(--blue)')};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here ;-) "more speacking names" maybe

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is also easier to change the main colors in the whole app that way. :)

color: white;
width: 100%;
display: flex;
height: 48px;
justify-content: center;
align-items: center;
font-size: 1rem;
border-radius: 5px;
margin: 20px 0;
cursor: pointer;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could think of grouping properties according theire functions to have a better overview. E. g. everything with display, fonts and so on.

`

Button.propTypes = {
text: PropTypes.string.isRequired,
onClick: PropTypes.func
}

export default Button
Loading