Skip to content

Commit 00732b0

Browse files
kamalkamal
authored andcommitted
add movie module
1 parent 8e4e308 commit 00732b0

File tree

18 files changed

+894
-222
lines changed

18 files changed

+894
-222
lines changed

components/Layout.tsx

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import React, { ReactNode } from "react";
22
import Link from "next/link";
33
import Head from "next/head";
44

5+
import { Navbar, Nav } from "react-bootstrap";
6+
57
type Props = {
68
children?: ReactNode;
79
title?: string;
@@ -15,29 +17,30 @@ const Layout = ({ children, title = "This is the default title" }: Props) => (
1517
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
1618
</Head>
1719
<header>
18-
<nav>
19-
<Link href="/">
20-
<a>Home</a>
21-
</Link>{" "}
22-
|{" "}
23-
<Link href="/about">
24-
<a>About</a>
25-
</Link>{" "}
26-
|{" "}
27-
<Link href="/users">
28-
<a>Users List</a>
29-
</Link>{" "}
30-
|{" "}
31-
<Link href="/photos">
32-
<a>Photos List</a>
33-
</Link>{" "}
34-
| <a href="/api/users">Users API</a>
35-
</nav>
20+
<Navbar bg="dark" variant="dark">
21+
<Link href="/" passHref>
22+
<Navbar.Brand>MD</Navbar.Brand>
23+
</Link>
24+
<Nav className="mr-auto">
25+
<Link href="/" passHref>
26+
<Nav.Link>Home</Nav.Link>
27+
</Link>
28+
<Link href="/movies" passHref>
29+
<Nav.Link>Movies</Nav.Link>
30+
</Link>
31+
<Link href="/photos" passHref>
32+
<Nav.Link>Photos</Nav.Link>
33+
</Link>
34+
</Nav>
35+
</Navbar>
3636
</header>
3737
{children}
38-
<footer>
39-
<hr />
40-
<span>I'm here to stay (Footer)</span>
38+
<footer className="footer mt-auto py-3">
39+
<div className="container">
40+
<span className="text-muted">
41+
© 2020, MAROC DEVELOP. All rights reserved.
42+
</span>
43+
</div>
4144
</footer>
4245
</div>
4346
);

next.config.js

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
module.exports = {
2-
// basePath: "/about",
3-
// async rewrites() {
4-
// return [
5-
// {
6-
// source: "/about",
7-
// destination: "/",
8-
// },
9-
// ];
10-
// },
11-
// async redirects() {
12-
// return [
13-
// {
14-
// source: "/about",
15-
// destination: "/",
16-
// permanent: true,
17-
// },
18-
// ];
19-
// },
20-
};
1+
// module.exports = {
2+
// // basePath: "/photos",
3+
// // async rewrites() {
4+
// // return [
5+
// // {
6+
// // source: "/about",
7+
// // destination: "/",
8+
// // },
9+
// // ];
10+
// // },
11+
// async redirects() {
12+
// return [
13+
// {
14+
// source: "/",
15+
// destination: "/photos",
16+
// permanent: true,
17+
// },
18+
// ];
19+
// },
20+
// };
2121

22-
console.log("next config");
22+
// console.log("next config");

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,29 @@
88
"type-check": "tsc"
99
},
1010
"dependencies": {
11+
"bootstrap": "^4.5.2",
1112
"next": "latest",
1213
"next-redux-wrapper": "^6.0.2",
1314
"nprogress": "^0.2.0",
1415
"react": "^16.12.0",
16+
"react-bootstrap": "^1.3.0",
1517
"react-dom": "^16.12.0",
1618
"react-redux": "^7.2.1",
1719
"redux": "^4.0.5",
1820
"redux-logger": "^3.0.6",
1921
"redux-thunk": "^2.3.0"
2022
},
2123
"devDependencies": {
24+
"@fullhuman/postcss-purgecss": "^2.3.0",
2225
"@types/node": "^12.12.21",
26+
"@types/nprogress": "^0.2.0",
2327
"@types/react": "^16.9.16",
2428
"@types/react-dom": "^16.9.4",
2529
"@types/react-redux": "^7.1.9",
2630
"@types/redux-logger": "^3.0.8",
31+
"autoprefixer": "^9.8.6",
2732
"redux-devtools-extension": "^2.13.8",
33+
"tailwindcss": "^1.6.2",
2834
"typescript": "3.7.3"
2935
},
3036
"license": "ISC"

pages/_app.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ import thunkMiddleware from "redux-thunk";
1717
// Store.
1818
import combinedReducer from "../redux/reducers/rootReducer";
1919

20+
// Bootstrap.
21+
import "bootstrap/dist/css/bootstrap.min.css";
22+
23+
// Tailwind css.
24+
import "../styles.css";
25+
2026
// Component App.
2127
function MyApp({ Component, pageProps }: AppProps) {
2228
return <Component {...pageProps} />;
@@ -29,7 +35,10 @@ const bindMiddleware = (middleware: any) => {
2935
// Create loggerMiddleware.
3036
const loggerMiddleware = createLogger();
3137
return composeWithDevTools(
32-
applyMiddleware(...middleware, loggerMiddleware)
38+
applyMiddleware(
39+
...middleware
40+
// loggerMiddleware
41+
)
3342
);
3443
}
3544
return applyMiddleware(...middleware);

pages/index.tsx

Lines changed: 15 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,24 @@
1-
import { connect } from "react-redux";
2-
import { bindActionCreators } from "redux";
3-
import {
4-
decrementCounter,
5-
incrementCounter,
6-
} from "../redux/actions/counterActions";
7-
import { fetchPhotos } from "../redux/actions/photoActions";
8-
91
import Link from "next/link";
102
import Layout from "../components/Layout";
3+
import { Container, Row, Col } from "react-bootstrap";
114

12-
const IndexPage = (props: any) => {
5+
const IndexPage = () => {
136
return (
147
<Layout title="Home | Next.js + TypeScript Example">
15-
<div>
16-
<h1>Index page</h1>
17-
<button onClick={props.incrementCounter}>Increment</button>
18-
<button onClick={props.decrementCounter}>Decrement</button>
19-
<h1>{props.counter}</h1>
20-
</div>
21-
<hr />
22-
<div>
23-
<button
24-
onClick={() => {
25-
props.fetchPhotos();
26-
}}
27-
>
28-
Decrement
29-
</button>
30-
{props.photos.length > 0 ? JSON.stringify(props.photos) : <></>}
31-
</div>
32-
<hr />
33-
<Link href="/about">
34-
<a>About</a>
35-
</Link>
8+
<Container fluid="md" className="mt-2 mb-4">
9+
<Row>
10+
<Col className="text-center">
11+
<h1>MAROC DEVELOP 👋</h1>
12+
<img src="/images/nextjs-redux.png" />
13+
<hr />
14+
<Link href="/movies">
15+
<a>Go to List Movies</a>
16+
</Link>
17+
</Col>
18+
</Row>
19+
</Container>
3620
</Layout>
3721
);
3822
};
3923

40-
const mapDispatchToProps = (dispatch: any) => {
41-
return {
42-
incrementCounter: bindActionCreators(incrementCounter, dispatch),
43-
decrementCounter: bindActionCreators(decrementCounter, dispatch),
44-
fetchPhotos: bindActionCreators(fetchPhotos, dispatch),
45-
};
46-
};
47-
48-
const mapStateToProps = (state: any) => ({
49-
counter: state.counter.value,
50-
photos: state.photo.photos,
51-
});
52-
53-
IndexPage.getInitialProps = async (props: any) => {
54-
const state = props.store.getState();
55-
console.log("state.photo.photos", state.photo.photos);
56-
if (state.photo.photos.length > 0) {
57-
// props.store.dispatch({
58-
// type: "GET_PHOTO",
59-
// payload: props.query.id,
60-
// });
61-
} else {
62-
await props.store.dispatch(fetchPhotos());
63-
}
64-
65-
return {};
66-
};
67-
68-
export default connect(mapStateToProps, mapDispatchToProps)(IndexPage);
24+
export default IndexPage;

pages/movies/[id].tsx

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { connect } from "react-redux";
2+
import { bindActionCreators } from "redux";
3+
import { fetchMovie, findMovie } from "../../redux/actions/movieActions";
4+
5+
import Link from "next/link";
6+
import Layout from "../../components/Layout";
7+
8+
import { Button, Card, Container, Row, Col } from "react-bootstrap";
9+
10+
const DetailsPage = (props: any) => {
11+
return (
12+
<Layout title="Details | Next.js + TypeScript Example">
13+
<Container fluid="md" className="mt-4 mb-4">
14+
<Row>
15+
<Col xs={12} md={12} className="mb-4">
16+
<Card>
17+
<Card.Header>Details</Card.Header>
18+
<Card.Body>
19+
<Row>
20+
<Col xs={3} md={3}>
21+
<Card.Title>{props.movie.original_title}</Card.Title>
22+
<Card.Img
23+
variant="top"
24+
src={`https://image.tmdb.org/t/p/w300/${props.movie.poster_path}`}
25+
/>
26+
</Col>
27+
<Col xs={6} md={6} className="mt-4">
28+
<p>{props.movie.overview}</p>
29+
</Col>
30+
</Row>
31+
</Card.Body>
32+
<Card.Footer className="text-muted">
33+
<Link href="/movies">
34+
<a>
35+
<Button variant="danger">Go to movies</Button>
36+
</a>
37+
</Link>
38+
</Card.Footer>
39+
</Card>
40+
</Col>
41+
</Row>
42+
</Container>
43+
</Layout>
44+
);
45+
};
46+
47+
const mapDispatchToProps = (dispatch: any) => {
48+
return {
49+
fetchMovie: bindActionCreators(fetchMovie, dispatch),
50+
findMovie: bindActionCreators(findMovie, dispatch),
51+
};
52+
};
53+
54+
const mapStateToProps = (state: any) => ({
55+
movie: state.movie.movie,
56+
});
57+
58+
DetailsPage.getInitialProps = async (props: any) => {
59+
const state = props.store.getState();
60+
if (state.movie.movies.length > 0) {
61+
await props.store.dispatch(findMovie(props.query.id));
62+
} else {
63+
await props.store.dispatch(fetchMovie(props.query.id));
64+
}
65+
66+
return { id: parseInt(props.query.id) };
67+
};
68+
69+
export default connect(mapStateToProps, mapDispatchToProps)(DetailsPage);

pages/movies/index.tsx

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { useState } from "react";
2+
import Link from "next/link";
3+
import { connect } from "react-redux";
4+
import { bindActionCreators } from "redux";
5+
import { fetchMovies } from "../../redux/actions/movieActions";
6+
7+
import Layout from "../../components/Layout";
8+
9+
import { Button, Card, Container, Row, Col } from "react-bootstrap";
10+
11+
const IndexPage = (props: any) => {
12+
return (
13+
<Layout title="Home | Next.js + TypeScript Example">
14+
<Container fluid="md" className="mt-2 mb-4">
15+
<Row>
16+
<Col className="text-center">
17+
<h1>List movies</h1>
18+
</Col>
19+
</Row>
20+
</Container>
21+
<Container fluid="md">
22+
<Row>
23+
{props.movies &&
24+
props.movies.map((m: any, idx: number) => (
25+
<Col key={idx} xs={3} md={3} className="mb-4">
26+
<Card>
27+
<Card.Img
28+
variant="top"
29+
src={`https://image.tmdb.org/t/p/w300/${m.poster_path}`}
30+
/>
31+
<Card.Body className="text-center">
32+
<Card.Title className="text-truncate">
33+
{m.original_title}
34+
</Card.Title>
35+
<Link href="/movies/[id]" as={`/movies/${m.id}`}>
36+
<a>
37+
<Button variant="dark">Details</Button>
38+
</a>
39+
</Link>
40+
</Card.Body>
41+
</Card>
42+
</Col>
43+
))}
44+
</Row>
45+
</Container>
46+
</Layout>
47+
);
48+
};
49+
50+
const mapDispatchToProps = (dispatch: any) => {
51+
return {
52+
fetchMovies: bindActionCreators(fetchMovies, dispatch),
53+
};
54+
};
55+
56+
const mapStateToProps = (state: any) => ({
57+
movies: state.movie.movies,
58+
loading: state.movie.loading,
59+
});
60+
61+
IndexPage.getInitialProps = async (props: any) => {
62+
const state = props.store.getState();
63+
if (state.movie.movies.length === 0) {
64+
await props.store.dispatch(fetchMovies());
65+
}
66+
return {};
67+
};
68+
69+
export default connect(mapStateToProps, mapDispatchToProps)(IndexPage);

0 commit comments

Comments
 (0)