Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Additionally, if you want to extend your project you might want read the code in
- https://github.com/jorgecortesdev/cf-3-myFlix-client/pull/11/files
- https://github.com/jorgecortesdev/cf-3-myFlix-client/pull/12/files
- https://github.com/jorgecortesdev/cf-3-myFlix-client/pull/13/files
- https://github.com/jorgecortesdev/cf-3-myFlix-client/pull/14/files

#### Branches

Expand Down
54 changes: 46 additions & 8 deletions src/components/MoviesList/MoviesList.jsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,60 @@
import React from 'react';
import { useSelector } from 'react-redux';
import { Container, Row, Col } from 'react-bootstrap';
import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { Row, Col } from 'react-bootstrap';

import { MovieCard } from '../Cards/MovieCard/MovieCard';
import { MoviesFilter } from '../MoviesFilter';

const MoviesList = () => {
import { setMovies } from '../../state/movies/moviesSlice';

export const MoviesList = () => {
const movies = useSelector((state) => state.movies.list);
const { token } = useSelector((state) => state.user);
const filter = useSelector((state) => state.movies.filter)
.trim()
.toLowerCase();

const filteredMovies = movies.filter((movie) => movie.Title.toLowerCase().includes(filter));

const dispatch = useDispatch();

useEffect(() => {
if (!token) {
return;
}

const { MYFLIX_API: myflixApi } = process.env;

fetch(`${myflixApi}/movies`, {
headers: { Authorization: `Bearer ${token}` },
})
.then((response) => response.json())
.then(({ data }) => {
// Please review the response format of the API here
// https://cf-2-movie-api.onrender.com/docs/#/Movie/get_movies
const moviesFromApi = data.map((movie) => {
return {
id: movie._id,
Title: movie.Title,
Description: movie.Description,
ImagePath: movie.ImagePath,
Featured: movie.Featured,
ReleaseYear: movie.ReleaseYear,
MPA: movie.MPA,
IMDb: movie.IMDb,
Genre: movie.Genre,
Director: movie.Director,
Actors: movie.Actors,
Runtime: movie.Runtime,
};
});

dispatch(setMovies(moviesFromApi));
});
}, [token]);

return (
<Container className="flex-grow-1">
<>
<Row className="pt-5 pb-2 d-flex justify-content-center">
<Col md={4}>
<MoviesFilter />
Expand All @@ -31,8 +71,6 @@ const MoviesList = () => {
))
)}
</Row>
</Container>
</>
);
};

export default MoviesList;
14 changes: 14 additions & 0 deletions src/components/ProtectedRoute/ProtectedRoute.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';
import { Navigate } from 'react-router-dom';
import { useSelector } from 'react-redux';

// eslint-disable-next-line react/prop-types
export const ProtectedRoute = ({ children }) => {
const { user } = useSelector((state) => state.user);

if (!user) {
return <Navigate to="/login" replace />;
}

return children;
};
2 changes: 2 additions & 0 deletions src/components/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { ProtectedRoute } from './ProtectedRoute/ProtectedRoute';
export { MoviesList } from './MoviesList/MoviesList';
2 changes: 1 addition & 1 deletion src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<title>myFlix</title>
</head>
<body>
<div id="root" class="d-flex flex-column"></div>
<div id="root"></div>
<script type="module" src="index.jsx"></script>
</body>
</html>
22 changes: 22 additions & 0 deletions src/layouts/AppLayout/AppLayout.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react';
import { Outlet } from 'react-router-dom';
import { Container, Row, Col } from 'react-bootstrap';
import { NavigationBar, FooterBar } from '../../layouts';

export const AppLayout = () => {
return (
<Container>
<Row>
<Col className="d-flex flex-column min-vh-100">
<NavigationBar />

<main className="flex-grow-1">
<Outlet />
</main>

<FooterBar />
</Col>
</Row>
</Container>
);
};
1 change: 1 addition & 0 deletions src/layouts/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { AppLayout } from './AppLayout/AppLayout';
export { NavigationBar } from './NavigationBar/NavigationBar';
export { FooterBar } from './FooterBar/FooterBar';
165 changes: 32 additions & 133 deletions src/pages/HomePage/HomePage.jsx
Original file line number Diff line number Diff line change
@@ -1,143 +1,42 @@
import React, { useEffect } from 'react';
import { Container, Row, Col } from 'react-bootstrap';
import { useSelector, useDispatch } from 'react-redux';
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';

import { NavigationBar, FooterBar } from '../../layouts';
import React from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { LoginPage, SignUpPage, MoviePage, ProfilePage } from '../../pages';

import MoviesList from '../../components/MoviesList';

import { setMovies } from '../../state/movies/moviesSlice';
import { ProtectedRoute, MoviesList } from '../../components';
import { AppLayout } from '../../layouts';

export const HomePage = () => {
const movies = useSelector((state) => state.movies.list);
const { user, token } = useSelector((state) => state.user);

const dispatch = useDispatch();

useEffect(() => {
if (!token) {
return;
}

const { MYFLIX_API: myflixApi } = process.env;

fetch(`${myflixApi}/movies`, {
headers: { Authorization: `Bearer ${token}` },
})
.then((response) => response.json())
.then(({ data }) => {
// Please review the response format of the API here
// https://cf-2-movie-api.onrender.com/docs/#/Movie/get_movies
const moviesFromApi = data.map((movie) => {
return {
id: movie._id,
Title: movie.Title,
Description: movie.Description,
ImagePath: movie.ImagePath,
Featured: movie.Featured,
ReleaseYear: movie.ReleaseYear,
MPA: movie.MPA,
IMDb: movie.IMDb,
Genre: movie.Genre,
Director: movie.Director,
Actors: movie.Actors,
Runtime: movie.Runtime,
};
});

dispatch(setMovies(moviesFromApi));
});
}, [token]);

return (
<BrowserRouter>
<NavigationBar />

<Routes>
<Route
path="/signup"
element={
<>
{user ? (
<Navigate to="/" />
) : (
<Container className="flex-grow-1 d-flex justify-content-center align-items-center">
<Row className="w-100 justify-content-center">
<Col md={5}>
<SignUpPage />
</Col>
</Row>
</Container>
)}
</>
}
/>

<Route
path="/login"
element={
<>
{user ? (
<Navigate to="/" />
) : (
<Container className="flex-grow-1 d-flex justify-content-center align-items-center">
<Row className="w-100 justify-content-center">
<Col md={5}>
<LoginPage />
</Col>
</Row>
</Container>
)}
</>
}
/>

<Route
path="/profile"
element={
<>
{!user ? (
<Navigate to="/login" />
) : (
<Container className="flex-grow-1">
<ProfilePage />
</Container>
)}
</>
}
/>

<Route
path="/movies/:movieId"
element={
<>
{!user ? (
<Navigate to="/" replace />
) : movies.length === 0 ? (
<Container className="flex-grow-1">
<Row className="pt-5 pb-2">
<Col>The list is empty!</Col>
</Row>
</Container>
) : (
<Container className="flex-grow-1">
<Row className="pt-5 pb-2">
<Col md={12}>
<MoviePage />
</Col>
</Row>
</Container>
)}
</>
}
/>

<Route path="/" element={<>{!user ? <Navigate to="/login" replace /> : <MoviesList />}</>} />
<Route element={<AppLayout />}>
<Route path="/signup" element={<SignUpPage />} />
<Route path="/login" element={<LoginPage />} />
<Route
path="/profile"
element={
<ProtectedRoute>
<ProfilePage />
</ProtectedRoute>
}
/>
<Route
path="/movies/:movieId"
element={
<ProtectedRoute>
<MoviePage />
</ProtectedRoute>
}
/>
<Route
path="/"
element={
<ProtectedRoute>
<MoviesList />
</ProtectedRoute>
}
/>
</Route>
</Routes>

<FooterBar />
</BrowserRouter>
);
};
Loading