Skip to content

Commit

Permalink
Add movie rating to movie screens
Browse files Browse the repository at this point in the history
  • Loading branch information
roycechua committed Jun 21, 2021
1 parent b6c8654 commit afb1c2d
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 10 deletions.
16 changes: 14 additions & 2 deletions src/features/home/HomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import theme from '../../themes/themes';
import moment from 'moment';
import Res from '../../themes/Res';
import { AirbnbRating } from 'react-native-ratings';
import { setUserMovieRatings } from '../movies/moviesSlice';

// Props
type HomeScreenNavigationProp = StackNavigationProp<
Expand All @@ -47,10 +48,21 @@ const HomeScreen: React.FC<Props> = (props: Props) => {
const dispatch = useAppDispatch();
const { data } = useAppSelector((state) => state.user);

// search feature
// search feature states
const [searchText, setSearchText] = useState('');
const handleClearSearchText = () => setSearchText('');

// retrieve data
const getUserRatingsQuery = useQuery(
'getUserRatings',
() => API.getRatings({ account_id: data.id, session_id: data.sessionId }),
{ keepPreviousData: true, staleTime: 5000 }
);

useEffect(() => {
dispatch(setUserMovieRatings(getUserRatingsQuery.data?.data.results))
}, [getUserRatingsQuery.isLoading])

// retrieve data
const trendingMoviesQuery = useQuery(
'getTrendingMovies',
Expand Down Expand Up @@ -173,7 +185,7 @@ const HomeScreen: React.FC<Props> = (props: Props) => {
count={5}
// showRating
defaultRating={
item.vote_average - 5
item.vote_average/2
}
size={20}
isDisabled
Expand Down
81 changes: 73 additions & 8 deletions src/features/movies/MovieDetailScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { StackNavigationProp } from '@react-navigation/stack';
import moment from 'moment';
import React, { useLayoutEffect } from 'react';
import React, { useState, useEffect, useLayoutEffect } from 'react';
import {
StyleSheet,
Text,
Expand All @@ -14,10 +14,11 @@ import { AirbnbRating, Rating } from 'react-native-ratings';
import { useMutation, useQueryClient } from 'react-query';
import Spacer from '../../common/components/Spacer';
import { RootStackParamsList } from '../../navigation/MainNavigationContainer';
import { useAppSelector } from '../../redux/hooks';
import { useAppDispatch, useAppSelector } from '../../redux/hooks';
import API from '../../services/API';
import Res from '../../themes/Res';
import theme from '../../themes/themes';
import { getMovieRatings } from './moviesSlice';

// Props
type MovieDetailScreenNavigationProp = StackNavigationProp<
Expand All @@ -37,12 +38,26 @@ const MovieDetailScreen: React.FC<Props> = (props: Props) => {
const { navigation, route } = props;
const { movie, type } = route.params;

// Access the react query client
const queryClient = useQueryClient();

const dispatch = useAppDispatch();
// retrieve user data
const { data } = useAppSelector((state) => state.user);
const { ratings } = useAppSelector((state) => state.movies);

// Access the react query client
const queryClient = useQueryClient();
// rating state
const [rating, setRating] = useState(0);

// assign this movie an existing rating from the user if any record was found
useEffect(() => {
const existingRating = ratings.find((entry) => entry.id == movie.id);
if (existingRating) {
setRating(existingRating.rating);
}
}, [ratings]);

// invoke a dynamic header title depending on the movie title
useLayoutEffect(() => {
navigation.setOptions({
headerTitle: movie.original_title,
Expand Down Expand Up @@ -72,8 +87,37 @@ const MovieDetailScreen: React.FC<Props> = (props: Props) => {
},
});

const addRatingMutation = useMutation(API.addRating, {
onSuccess: () => {
alert('Rating saved');
// Invalidate and refetch
queryClient.invalidateQueries('getUserRatings');
dispatch(getMovieRatings());
},
onError: (error: Error) => {
alert(
`Error encountered while adding movie rating. '${error.message}'`
);
},
});

const deleteRatingMutation = useMutation(API.deleteRating, {
onSuccess: () => {
alert('Movie rating deleted');
setRating(0);
// Invalidate and refetch
queryClient.invalidateQueries('getUserRatings');
dispatch(getMovieRatings());
},
onError: (error: Error) => {
alert(
`Error encountered while deleting movie rating. '${error.message}'`
);
},
});

const handleAddToWatchList = () => {
addToWatchlistMutation.mutate({
addToWatchlistMutation.mutateAsync({
account_id: data.id,
session_id: data.sessionId,
media_type: 'movie',
Expand All @@ -82,6 +126,22 @@ const MovieDetailScreen: React.FC<Props> = (props: Props) => {
});
};

const handleOnFinishRating = (rating : number) => {
setRating(rating);
addRatingMutation.mutateAsync({
media_id: movie.id,
session_id: data.sessionId,
value: rating,
})
}

const handleRemoveRating = () => {
deleteRatingMutation.mutateAsync({
media_id: movie.id,
session_id: data.sessionId,
});
}

return (
<ScrollView style={{ padding: 20 }}>
<View style={{ alignItems: 'center' }}>
Expand Down Expand Up @@ -113,7 +173,7 @@ const MovieDetailScreen: React.FC<Props> = (props: Props) => {
showRating={false}
count={5}
// showRating
defaultRating={movie.vote_average - 5}
defaultRating={movie.vote_average / 2}
size={20}
isDisabled
/>
Expand Down Expand Up @@ -141,10 +201,15 @@ const MovieDetailScreen: React.FC<Props> = (props: Props) => {
showRating={false}
count={5}
// showRating
defaultRating={0}
defaultRating={rating}
size={20}
onFinishRating={(rating) => {}}
onFinishRating={handleOnFinishRating}
/>
{
rating
? <Button color={colors.error} onPress={handleRemoveRating}>Remove Rating</Button>
: null
}
</View>
<Spacer margin={20} />
</ScrollView>
Expand Down

0 comments on commit afb1c2d

Please sign in to comment.