Skip to content

Commit

Permalink
add to favorite function
Browse files Browse the repository at this point in the history
  • Loading branch information
amandeepmittal committed Mar 29, 2021
1 parent ee6c21c commit 21b0dbe
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 27 deletions.
8 changes: 7 additions & 1 deletion reduxWithHooks/App.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import React from 'react';
import {Provider} from 'react-redux';

import {store} from './redux/store';
import RootNavigator from './navigation/RootNavigator';

const App = () => {
return <RootNavigator />;
return (
<Provider store={store}>
<RootNavigator />
</Provider>
);
};

export default App;
19 changes: 17 additions & 2 deletions reduxWithHooks/redux/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import axios from 'axios';

// Define action types
export const GET_MOVIES = 'FETCH_MOVIES';
export const ADD_FAVORITE_ITEM = 'ADD_FAVORITE_ITEM';
export const REMOVE_FAVORITE_ITEM = 'REMOVE_FAVORITE_ITEM';

// Construct a BASE URL for API endpoint
const API_URL = 'https://api.themoviedb.org/3/movie/popular';
Expand All @@ -13,12 +15,11 @@ export const getMovies = () => {
try {
return async dispatch => {
const res = await axios.get(`${BASE_URL}`);
console.log(res.data.results);

if (res.data) {
dispatch({
type: GET_MOVIES,
payload: res.data,
payload: res.data.results,
});
} else {
console.log('Unable to fetch');
Expand All @@ -29,3 +30,17 @@ export const getMovies = () => {
// Add custom logic to handle errors
}
};

export const addFavorite = movie => dispatch => {
dispatch({
type: ADD_FAVORITE_ITEM,
payload: movie,
});
};

export const removeFavorite = movie => dispatch => {
dispatch({
type: REMOVE_FAVORITE_ITEM,
payload: movie,
});
};
11 changes: 10 additions & 1 deletion reduxWithHooks/redux/reducers.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {GET_MOVIES} from './actions';
import {GET_MOVIES, ADD_FAVORITE_ITEM, REMOVE_FAVORITE_ITEM} from './actions';

const initialState = {
movies: [],
Expand All @@ -9,6 +9,15 @@ function moviesReducer(state = initialState, action) {
switch (action.type) {
case GET_MOVIES:
return {...state, movies: action.payload};
case ADD_FAVORITE_ITEM:
return {...state, favorites: [...state.favorites, action.payload]};
case REMOVE_FAVORITE_ITEM:
return {
...state,
favorites: state.favorites.filter(
movie => movie.id !== action.payload.id,
),
};
default:
return state;
}
Expand Down
102 changes: 91 additions & 11 deletions reduxWithHooks/screens/Favorites.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,100 @@
import React from 'react';
import {View, Text, StyleSheet} from 'react-native';
import {Text, View, FlatList, TouchableOpacity, Image} from 'react-native';
import {useSelector, useDispatch} from 'react-redux';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';

import {removeFavorite} from '../redux/actions';

const Favorites = () => {
const {favorites} = useSelector(state => state.moviesReducer);
const dispatch = useDispatch();
const removeFromFavorites = movie => dispatch(removeFavorite(movie));
const handleRemoveFavorite = movie => {
removeFromFavorites(movie);
};

return (
<View style={styles.container}>
<Text>Favorites</Text>
<View style={{flex: 1, marginTop: 44, paddingHorizontal: 20}}>
<Text style={{fontSize: 22}}>Favorites</Text>
<View style={{flex: 1, marginTop: 8}}>
{favorites.length === 0 ? (
<Text style={{color: '#010101', fontSize: 18}}>
Add a movie to the list.
</Text>
) : (
<FlatList
data={favorites}
keyExtractor={item => item.id.toString()}
showsVerticalScrollIndicator={false}
renderItem={({item}) => {
const IMAGE_URL =
'https://image.tmdb.org/t/p/w185' + item.poster_path;

return (
<View style={{marginVertical: 12}}>
<View style={{flexDirection: 'row', flex: 1}}>
<Image
source={{
uri: IMAGE_URL,
}}
resizeMode="cover"
style={{width: 100, height: 150, borderRadius: 10}}
/>
<View style={{flex: 1, marginLeft: 12}}>
<View>
<Text style={{fontSize: 22, paddingRight: 16}}>
{item.title}
</Text>
</View>
<View
style={{
flexDirection: 'row',
marginTop: 10,
alignItems: 'center',
}}>
<MaterialIcons
color="green"
name="thumb-up"
size={32}
/>
<Text
style={{
fontSize: 18,
paddingLeft: 10,
color: '#64676D',
}}>
{item.vote_count}
</Text>
<TouchableOpacity
onPress={() => handleRemoveFavorite(item)}
activeOpacity={0.7}
style={{
marginLeft: 14,
flexDirection: 'row',
padding: 2,
borderRadius: 20,
alignItems: 'center',
justifyContent: 'center',
height: 40,
width: 40,
}}>
<MaterialIcons
color="orange"
size={32}
name="favorite"
/>
</TouchableOpacity>
</View>
</View>
</View>
</View>
);
}}
/>
)}
</View>
</View>
);
};

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});

export default Favorites;
116 changes: 104 additions & 12 deletions reduxWithHooks/screens/Movies.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,112 @@
import React from 'react';
import {View, Text, StyleSheet} from 'react-native';
import React, {useEffect} from 'react';
import {View, Text, FlatList, Image, TouchableOpacity} from 'react-native';
import {useSelector, useDispatch} from 'react-redux';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';

import {getMovies, addFavorite, removeFavorite} from '../redux/actions';

const Movies = () => {
const {movies, favorites} = useSelector(state => state.moviesReducer);
const dispatch = useDispatch();
const fetchMovies = () => dispatch(getMovies());
const addToFavorites = movie => dispatch(addFavorite(movie));
const removeFromFavorites = movie => dispatch(removeFavorite(movie));

useEffect(() => {
fetchMovies();
}, []);

const handleAddFavorite = movie => {
addToFavorites(movie);
};

const handleRemoveFavorite = movie => {
removeFromFavorites(movie);
};

const exists = movie => {
if (favorites.filter(item => item.id === movie.id).length > 0) {
return true;
}

return false;
};

return (
<View style={styles.container}>
<Text>Movies</Text>
<View style={{flex: 1, marginTop: 44, paddingHorizontal: 20}}>
<Text style={{fontSize: 22}}>Popular Movies</Text>
<View style={{flex: 1, marginTop: 12}}>
<FlatList
data={movies}
keyExtractor={item => item.id.toString()}
renderItem={({item}) => {
const IMAGE_URL =
'https://image.tmdb.org/t/p/w185' + item.poster_path;
return (
<View style={{marginVertical: 12}}>
<View style={{flexDirection: 'row', flex: 1}}>
<Image
source={{
uri: IMAGE_URL,
}}
resizeMode="cover"
style={{width: 100, height: 150, borderRadius: 10}}
/>
<View style={{flex: 1, marginLeft: 12}}>
<View>
<Text style={{fontSize: 22, paddingRight: 16}}>
{item.title}
</Text>
</View>
<View
style={{
flexDirection: 'row',
marginTop: 10,
alignItems: 'center',
}}>
<MaterialIcons color="green" name="thumb-up" size={32} />
<Text
style={{
fontSize: 18,
paddingLeft: 10,
color: '#64676D',
}}>
{item.vote_count}
</Text>
<TouchableOpacity
onPress={() =>
exists(item)
? handleRemoveFavorite(item)
: handleAddFavorite(item)
}
activeOpacity={0.7}
style={{
marginLeft: 14,
flexDirection: 'row',
padding: 2,
borderRadius: 20,
alignItems: 'center',
justifyContent: 'center',
height: 40,
width: 40,
}}>
<MaterialIcons
color="orange"
size={32}
name={exists(item) ? 'favorite' : 'favorite-outline'}
/>
</TouchableOpacity>
</View>
</View>
</View>
</View>
);
}}
showsVerticalScrollIndicator={false}
/>
</View>
</View>
);
};

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});

export default Movies;

0 comments on commit 21b0dbe

Please sign in to comment.