Permalink
Browse files

Step 18: Add functionality to favorite gifs with Firebase

  • Loading branch information...
samanthamichele7 committed Jun 1, 2017
1 parent 82d4f6a commit 73c2a78ca85ecc1ca80e3a5dfc5143d2c15a53da
@@ -5,6 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>React App</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.2/css/font-awesome.min.css">
</head>
<body>
<div id="app"></div>
@@ -4,6 +4,7 @@ import Firebase from 'firebase';
export const OPEN_MODAL = 'OPEN_MODAL';
export const CLOSE_MODAL = 'CLOSE_MODAL';
export const REQUEST_GIFS = 'REQUEST_GIFS';
export const FETCH_FAVORITED_GIFS = 'FETCH_FAVORITED_GIFS';
export const SIGN_OUT_USER = 'SIGN_OUT_USER';
export const AUTH_ERROR = 'AUTH_ERROR';
export const AUTH_USER = 'AUTH_USER';
@@ -30,6 +31,35 @@ export function requestGifs(term = null) {
}
}

export function favoriteGif({selectedGif}) {
const userUid = Firebase.auth().currentUser.uid;
const gifId = selectedGif.id;

return dispatch => Firebase.database().ref(userUid).update({
[gifId]: selectedGif
});
}

export function unfavoriteGif({selectedGif}) {
const userUid = Firebase.auth().currentUser.uid;
const gifId = selectedGif.id;

return dispatch => Firebase.database().ref(userUid).child(gifId).remove();
}

export function fetchFavoritedGifs() {
return function(dispatch) {
const userUid = Firebase.auth().currentUser.uid;

Firebase.database().ref(userUid).on('value', snapshot => {
dispatch({
type: FETCH_FAVORITED_GIFS,
payload: snapshot.val()
})
});
}
}

export function openModal(gif) {
return {
type: OPEN_MODAL,
@@ -1,11 +1,41 @@
import React from 'react';

const GifItem = ({gif, onGifSelect}) => {
return (
<div className="gif-item" onClick={() => onGifSelect(gif)}>
<img src={gif.images.downsized.url} alt="" />
</div>
)
};
class GifItem extends React.Component {
constructor(props) {
super(props);
this.state = { favorited: this.props.isFavorite };
}

favoriteGif() {
this.setState({ favorited: true });
this.props.onFavoriteSelect(this.props.gif);
}

unfavoriteGif() {
this.setState({ favorited: false });
this.props.onFavoriteDeselect(this.props.gif);
}

renderFavoriteHeart = () => {
if (! this.props.isAuthenticated) {
return '';
}

if (this.state.favorited) {
return <i className="favorite fa fa-heart" onClick={() => this.unfavoriteGif()} />;
}

return <i className="favorite fa fa-heart-o" onClick={() => this.favoriteGif()} />;
};

render() {
return (
<div className="gif-item">
{ this.renderFavoriteHeart() }
<img src={this.props.gif.images.downsized.url} onClick={() => this.props.onGifSelect(this.props.gif)} />
</div>
);
}
}

export default GifItem;
@@ -5,7 +5,11 @@ const GifList = (props) => {
const gifItems = props.gifs.map((image) => {
return <GifItem key={image.id}
gif={image}
onGifSelect={props.onGifSelect} />
onGifSelect={props.onGifSelect}
onFavoriteSelect={props.onFavoriteSelect}
onFavoriteDeselect={props.onFavoriteDeselect}
isAuthenticated={props.isAuthenticated}
isFavorite={props.isFavorite} />
});

return (
@@ -1,9 +1,46 @@
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as Actions from '../actions';
import GifList from '../components/GifList';
import GifModal from '../components/GifModal';
import '../styles/app.css';

class Favorites extends React.Component {
componentWillMount() {
this.props.actions.fetchFavoritedGifs();
}

render() {
return <div>My Favorites</div>;
return (
<div>
<GifList gifs={ this.props.gifs }
onGifSelect={ selectedGif => this.props.actions.openModal({selectedGif}) }
onFavoriteSelect={ selectedGif => this.props.actions.favoriteGif({selectedGif}) }
onFavoriteDeselect={ selectedGif => this.props.actions.unfavoriteGif({selectedGif}) }
isAuthenticated={ this.props.authenticated }
isFavorite={true} />
<GifModal modalIsOpen={ this.props.modalIsOpen }
selectedGif={ this.props.selectedGif }
onRequestClose={ () => this.props.actions.closeModal() } />
</div>
);
}
}

export default Favorites;
function mapStateToProps(state) {
return {
authenticated: state.auth.authenticated,
gifs: state.gifs.favorites,
modalIsOpen: state.modal.modalIsOpen,
selectedGif: state.modal.selectedGif
};
}

function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(Actions, dispatch)
};
}

export default connect(mapStateToProps, mapDispatchToProps)(Favorites);
@@ -12,7 +12,13 @@ class Home extends React.Component {
return (
<div>
<SearchBar onTermChange={this.props.actions.requestGifs} />
<GifList gifs={ this.props.gifs } onGifSelect={ selectedGif => this.props.actions.openModal({selectedGif}) } />

<GifList gifs={ this.props.gifs }
onGifSelect={ selectedGif => this.props.actions.openModal({selectedGif}) }
onFavoriteSelect={ selectedGif => this.props.actions.favoriteGif({selectedGif}) }
onFavoriteDeselect={ selectedGif => this.props.actions.unfavoriteGif({selectedGif}) }
isAuthenticated={ this.props.authenticated } />

<GifModal modalIsOpen={ this.props.modalIsOpen }
selectedGif={ this.props.selectedGif }
onRequestClose={ () => this.props.actions.closeModal() } />
@@ -23,6 +29,7 @@ class Home extends React.Component {

function mapStateToProps(state) {
return {
authenticated: state.auth.authenticated,
gifs: state.gifs.data,
modalIsOpen: state.modal.modalIsOpen,
selectedGif: state.modal.selectedGif
@@ -1,7 +1,8 @@
import { REQUEST_GIFS } from '../actions';
import { REQUEST_GIFS, FETCH_FAVORITED_GIFS } from '../actions';

const initialState = {
data: []
data: [],
favorites: []
};

export default function gifs(state = initialState, action) {
@@ -10,6 +11,16 @@ export default function gifs(state = initialState, action) {
return {
...state, data: action.payload.body.data
};
case FETCH_FAVORITED_GIFS:
var arr =[];
for( var i in action.payload ) {
if (action.payload.hasOwnProperty(i)){
arr.push(action.payload[i]);
}
}
return {
...state, favorites: arr
};
default:
return state;
}
@@ -3,12 +3,36 @@
width: 90%;
}

.fa-heart {
color: #a94442;
font-size: 12px;
position: absolute;
right: 0;
top: 0;
}

.fa-heart:hover {
color: #ccc;
}

.fa-heart-o {
font-size: 12px;
position: absolute;
right: 0;
top: 0;
}

.fa-heart-o:hover {
color: #a94442;
}

.gif-item {
box-shadow: 2px 2px 4px 0 #ccc;
box-sizing: border-box;
display: inline-block;
margin: 0 0 1.5em;
padding: 1em;
position: relative;
width: 100%;
}

0 comments on commit 73c2a78

Please sign in to comment.