first commit

This commit is contained in:
andres alcocer
2018-11-12 21:57:57 -05:00
commit 21bfb2cb91
36 changed files with 14663 additions and 0 deletions

12
.babelrc Normal file
View File

@@ -0,0 +1,12 @@
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
],
"plugins": [
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-export-namespace-from",
"@babel/plugin-proposal-throw-expressions"
]
}

10
.gitignore vendored Normal file
View File

@@ -0,0 +1,10 @@
# NPM packages folder.
node_modules
# Build files
dist/
# Logs
logs
*.log
npm-debug.log*

11
README.md Normal file
View File

@@ -0,0 +1,11 @@
# React Webpack Starterkit
A simple react starter kit that uses webpack for a custom workflow
## Run server
` npm start `
## Build project
` npm run build `

13944
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

47
package.json Normal file
View File

@@ -0,0 +1,47 @@
{
"name": "webpack-basics",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "webpack-dev-server --open --mode development",
"build": "webpack -p"
},
"author": "Andres Alcocer",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.1.5",
"@babel/plugin-proposal-class-properties": "^7.0.0",
"@babel/plugin-proposal-export-namespace-from": "^7.0.0",
"@babel/plugin-proposal-throw-expressions": "^7.0.0",
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
"@babel/polyfill": "^7.0.0-beta.51",
"@babel/preset-env": "^7.1.5",
"@babel/preset-react": "^7.0.0",
"axios": "^0.18.0",
"babel-loader": "^8.0.4",
"clean-webpack-plugin": "^1.0.0",
"copy-webpack-plugin": "^4.6.0",
"css-loader": "^1.0.1",
"extract-text-webpack-plugin": "^3.0.2",
"file-loader": "^2.0.0",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
"image-webpack-loader": "^4.5.0",
"mini-css-extract-plugin": "^0.4.4",
"node-sass": "^4.10.0",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"prop-types": "^15.6.2",
"react": "^16.6.1",
"react-dom": "^16.6.1",
"react-router-dom": "^4.3.1",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"svg-inline-loader": "^0.8.0",
"svg-react-loader": "^0.4.6",
"uglifyjs-webpack-plugin": "^2.0.1",
"webpack": "^4.25.1",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.10"
}
}

View File

@@ -0,0 +1,27 @@
import React from 'react';
const footer = () => (
<footer className="footer">
<div className="footer__heading">icons</div>
<div className="footer__container">
<div className="footer__container--description">desc 1</div>
<div className="footer__container--description">desc 2</div>
<div className="footer__container--description">desc 3</div>
<div className="footer__container--description">desc 4</div>
<div className="footer__container--description">desc 5</div>
<div className="footer__container--description">desc 6</div>
<div className="footer__container--description">desc 7</div>
<div className="footer__container--description">desc 8</div>
<div className="footer__container--description">desc 9</div>
<div className="footer__container--description">desc 10</div>
<div className="footer__container--description">desc 11</div>
<div className="footer__container--description">desc 12</div>
<div className="footer__container--description">desc 13</div>
</div>
<div className="footer__serviceCode">service code</div>
<div className="footer__copyright">copyright</div>
</footer>
);
export default footer;

View File

@@ -0,0 +1,9 @@
import React from 'react';
const header = () => (
<header className="header">
Header
</header>
);
export default header;

View File

@@ -0,0 +1,20 @@
import React from 'react';
const movieRow = (props) => (
<div className="movie">
<div className="movie__column-poster">
<img src={props.movie.posterSrc} alt="" className="movie__poster" />
</div>
<div className={"movie__column-overview " + (props.val % 2 == 0 ? 'even' : 'odd')}>
<h1 className="movie__column-overview-heading">{props.movie.title}</h1>
<p className="movie__column-overview-text">{props.movie.overview}</p>
<a className="movie__column-overview-btn"
onClick={() => { window.location.href = "https://www.themoviedb.org/movie/" + props.movie.id; }}>
view</a>
</div>
</div>
);
export default movieRow;

View File

@@ -0,0 +1,11 @@
import React from 'react';
import { NavLink } from 'react-router-dom';
const navigationItem = (props) => (
<NavLink className="navigation__container-link" exact={props.exact}
to={props.link}>{props.children}</NavLink>
)
export default navigationItem;

View File

@@ -0,0 +1,24 @@
import React from 'react';
import NavigationItem from './NavigationItem/NavigationItem';
const navigationItems = props => (
<ul className="navigation__container">
<NavigationItem link="/" exact>Netflix</NavigationItem>
<NavigationItem link="/">Home</NavigationItem>
<NavigationItem link="/">TV Shows</NavigationItem>
<NavigationItem link="/">Movies</NavigationItem>
<NavigationItem link="/">Recently Added</NavigationItem>
<NavigationItem link="/">My List</NavigationItem>
<div className="navigation__container--left">
<input
placeholder="Search movie..."
type="text" />
{/* <p>hello</p>
<p>hello</p> */}
</div>
</ul>
);
export default navigationItems;

View File

@@ -0,0 +1,16 @@
import React from 'react';
const search = (props) => (
<div className="search">
<input
onChange={props.onSearch}
type="text"
placeholder="Search movie..."
className="search__input"/>
</div>
);
export default search;

62
src/containers/App.js Normal file
View File

@@ -0,0 +1,62 @@
import React, { Component } from 'react';
import axios from 'axios';
import Layout from './Layout/Layout';
import MovieRow from '../components/MovieRow/MovieRow';
class App extends Component {
state = {
// an array that will hold all of our movies component
rows: []
}
makeAipCall = (searchItem) => {
const url = "https://api.themoviedb.org/3/search/movie?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&page=1&query=" + searchItem;
axios.get(url)
.then(res => {
// extract the data from json object
const movies = res.data.results;
// Holds our movieComponent.
let movieRows = [];
let total = 0;
movies.forEach((movie) => {
// manually build our image url and set it on the movie object
movie.posterSrc = "https://image.tmdb.org/t/p/w185" + movie.poster_path;
total+= 1;
// pass in the movie object to our MovieRow component and keep it in a variable called
// movieComponent
const movieComponent = <MovieRow
val={total}
key={movie.id}
movie={movie}
/>
// push our movieComponent to our movieRows array;
movieRows.push(movieComponent);
})
// update state
this.setState({ rows: movieRows });
}).catch(error => {
console.log(error);
});
}
// get the user input and pass it to the makeAPICall function
searchHandler = (event) => {
const searchItem = event.target.value;
this.makeAipCall(searchItem);
}
render() {
return (
<div>
<Layout />
{/* <Search onSearch={this.searchHandler}/>
{this.state.rows} */}
</div>
);
}
}
export default App;

View File

@@ -0,0 +1,35 @@
import React, { Component } from 'react';
import Navigation from '../Navigation/Navigation';
import Header from '../../components/Header/Header';
import MovieShowcase from '../MovieShowcase/MovieShowcase';
import MovieOriginals from '../MovieOriginals/MovieOriginals';
import Footer from '../../components/Footer/Footer';
import { BrowserRouter } from "react-router-dom";
// < Navigation />
// <Header />
// <MovieShowcase />
// <MovieOriginals />
// <Footer />
class Layout extends Component {
render() {
return (
<BrowserRouter>
<div className="container">
<Navigation />
<Header />
<MovieShowcase />
<MovieOriginals />
<Footer />
</div>
</BrowserRouter>)
}
}
export default Layout;

View File

@@ -0,0 +1,22 @@
import React, { Component } from 'react';
class MovieOriginals extends Component {
render() {
return (
<div className="movieOriginals">
<h1>Netflix Originals</h1>
<div className="movieOriginals__container">
<div className="movieOriginals__container--movie">movie 1</div>
<div className="movieOriginals__container--movie">movie 2</div>
<div className="movieOriginals__container--movie">movie 3</div>
<div className="movieOriginals__container--movie">movie 4</div>
<div className="movieOriginals__container--movie">movie 5</div>
<div className="movieOriginals__container--movie">movie 6</div>
</div>
</div>
);
}
}
export default MovieOriginals;

View File

@@ -0,0 +1,31 @@
import React, { Component } from "react";
class MovieShowcase extends Component {
render() {
return (
<div className="movieShowcase">
<h1 className="movieShowcase__heading">New Releases</h1>
<div className="movieShowcase__container">
<div className="movieShowcase__container--movie">movie 1</div>
<div className="movieShowcase__container--movie">movie 2</div>
<div className="movieShowcase__container--movie">movie 3</div>
<div className="movieShowcase__container--movie">movie 4</div>
<div className="movieShowcase__container--movie">movie 5</div>
<div className="movieShowcase__container--movie">movie 6</div>
</div>
<h1 className="movieShowcase__heading">Trending Now</h1>
<div className="movieShowcase__container">
<div className="movieShowcase__container--movie">movie 1</div>
<div className="movieShowcase__container--movie">movie 2</div>
<div className="movieShowcase__container--movie">movie 3</div>
<div className="movieShowcase__container--movie">movie 4</div>
<div className="movieShowcase__container--movie">movie 5</div>
<div className="movieShowcase__container--movie">movie 6</div>
</div>
</div>
)
}
}
export default MovieShowcase;

View File

@@ -0,0 +1,38 @@
import React, { Component } from 'react';
import NavigationItems from '../../components/NavigationItems/NavigationItems';
class navigation extends Component {
state = {
scrolling: false
}
componentDidMount() {
window.addEventListener('scroll', this.handleScroll);
}
componentWillUnmount() {
window.removeEventListener('scroll', this.handleScroll);
}
handleScroll = (event) => {
if (window.scrollY === 0 ) {
this.setState({ scrolling: false });
}
else if (window.scrollY > 50) {
this.setState({ scrolling: true });
}
}
render () {
return (
<nav className={"navigation " + (this.state.scrolling ? "black" : "")} >
<NavigationItems />
</nav>
)
}
}
export default navigation;

15
src/index.html Normal file
View File

@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Netflix Clone</title>
</head>
<body>
<div id="app"></div>
</body>
</html>

15
src/index.js Normal file
View File

@@ -0,0 +1,15 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from "react-router-dom";
import App from './containers/App';
import './static/sass/style.scss';
const app = (
<BrowserRouter>
<App />
</BrowserRouter>
);
ReactDOM.render(app, document.getElementById('app'));

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 MiB

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="251px" height="251px" viewBox="0 0 251 251" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 49.3 (51167) - http://www.bohemiancoding.com/sketch -->
<title>Slice 1</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="musica-searcher" fill="#FFFFFF" fill-rule="nonzero">
<path d="M244.186,214.604 L189.807,160.226 C189.518,159.937 189.179,159.735 188.877,159.466 C199.577,143.235 205.822,123.806 205.822,102.912 C205.822,46.075 159.747,0 102.911,0 C46.075,0 0,46.075 0,102.911 C0,159.746 46.074,205.822 102.91,205.822 C123.805,205.822 143.233,199.577 159.464,188.877 C159.733,189.178 159.934,189.517 160.223,189.806 L214.603,244.186 C222.772,252.354 236.016,252.354 244.186,244.186 C252.354,236.017 252.354,222.773 244.186,214.604 Z M102.911,170.146 C65.777,170.146 35.675,140.044 35.675,102.911 C35.675,65.777 65.778,35.675 102.911,35.675 C140.043,35.675 170.146,65.778 170.146,102.911 C170.146,140.044 140.043,170.146 102.911,170.146 Z" id="Shape"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

View File

@@ -0,0 +1,14 @@
$color-dark: #171818;
$color-background: #141414;
$color-white: rgb(221, 218, 218);
$color-green: #1cb831;
$color-red: #e21221;
$color-dark-blue: #082452;
$color-light-blue: rgb(15, 61, 129);
$color-light-blue-2: #2b2da5;
$color-purple: #782da3;

View File

@@ -0,0 +1,2 @@

View File

@@ -0,0 +1,61 @@
/* GLOBAL RESET */
:global(html), :global(body), :global(div), :global(span), :global(applet), :global(object), :global(iframe),
:global(h1), :global(h2), :global(h3), :global(h4), :global(h5), :global(h6), :global(p), :global(blockquote), :global(pre),
:global(a), :global(abbr), :global(acronym), :global(address), :global(big), :global(cite), :global(code),
:global(del), :global(dfn), :global(em), :global(img), :global(ins), :global(kbd), :global(q), :global(s), :global(samp),
:global(small), :global(strike), :global(strong), :global(sub), :global(sup), :global(tt), :global(var),
:global(b), :global(u), :global(i), :global(center),
:global(dl), :global(dt), :global(dd), :global(ol), :global(ul), :global(li),
:global(fieldset), :global(form), :global(label), :global(legend),
:global(table), :global(caption), :global(tbody), :global(tfoot), :global(thead), :global(tr), :global(th), :global(td),
:global(article), :global(aside), :global(canvas), :global(details), :global(embed),
:global(figure), :global(figcaption), :global(footer), :global(header), :global(hgroup),
:global(menu), :global(nav), :global(output), :global(ruby), :global(section), :global(summary),
:global(time), :global(mark), :global(audio), :global(video) {
margin: 0;
padding: 0;
border: 0;
vertical-align: baseline;
box-sizing: inherit;
}
/* HTML5 display-role reset for older browsers */
:global(article), :global(aside), :global(details), :global(figcaption), :global(figure),
:global(footer), :global(header), :global(hgroup), :global(menu), :global(nav), :global(section) {
display: block;
}
:global(body) {
line-height: 1;
}
:global(ol), :global(ul) {
list-style: none;
}
:global(blockquote), :global(q) {
quotes: none;
}
:global(blockquote:before), :global(blockquote:after),
:global(q:before), :global(q:after) {
content: '';
content: none;
}
:global(table) {
border-collapse: collapse;
border-spacing: 0;
}
body {
box-sizing: border-box;
background-color: fff;
}
html {
// this defines what 1rem is --> font root size
font-size: 62.5%; // 10/16, 1rem = 10px;
}
// GRID AREA
.container {
display: grid;
grid-template-rows: 47vw min-content min-content min-content;
grid-template-columns: 4% repeat(10, 1fr) 4%;
}

View File

View File

View File

View File

@@ -0,0 +1,14 @@
.movieOriginals {
background-color: pink;
grid-column: 2 / 13;
&__container {
display: grid;
grid-template-columns: repeat(6, 1fr);
column-gap: .5rem;
&--movie {
padding-bottom: 45rem;
}
}
}

View File

@@ -0,0 +1,14 @@
.movieShowcase {
background-color: blue;
grid-column: 2 / 13;
&__container {
display: grid;
grid-template-columns: repeat(6, 1fr);
column-gap: .5rem;
&--movie {
padding: 3rem;
}
}
}

View File

View File

@@ -0,0 +1,14 @@
.footer {
background-color: greenyellow;
grid-column: 2 / 13;
&__container {
display: grid;
grid-template-columns: repeat(4, 1fr);
&--description {
padding: 3rem;
}
}
}

View File

@@ -0,0 +1,5 @@
.header {
padding-top: 4rem;
background-color: rebeccapurple;
grid-column: 1 / 13;
}

View File

@@ -0,0 +1,87 @@
.navigation {
background-color: transparent;
grid-column: 1 / 13;
position: fixed;
width: 100%;
height: 6.7rem;
transition-timing-function: ease-in;
transition: all 1s;
&.black {
background-color: $color-background;
}
&__container {
background-color: transparent;
margin-left: 3.8rem;
display: flex;
height: 6.7rem;
justify-content: flex-start;
align-items: center;
a:first-child {
padding-left: .2%;
color: $color-red;
font-size: 4rem;
}
&-link {
color: #fff;
text-decoration: none;
margin-right: 3rem;
}
&--left {
flex-grow: 1;
color: #fff;
padding-right: 4.6rem;
display: flex;
justify-content: flex-end;
}
}
}
input[type="text"] {
// display: none;
// color: #fff;
border: none;
outline: none;
width: 0px;
padding: 10px;
padding-right: 2rem;
// background: none;
transition: width .5s cubic-bezier(0.000, 0.795, 0.000, 1.000);
cursor: pointer;
}
input[type="text"]:focus:hover {
border-bottom: 1px solid #BBB;
color: #fff;
}
input[type="text"]:focus {
width: 22rem;
z-index: 1;
background-color: #000;
border: 1px solid #fff;
cursor: text;
}
input[type="submit"] {
height: 67px;
width: 63px;
color: red;
text-indent: -10000px;
border: none;
position: absolute;
z-index: 2;
cursor: pointer;
opacity: 0.4;
cursor: pointer;
transition: opacity .4s ease;
}

View File

@@ -0,0 +1,18 @@
@import "abstracts/functions";
@import "abstracts/mixins";
@import "abstracts/variables";
@import "base/animations";
@import "base/base";
@import "base/typography";
@import "base/utils";
@import "components/search";
@import "components/movie";
@import "components/movieOriginals";
@import "components/movieShowcase";
@import "layout/footer";
@import "layout/header";
@import "layout/navigation";

73
webpack.config.js Normal file
View File

@@ -0,0 +1,73 @@
const HtmlWebPackPlugin = require("html-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: "./src/index.js",
output: {
filename: "bundle.js",
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.svg$/,
exclude: /node_modules/,
use: {
loader: 'svg-react-loader'
}
},
{
test: /\.scss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../'
}
},
// 'style-loader',
'css-loader',
'sass-loader'
]
},
{
test: /\.(gif|png|jpe?g)$/i,
use: [
'file-loader',
{
loader: 'image-webpack-loader',
options: {
bypassOnDebug: true, // webpack@1.x
disable: true, // webpack@2.x and newer
},
},
],
}
] // end rules array
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
}),
new CopyWebpackPlugin([{ from: 'src/static/images', to: 'static/images'}]),
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: "main.css"
}),
new CleanWebpackPlugin(['dist'])
]
};