Skip to content

Commit

Permalink
add to favorites
Browse files Browse the repository at this point in the history
  • Loading branch information
MarynaOzkara committed Dec 28, 2023
1 parent 016118e commit a6cb315
Show file tree
Hide file tree
Showing 13 changed files with 149 additions and 50 deletions.
3 changes: 2 additions & 1 deletion public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@
"loginBtn": "Log in"
},
"profile": {
"welcome": "Welcome to your profile,"
"welcome": "Welcome to your profile,",
"favorite": "List of favorite movies"
},
"userMenu": {
"welcome": "Welcome",
Expand Down
3 changes: 2 additions & 1 deletion public/locales/uk/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@
"loginBtn": "Вхід"
},
"profile": {
"welcome": "Ласкаво просимо до профілю,"
"welcome": "Ласкаво просимо до профілю,",
"favorite": "Список улюблених фільмів"
},
"userMenu": {
"welcome": "Раді бачити",
Expand Down
85 changes: 47 additions & 38 deletions src/components/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import { Navigate, Route, Routes } from 'react-router-dom';
import SheredLayout from './SheredLayout/SheredLayout';
import { ThemeProvider } from 'styled-components';
import { GlobalStyles, darkTheme, lightTheme } from 'constants/themes';
import { useSelector } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import { selectTheme } from 'redux/selectors';
import { lazy } from 'react';
import { Suspense, lazy, useEffect } from 'react';
import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import PublicRoute from 'routes/PublicRoutes';
import PrivateRoutes from 'routes/PrivateRoutes';
import { refreshUser } from 'redux/authorization/authOperations';
import Loader from './Loader/Loader';
// import '../i18n';

const Home = lazy(() => import('pages/Home'));
Expand All @@ -23,50 +25,57 @@ const Review = lazy(() => import('components/Review/Review'));

export const App = () => {
const theme = useSelector(selectTheme);
const dispatch = useDispatch();
useEffect(() => {
dispatch(refreshUser());
}, [dispatch]);
return (
<ThemeProvider theme={theme === 'light' ? lightTheme : darkTheme}>
<GlobalStyles />
<>
<Routes>
<Route path="/" element={<SheredLayout />}>
<Route index element={<Home />} />
<Route path="movies" element={<Movies />} />
<Route path="movies/:movieId" element={<MovieDetails />}>
<Route path="trailer" element={<Trailer />} />
<Route path="cast" element={<Cast />} />
<Route path="reviews" element={<Review />} />
<Suspense fallback={<Loader />}>
<Routes>
<Route path="/" element={<SheredLayout />}>
<Route index element={<Home />} />
<Route path="movies" element={<Movies />} />
<Route path="movies/:movieId" element={<MovieDetails />}>
<Route path="trailer" element={<Trailer />} />
<Route path="cast" element={<Cast />} />
<Route path="reviews" element={<Review />} />
</Route>
<Route
path="/signup"
element={
<PublicRoute>
<Signup />
</PublicRoute>
}
/>
<Route
path="/login"
element={
<PublicRoute>
<Login />
</PublicRoute>
}
/>
<Route
path="/profile"
element={
<PrivateRoutes>
<Profile />
</PrivateRoutes>
}
/>

<Route path="*" element={<Navigate to="/" />} />
</Route>
<Route
path="/signup"
element={
<PublicRoute>
<Signup />
</PublicRoute>
}
/>
<Route
path="/login"
element={
<PublicRoute>
<Login />
</PublicRoute>
}
/>
<Route
path="/profile"
element={
<PrivateRoutes>
<Profile />
</PrivateRoutes>
}
/>
</Routes>
</Suspense>

<Route path="*" element={<Navigate to="/" />} />
</Route>
</Routes>
<ToastContainer
position="top-right"
autoClose={5000}
autoClose={3000}
closeOnClick
theme="colored"
/>
Expand Down
30 changes: 30 additions & 0 deletions src/components/Favorite/Favorite.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { IoHeartOutline, IoHeartSharp } from 'react-icons/io5';

import React, { useState } from 'react';
import { FavBtn } from './Favorite.styled';
import { useDispatch } from 'react-redux';
import { addToFavorite } from 'redux/favorites/favoritesSlice';

const Favorite = ({ movie }) => {
const dispatch = useDispatch();
const [isFav, setFav] = useState();

return (
<>
<FavBtn
onClick={() => {
setFav(!isFav);
dispatch(addToFavorite(movie));
}}
>
{!isFav ? (
<IoHeartOutline size={34} color="white" />
) : (
<IoHeartSharp size={34} color="white" />
)}
</FavBtn>
</>
);
};

export default Favorite;
15 changes: 15 additions & 0 deletions src/components/Favorite/Favorite.styled.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import styled from 'styled-components';

export const FavBtn = styled.button`
display: block;
width: 36px;
height: 36px;
background: transparent;
margin-left: auto;
border: 0;
padding: 0;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
`;
2 changes: 1 addition & 1 deletion src/components/Languages/Languages.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const Languages = () => {
{locales.map(({ code, title, country_code }) => (
<FlagItem key={code}>
<FlagBtn
type="submit"
type="button"
onClick={() => {
i18n.changeLanguage(code);
dispatch(setLenguage(code));
Expand Down
5 changes: 5 additions & 0 deletions src/components/MoviesList/MoviesList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import {
Poster,
Title,
PosterWrap,
FavWrap,
} from './MoviesList.styled';
import Favorite from 'components/Favorite/Favorite';

const MoviesList = ({ movies }) => {
const location = useLocation();
Expand All @@ -28,6 +30,9 @@ const MoviesList = ({ movies }) => {

<Title>{title}</Title>
</MovieLink>
<FavWrap>
<Favorite movie={{ id, title, poster_path }} />
</FavWrap>
</MovieItem>
))}
</MovieList>
Expand Down
11 changes: 11 additions & 0 deletions src/components/MoviesList/MoviesList.styled.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const MovieItem = styled.li`
background-color: ${props => props.theme.movieWrap};
border-radius: var(--radii);
overflow: hidden;
position: relative;
@media (min-width: 767px) {
flex-basis: calc((100% - 2 * 15px) / 3);
}
Expand Down Expand Up @@ -58,6 +59,16 @@ export const Poster = styled.img`
/* width: 100%; */
transition: 500ms cubic-bezier(0.4, 0, 0.2, 1);
`;
export const FavWrap = styled.div`
position: absolute;
z-index: 20;
top: 10px;
right: 10px;
width: 36px;
height: 36px;
border-radius: 4px;
background-color: rgba(0, 0, 0, 0.3);
`;
export const Title = styled.h1`
font-size: 18px;
margin-top: 10px;
Expand Down
10 changes: 5 additions & 5 deletions src/pages/Profile.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import MoviesList from 'components/MoviesList/MoviesList';
import { useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux';
import { selectUserName } from 'redux/selectors';
import { selectFavorite } from 'redux/selectors';

const Profile = () => {
const { t } = useTranslation();
const userName = useSelector(selectUserName);
const movies = useSelector(selectFavorite);
return (
<>
<h2>
{t('profile.welcome')} {userName}
</h2>
<h2>{t('profile.favorite')}</h2>
{movies && <MoviesList movies={movies} />}
</>
);
};
Expand Down
20 changes: 20 additions & 0 deletions src/redux/favorites/favoritesSlice.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const { createSlice } = require('@reduxjs/toolkit');

const favoriteSlise = createSlice({
name: 'favorites',
initialState: {
movies: [],
isLoading: false,
},
reducers: {
addToFavorite(state, action) {
state.movies.push(action.payload);
},
deleteFromFavorite(state, action) {
state.movies = state.movies.filter(el => el.id !== action.payload.id);
},
},
});

export const { addToFavorite, deleteFromFavorite } = favoriteSlise.actions;
export const favoriteReducer = favoriteSlise.reducer;
2 changes: 1 addition & 1 deletion src/redux/lenguages/lenguageSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ console.log(currntLang);
const lenguageSlice = createSlice({
name: 'lenguage',
initialState: {
lenguage: currntLang,
lenguage: currntLang || 'en',
},
reducers: {
setLenguage(state, action) {
Expand Down
7 changes: 4 additions & 3 deletions src/redux/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ export const selectSearchIsLoading = state => state.searchMovies.isLoading;
export const selectSearchMoviePage = state => state.searchMovies.page;
export const selectSearchTotalPages = state => state.searchMovies.totalPages;

export const selectTheme = state => state.theme.theme;
export const selectLenguage = state => state.lenguage.lenguage;

export const selectUser = state => state.auth.user;
export const selectEmail = state => state.auth.user.email;
export const selectUserName = state => state.auth.user.name;
export const selectToken = state => state.auth.token;
export const selectIsLoggedIn = state => state.auth.isLoggedIn;
export const selectIsRefreshing = state => state.auth.isRefreshing;

export const selectTheme = state => state.theme.theme;
export const selectLenguage = state => state.lenguage.lenguage;
export const selectFavorite = state => state.favorite.movies;
6 changes: 6 additions & 0 deletions src/redux/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from 'redux-persist';
import { authReducer } from './authorization/authSlice';
import { lenguageReducer } from './lenguages/lenguageSlice';
import { favoriteReducer } from './favorites/favoritesSlice';

const themePersistConfig = {
key: 'theme',
Expand All @@ -28,12 +29,17 @@ const lenguagePresistConfig = {
key: 'lenguage',
storage,
};
const favoritePersistConfig = {
key: 'favorite',
storage,
};
const reduser = combineReducers({
movies: moviesReducer,
searchMovies: searchMoviesReducer,
theme: persistReducer(themePersistConfig, themeReducer),
auth: persistReducer(authPersistCongig, authReducer),
lenguage: persistReducer(lenguagePresistConfig, lenguageReducer),
favorite: persistReducer(favoritePersistConfig, favoriteReducer),
});
export const store = configureStore({
reducer: reduser,
Expand Down

0 comments on commit a6cb315

Please sign in to comment.