Skip to content

Commit 7e5f3ef

Browse files
committed
Add MVP (aka 'Most Valuable Pup') app
1 parent bdd31b6 commit 7e5f3ef

16 files changed

Lines changed: 344 additions & 71 deletions

public/bone.svg

Lines changed: 11 additions & 0 deletions
Loading

public/favicon.ico

12 KB
Binary file not shown.

public/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
work correctly both with client-side routing and a non-root public URL.
2525
Learn how to configure a non-root public URL by running `npm run build`.
2626
-->
27-
<title>React App</title>
27+
<title>Fetchr</title>
2828
</head>
2929
<body>
3030
<noscript>You need to enable JavaScript to run this app.</noscript>

src/App.css

Lines changed: 0 additions & 38 deletions
This file was deleted.

src/App.tsx

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
import React from 'react';
2-
import logo from './logo.svg';
3-
import './App.css';
2+
import { Root, Subtitle, Title } from './appStyles';
3+
import DogDisplay from './components/DogDisplay';
4+
import FetchDog from './components/FetchDog';
45

5-
function App() {
6-
return (
7-
<div className="App">
8-
<header className="App-header">
9-
<img src={logo} className="App-logo" alt="logo" />
10-
<p>
11-
Edit <code>src/App.tsx</code> and save to reload.
12-
</p>
13-
<a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer">
14-
Learn React
15-
</a>
16-
</header>
17-
</div>
18-
);
19-
}
6+
const App: React.FunctionComponent = () => (
7+
<Root>
8+
<Title>Fetchr</Title>
9+
<Subtitle>
10+
It's about time <em>we</em> did some fetching
11+
</Subtitle>
12+
<FetchDog>
13+
<DogDisplay />
14+
</FetchDog>
15+
</Root>
16+
);
2017

2118
export default App;

src/appStyles.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import styled from 'styled-components';
2+
3+
export const Root = styled.div`
4+
display: flex;
5+
flex-direction: column;
6+
align-items: center;
7+
background-color: midnightblue;
8+
color: white;
9+
min-height: 100%;
10+
padding: 2rem;
11+
`;
12+
13+
export const Title = styled.h1`
14+
font-family: 'Gloria Hallelujah', sans-serif;
15+
font-size: 10rem;
16+
margin-bottom: 1rem;
17+
`;
18+
19+
export const Subtitle = styled.h2`
20+
font-family: 'DM Sans', sans-serif;
21+
font-size: 2.5rem;
22+
font-weight: bold;
23+
margin-bottom: 6rem;
24+
`;

src/components/DogDisplay.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React from 'react';
2+
import { connect } from 'react-redux';
3+
import styled from 'styled-components';
4+
import { ReduxStore } from '../ducks';
5+
6+
const DogPic = styled.img`
7+
border-radius: 1.5rem;
8+
max-height: 50rem;
9+
`;
10+
11+
const DogDisplay: React.FunctionComponent<{ dogPicSrc: string }> = ({ dogPicSrc }) => (
12+
<DogPic src={dogPicSrc} alt="doggo" />
13+
);
14+
15+
const mapDispatchToProps = (state: ReduxStore) => ({
16+
dogPicSrc: state.dogs.dogPicSrc,
17+
});
18+
19+
export default connect(mapDispatchToProps)(DogDisplay);

src/components/ErrorMessage.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import React from 'react';
2+
import styled from 'styled-components';
3+
4+
const Root = styled.div`
5+
text-align: center;
6+
font-size: 10rem;
7+
8+
& > p {
9+
color: red;
10+
font-size: 2rem;
11+
}
12+
`;
13+
14+
const ErrorMessage: React.FunctionComponent<{ error: string }> = ({ error }) => (
15+
<Root>
16+
<span role="img" aria-label="sad face">
17+
😵
18+
</span>
19+
<p>{error}</p>
20+
</Root>
21+
);
22+
23+
export default ErrorMessage;

src/components/FetchDog.tsx

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import React from 'react';
2+
import { connect } from 'react-redux';
3+
import {
4+
fetchDogError,
5+
FetchDogErrorActionCreator,
6+
fetchDogSuccess,
7+
FetchDogSuccessActionCreator,
8+
initiateFetchDog,
9+
InitiateFetchDogActionCreator,
10+
} from '../ducks/dogs';
11+
import { ReduxStore } from '../ducks/index';
12+
import ErrorMessage from './ErrorMessage';
13+
import LoadingBone from './LoadingBone';
14+
15+
interface Props {
16+
initiateFetchDog: InitiateFetchDogActionCreator;
17+
fetchDogSuccess: FetchDogSuccessActionCreator;
18+
fetchDogError: FetchDogErrorActionCreator;
19+
isLoading: boolean;
20+
error: string;
21+
}
22+
23+
const FetchDog: React.FunctionComponent<Props> = ({
24+
children,
25+
initiateFetchDog,
26+
fetchDogSuccess,
27+
fetchDogError,
28+
isLoading,
29+
error,
30+
}) => {
31+
React.useEffect(() => {
32+
initiateFetchDog();
33+
34+
setTimeout(() => {
35+
fetch('https://dog.ceo/api/breeds/image/random')
36+
.then(response => {
37+
// throw new Error('Something went wrong...');
38+
return response.json();
39+
})
40+
.then(json => fetchDogSuccess(json.message))
41+
.catch(error => {
42+
fetchDogError(error.message);
43+
});
44+
}, 4000);
45+
}, []);
46+
47+
if (error) {
48+
return <ErrorMessage error={error} />;
49+
}
50+
51+
return isLoading ? <LoadingBone /> : <>{children}</>;
52+
};
53+
54+
const mapStateToProps = (state: ReduxStore) => ({
55+
isLoading: state.dogs.isLoading,
56+
error: state.dogs.error,
57+
});
58+
59+
const mapDispatchToProps = {
60+
initiateFetchDog,
61+
fetchDogSuccess,
62+
fetchDogError,
63+
};
64+
65+
export default connect(mapStateToProps, mapDispatchToProps)(FetchDog);

src/components/LoadingBone.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import React from 'react';
2+
import styled from 'styled-components';
3+
4+
const Icon = styled.svg`
5+
height: 15rem;
6+
@keyframes spin {
7+
0% {
8+
transform: rotate(0deg);
9+
}
10+
100% {
11+
transform: rotate(719deg);
12+
}
13+
}
14+
animation: spin 2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
15+
margin-top: 10rem;
16+
`;
17+
18+
const LoadingBone: React.FunctionComponent = () => (
19+
<Icon
20+
version="1.1"
21+
xmlns="http://www.w3.org/2000/Icon"
22+
xmlnsXlink="http://www.w3.org/1999/xlink"
23+
x="0px"
24+
y="0px"
25+
viewBox="0 0 1000 1000"
26+
enable-background="new 0 0 1000 1000"
27+
xmlSpace="preserve"
28+
>
29+
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
30+
<g>
31+
<g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)">
32+
<path
33+
fill="#FFF"
34+
d="M7334.8,5000.5c-198.2-48.1-350.3-140.5-529.3-319.5c-138.6-138.6-180.9-198.2-254.1-348.4c-48.1-100.1-105.9-256-127-350.3c-48.1-204-77-571.6-61.6-829.5l9.6-188.6L4266.9,858.7L2161.3-1246.9h-346.4c-383,0-612-28.9-835.3-105.9c-398.4-134.7-714.1-429.2-833.4-775.6c-61.6-182.8-61.6-479.2,0-662.1c154-444.6,575.5-746.8,1047-746.8h150.1v-150.1c0-306,103.9-552.4,325.3-775.6c344.5-344.5,793-419.6,1233.7-205.9c155.9,75,402.3,317.6,504.3,496.6c161.7,277.2,227.1,594.7,227.1,1104.8v348.4L5737.3-615.6l2101.7,2101.7h348.3c398.4,0,623.6,30.8,871.9,121.3c379.1,136.7,685.2,435,802.6,783.3c53.9,159.7,50,469.6-7.7,639c-84.7,246.3-294.5,496.6-517.7,617.8c-136.7,73.1-369.6,129-538.9,129H8657v140.5c0,311.8-105.9,565.9-325.3,785.3C8056.5,4975.5,7688.9,5085.2,7334.8,5000.5z M7908.3,4686.8c400.3-198.2,562-594.7,442.7-1093.2c-21.2-84.7-34.6-155.9-32.7-157.8c1.9-1.9,73.1,13.5,155.9,34.6c121.3,30.8,198.2,38.5,356.1,32.7c179-5.8,217.5-13.5,333-67.4c367.6-173.2,554.3-583.2,438.8-964.2c-103.9-342.6-438.8-600.5-896.9-689c-134.7-26.9-263.7-32.7-567.8-30.8l-394.6,1.9L5548.7-440.5L3354.6-2632.7l13.5-225.2c15.4-256-9.6-660.2-50-816c-102-384.9-306-656.3-598.6-791.1c-80.8-36.6-129-44.3-298.3-44.3c-186.7,0-211.7,3.8-333,61.6c-167.5,78.9-323.3,234.8-398.4,394.6c-100.1,215.6-109.7,448.4-28.9,746.8c15.4,57.7,25,105.9,23.1,107.8c-1.9,1.9-77-13.5-167.5-34.6c-248.3-57.7-504.3-44.3-679.4,36.6c-171.3,80.8-323.3,232.9-404.2,404.2c-57.7,121.3-61.6,146.3-61.6,333c0,188.6,3.9,211.7,63.5,334.9c117.4,250.2,392.6,460,716,548.5c205.9,55.8,542.8,82.8,843,67.4l257.9-13.5L4445.9,670L6638,2862.2l-11.5,279.1c-28.9,646.7,86.6,1074,365.7,1358.8c190.5,192.5,354.1,259.8,617.8,252.1C7762.1,4748.4,7802.5,4738.8,7908.3,4686.8z"
35+
/>
36+
</g>
37+
</g>
38+
</Icon>
39+
);
40+
41+
export default LoadingBone;

0 commit comments

Comments
 (0)