Skip to content
This repository was archived by the owner on Jan 2, 2020. It is now read-only.
Open
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
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"muicss": "^0.9.12",
"react": "^15.4.2",
"react-dom": "^15.4.2",
"react-rating": "^0.6.5"
"react-rating": "^0.6.5",
"axios": "^0.16.1"
},
"devDependencies": {
"gh-pages": "^0.12.0",
Expand Down
6 changes: 6 additions & 0 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,9 @@
.App .overlay .add-movie-container .add-movie-form .mui-textfield>textarea:focus~label {
color: #FF424F;
}

.fit {
object-fit: cover;
object-position: top;
width: 100%;
}
99 changes: 19 additions & 80 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import React, { Component } from 'react';
import Flexbox from 'flexbox-react';
import Form from 'muicss/lib/react/form';
import Input from 'muicss/lib/react/input';
import Button from 'muicss/lib/react/button';
import Rating from 'react-rating';
import AddMovie from './components/addMovie/addMovie';

import './App.css';

Expand All @@ -12,8 +9,6 @@ class App extends Component {
super(props);
this.state = {
movies: {},
showAddMovie: false,
addMovie: {},
};
}

Expand All @@ -24,41 +19,8 @@ class App extends Component {
});
}

addMovie() {
this.setState({
showAddMovie: true,
});
}

addAttr(type, obj) {
const update = {};
update[type] = obj.currentTarget.value;
this.setState({
addMovie: Object.assign({}, this.state.addMovie, update)
});
}

setRating(rating) {
this.addAttr('rating', {
currentTarget: {
value: rating,
},
});
}

submitNewMovie(e) {
e.preventDefault();
const updateMovie = {};
updateMovie[Object.keys(this.state.movies).length + 1] = this.state.addMovie;
const movies = Object.assign({}, this.state.movies, updateMovie);
this.setState({
movies: movies,
addMovie: {},
showAddMovie: false,
});
window.localStorage.setItem('movie-collection', JSON.stringify({
movies: movies
}));
update(movies) {
this.setState({ movies })
}

render() {
Expand All @@ -74,7 +36,13 @@ class App extends Component {
movies.push(
<Flexbox key={`movie-${movieId}`} className="movie" flexDirection="column">
<div className="movie-rating">{movie.rating}</div>
<Flexbox className="movie-poster"></Flexbox>
<Flexbox className="movie-poster">
{movie.poster &&
<img src={movie.poster}
className="fit"
alt={movie.title}/>
}
</Flexbox>
<Flexbox className="movie-title" flexDirection="row">
{movie.title}
</Flexbox>
Expand All @@ -99,12 +67,12 @@ class App extends Component {
</div>
</Flexbox>
<a href="#add"
className="add-movie"
onClick={(e) => {
className="add-movie"
onClick={(e) => {
e.preventDefault();
this.addMovie();
this.child.addMovie();
}}
>
>
<i className="material-icons">add</i>
</a>
</Flexbox>
Expand All @@ -124,40 +92,11 @@ class App extends Component {
</Flexbox>
</Flexbox>
</Flexbox>
<Flexbox className="overlay" style={{display: (this.state.showAddMovie === true ? 'flex' : 'none')}}>
<Flexbox className="add-movie-container">
<Form
onSubmit={this.submitNewMovie.bind(this)}
className="add-movie-form"
>
<legend>Add Movie</legend>
<Input ref="title" label="Title" floatingLabel={true} onChange={this.addAttr.bind(this, 'title')} />
<Input ref="director" label="Director" floatingLabel={true} onChange={this.addAttr.bind(this, 'director')} />
<Input ref="year" label="Year of Release" floatingLabel={true} onChange={this.addAttr.bind(this, 'year')} />
<div className="mui-textfield" style={{marginBottom: 0}}>
<div style={{marginBottom: 15}}>Rating</div>
<Rating
initialRate={this.state.addMovie.rating || 0}
onClick={this.setRating.bind(this)}
/>
</div>
<div style={{textAlign: 'right'}}>
<Button
variant="flat"
onClick={(e) => {
e.preventDefault();
this.setState({
showAddMovie: false,
});
}}
>
Cancel
</Button>
<Button variant="flat" color="primary">Submit</Button>
</div>
</Form>
</Flexbox>
</Flexbox>
<AddMovie
ref={instance => { this.child = instance; }}
movies={this.state.movies}
update={this.update.bind(this)}
/>
</Flexbox>
);
}
Expand Down
153 changes: 153 additions & 0 deletions src/components/addMovie/addMovie.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import React, { Component } from 'react';
import Flexbox from 'flexbox-react';
import Form from 'muicss/lib/react/form';
import Input from 'muicss/lib/react/input';
import Button from 'muicss/lib/react/button';
import Rating from 'react-rating';
import axios from 'axios';

class AddMovie extends Component {
constructor(props) {
super(props);
this.state = {
showAddMovie: false,
addMovie: {},
options: [],
};
}

submitNewMovie(e) {
e.preventDefault();
const updateMovie = {};
updateMovie[Object.keys(this.props.movies).length + 1] = this.state.addMovie;
const movies = Object.assign({}, this.props.movies, updateMovie);
this.setState({
addMovie: {},
showAddMovie: false,
});
this.props.update(movies);
window.localStorage.setItem('movie-collection', JSON.stringify({
movies: movies
}));
}

addAttr(type, obj) {
const update = {};
update[type] = obj.currentTarget.value;
this.setState({
addMovie: Object.assign({}, this.state.addMovie, update)
});

if (type === "title" && update[type].length > 2) {
this.autoComplete(update);
}
}

autoComplete(update) {
axios.get('https://api.themoviedb.org/3/search/movie', {
params: {
api_key: 'd4b2e5e0e5a46c592a05101bdc4d70fe',
page: 1,
query: update.title,
}
})
.then((response) => {
this.setState({
options: response.data.results
});

const movie = (response.data.results.length > 0) ? response.data.results[0] : false;

if (movie) {
update.year = (movie.release_date) ? movie.release_date.split("-")[0] : "";
update.director = (movie.director) ? movie.director : "No director in DB";
update.rating = (movie.vote_average) ? movie.vote_average * 5 / 10 : 0;
update.poster = (movie.poster_path) ? 'http://image.tmdb.org/t/p/w185/' + movie.poster_path : 0;

this.setState({
addMovie: Object.assign({}, this.state.addMovie, update)
});
}
})
.catch((error) => {
console.log(error);
});
}

addMovie() {
this.setState({
showAddMovie: true,
options: [],
});
}

setRating(rating) {
this.addAttr('rating', {
currentTarget: {
value: rating,
},
});
}

render() {
let options = [];
if (this.state.options.length > 0) {
this.state.options.forEach((option, id) => {
options.push(
<option key={id} value={option.title}></option>
);
})
}

return (
<Flexbox className="overlay" style={{display: (this.state.showAddMovie === true ? 'flex' : 'none')}}>
<Flexbox className="add-movie-container">
<Form
onSubmit={this.submitNewMovie.bind(this)}
className="add-movie-form"
>
<legend>Add Movie</legend>
<Input ref="title" label="Title" floatingLabel={true}
onChange={this.addAttr.bind(this, 'title')}
list="titles"
value={this.state.addMovie.title || ""}/>
<datalist id="titles">
{options}
</datalist>
<Input ref="director" label="Director" floatingLabel={true}
onChange={this.addAttr.bind(this, 'director')}
value={this.state.addMovie.director || ""}/>
<Input ref="year" label="Year of Release" floatingLabel={true}
onChange={this.addAttr.bind(this, 'year')}
value={this.state.addMovie.year || ""}/>

<div className="mui-textfield" style={{marginBottom: 0}}>
<div style={{marginBottom: 15}}>Rating</div>
<Rating
initialRate={this.state.addMovie.rating || 0}
onClick={this.setRating.bind(this)}
value={this.state.addMovie.rating || 0}
/>
</div>
<div style={{textAlign: 'right'}}>
<Button
variant="flat"
onClick={(e) => {
e.preventDefault();
this.setState({
showAddMovie: false,
});
}}
>
Cancel
</Button>
<Button variant="flat" color="primary">Submit</Button>
</div>
</Form>
</Flexbox>
</Flexbox>
);
}
}

export default AddMovie;
31 changes: 31 additions & 0 deletions src/components/addMovie/addMovie.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react-dom/test-utils';
import AddMovie from './addMovie';

it('Component rendering', () => {
const div = document.createElement('div');
ReactDOM.render(<AddMovie/>, div);
});

it('Component autocomplete rendering', () => {
const state = {
options: [
{title: "Movie 1"},
{title: "Movie 2"},
]
};
const testHTML = '<option value="Movie 1"></option><option value="Movie 2"></option>';
const component = TestUtils.renderIntoDocument(
<AddMovie/>
);
component.setState({
options: state.options,
});
const options = TestUtils.findRenderedDOMComponentWithTag(
component, 'datalist'
);
const datalistHTML = ReactDOM.findDOMNode(options).innerHTML;

expect(datalistHTML).toEqual(testHTML);
});