-
Notifications
You must be signed in to change notification settings - Fork 62
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
React Series Challenge - Daniel #66
base: master
Are you sure you want to change the base?
Changes from all commits
677680e
3506f63
ca33928
339d6ec
a1a18ec
566dd9d
4fdebab
6081ad2
2988b95
91bbb95
491e6d6
f7d2b94
cf52e09
3e5561d
bb0d7b1
38556fe
0d5b735
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
REACT_APP_GIPHY_API_KEY = NYBl3G1fuM3PcJWfeAv0wSS6fuHAJhIK |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
/coverage/ | ||
/dist/ | ||
/node_modules/ | ||
.env |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import styled from "styled-components"; | ||
|
||
const Container = styled.div` | ||
display: flex; | ||
flex-direction: column; | ||
flex: 1; | ||
`; | ||
|
||
|
||
export { Container }; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import React from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
import App from './App'; | ||
|
||
it('renders without crashing', () => { | ||
const div = document.createElement('div'); | ||
ReactDOM.render(<App />, div); | ||
ReactDOM.unmountComponentAtNode(div); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import React from "react"; | ||
import { BrowserRouter as Router, Route, Switch } from "react-router-dom"; | ||
import Home from "./pages/Home"; | ||
import Favorites from "./pages/Favorites"; | ||
import Navbar from "./components/Navigation/Navbar"; | ||
|
||
import { Container } from "./App.style"; | ||
import NotFound from "./pages/NotFound"; | ||
|
||
const Routes = () => { | ||
return( | ||
<Router> | ||
<Container> | ||
<Navbar /> | ||
<Switch> | ||
<Route exact path="/" component={Home} /> | ||
<Route path="/favorites" component={Favorites} /> | ||
<Route component={NotFound} /> | ||
</Switch> | ||
</Container> | ||
</Router> | ||
); | ||
} | ||
|
||
export default Routes; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const ADD_FAVORITE_GIF = "ADD_FAVORITE_GIF"; | ||
const GET_FAVORITE_SEARCH_GIFS = "GET_FAVORITE_SEARCH_GIFS"; | ||
|
||
export default { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing action creators. |
||
types: { | ||
ADD_FAVORITE_GIF, | ||
GET_FAVORITE_SEARCH_GIFS | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
const GET_FAVORITE_SEARCH_GIFS = "GET_FAVORITE_SEARCH_GIFS"; | ||
|
||
const getSearchFavoriteGifs = (payload = {}) => ({ type: GET_FAVORITE_SEARCH_GIFS, payload }); | ||
|
||
export default { | ||
types: { | ||
GET_FAVORITE_SEARCH_GIFS | ||
}, | ||
creators: { | ||
getSearchFavoriteGifs | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const FETCH_SEARCH_GIFS = "FETCH_SEARCH_GIFS"; | ||
const GET_SEARCH_GIFS = "GET_SEARCH_GIFS"; | ||
|
||
export default { | ||
types: { | ||
FETCH_SEARCH_GIFS, | ||
GET_SEARCH_GIFS | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const FETCH_TRENDING_GIFS = "FETCH_TRENDING_GIFS"; | ||
const GET_TRENDING_GIFS = "GET_TENDING_GIFS"; | ||
|
||
export default { | ||
types: { | ||
FETCH_TRENDING_GIFS, | ||
GET_TRENDING_GIFS | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import React from "react"; | ||
import { connect } from "react-redux"; | ||
import { Button } from "./FavoriteButtonStyled"; | ||
|
||
const AddTransactionButton = ({ gif, addFavoriteGif, favorite }) => ( | ||
<Button favorite={favorite} onClick={() => addFavoriteGif(gif)}> | ||
<i className="fas fa-heart" /> | ||
</Button> | ||
); | ||
|
||
const mapDispatchToProps = dispatch => { | ||
return { | ||
addFavoriteGif: gif => dispatch({ type: "ADD_FAVORITE_GIF", payload: gif }) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With creators you could have done something like: const mapDispatchToProps = dispatch => bindActionCreators({
addFavoriteGif: creators.addFavoriteGif,
}, dispatch); or const mapDispatchToProps = { addFavoriteGif: creators.addFavoriteGif }; |
||
}; | ||
}; | ||
|
||
export default connect( | ||
null, | ||
mapDispatchToProps | ||
)(AddTransactionButton); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import React from 'react'; | ||
import { mount, shallow } from 'enzyme'; | ||
import configureStore from 'redux-mock-store'; | ||
import FavoriteButton from "./FavoriteButton"; | ||
|
||
|
||
describe('test', () => { | ||
const initialState = { }; | ||
const mockStore = configureStore(); | ||
let store,wrapper; | ||
|
||
beforeEach(() => { | ||
let props = { | ||
favorite: true, | ||
gif: { | ||
id : "01", | ||
images: { | ||
url: "https://media0.giphy.com/media/4TgL0taO3uU5H6kKcQ/giphy-preview.webp" | ||
} | ||
} | ||
}; | ||
store = mockStore(initialState) | ||
wrapper = mount(shallow(<FavoriteButton store={store} {...props} />).get(0)); | ||
}) | ||
///// Test button onClick | ||
test("Button on click", ()=> { | ||
const button = wrapper.find("button").first() | ||
button.simulate("click") | ||
}) | ||
}); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import styled from "styled-components"; | ||
|
||
const Button = styled.button` | ||
position: absolute; | ||
right: 2px; | ||
top: 5px; | ||
background-color: transparent; | ||
color: ${props => props.favorite ? "#EF4748" : "#ccc" }; | ||
font-size: 2.5rem | ||
font-weight: bold; | ||
border: none; | ||
&:focus { | ||
outline: 0; | ||
} | ||
cursor: pointer | ||
|
||
&:hover { | ||
transform: translateY(-3px); | ||
} | ||
`; | ||
|
||
export { Button }; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import React from "react"; | ||
import { connect } from "react-redux"; | ||
import FavoriteButton from "../FavoriteButton/FavoriteButton"; | ||
import {ItemGif, Image } from "../ListGifs/GifItemStyle"; | ||
|
||
const FavoritesGifs = ({ favoriteGifs, searchFavoriteGifs }) => { | ||
let filterFavoriteGifs = null; | ||
if (Object.keys(searchFavoriteGifs).length) { | ||
filterFavoriteGifs = Object.keys(favoriteGifs) | ||
.filter(key => searchFavoriteGifs.includes(key)) | ||
.reduce((obj, key) => { | ||
obj[key] = favoriteGifs[key]; | ||
return obj | ||
}, {}); | ||
} | ||
return( | ||
Object.keys(filterFavoriteGifs || favoriteGifs).map(key => ( | ||
<ItemGif key={key}> | ||
<Image src={favoriteGifs[key].images.preview_webp.url} /> | ||
<FavoriteButton gif={favoriteGifs[key]} key={favoriteGifs[key].id} favorite /> | ||
</ItemGif> | ||
)) | ||
) | ||
}; | ||
|
||
const mapStateToProps = ({ favoriteGifs, searchFavoriteGifs }) => ({ | ||
favoriteGifs, | ||
searchFavoriteGifs | ||
}); | ||
|
||
export default connect( | ||
mapStateToProps, | ||
null | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you are not using |
||
)(FavoritesGifs); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import FavoriteGifs from "./FavoriteGifs"; | ||
import { shallow } from 'enzyme'; | ||
import configureStore from 'redux-mock-store' | ||
import React from 'react'; | ||
|
||
describe('Todo component renders the list of trending gifs', () => { | ||
const favoriteGifs = [ | ||
{ | ||
id: "01", | ||
images: { | ||
preview_webp: { | ||
url: "https://media0.giphy.com/media/4TgL0taO3uU5H6kKcQ/giphy-preview.webp" | ||
} | ||
} | ||
}, | ||
{ | ||
id: "02", | ||
images: { | ||
preview_webp: { | ||
url: "https://media0.giphy.com/media/4TgL0taO3uU5H6kKcQ/giphy-preview.webp" | ||
} | ||
} | ||
}]; | ||
const initialState = { favoriteGifs, searchFavoriteGifs: null }; | ||
const mockStore = configureStore(); | ||
let store,container; | ||
|
||
beforeEach(()=>{ | ||
store = mockStore(initialState) | ||
container = shallow(<FavoriteGifs store={store} /> ) | ||
}); | ||
it('+++ render the DUMB component', () => { | ||
expect(container.length).toEqual(1) | ||
}); | ||
|
||
it('+++ contains output', () => { | ||
expect(container.prop('output')).toEqual(initialState.output) | ||
}); | ||
|
||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import React from "react"; | ||
import FavoriteButton from "../FavoriteButton/FavoriteButton"; | ||
import { ItemGif, Image } from "./GifItemStyle"; | ||
|
||
const GifItem = ({ gif, favoriteGifs }) => | ||
<ItemGif> | ||
<Image src={gif.images.preview_webp.url} alt="Gif item" /> | ||
<FavoriteButton gif={gif} favorite ={favoriteGifs[gif.id]} /> | ||
</ItemGif>; | ||
|
||
export default GifItem; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import styled from "styled-components"; | ||
|
||
const ItemGif = styled.div` | ||
position: relative; | ||
` | ||
|
||
const Image = styled.img` | ||
height: 200px; | ||
width: 200px; | ||
padding: 0.5rem; | ||
display: flex; | ||
object-fit: cover; | ||
justify-content: flex-end; | ||
|
||
`; | ||
|
||
export { ItemGif, Image }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this specific exercise you may not see the value but you are declaring the routes in a semi static way on a separate file. Remember that one of the key takeaways of react router 4 is integrating the routes through the component views dynamically, as your application grows and become more complex maintaining this static definition of routes may not be the best approach