From a3689dbef8e889a8d6a44a00f6cab75e637eaf8f Mon Sep 17 00:00:00 2001 From: Phil B Date: Fri, 28 Sep 2018 11:53:02 +0100 Subject: [PATCH 01/12] search component is sending query back to app --- src/components/App.js | 20 ++++++++++++++++++-- src/components/Search.js | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 src/components/Search.js diff --git a/src/components/App.js b/src/components/App.js index 9520f77..d73f60d 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -1,14 +1,30 @@ import React from 'react'; +import Search from './Search' class App extends React.Component { constructor(){ super(); + + this.state = { + query : '', + results : [], + movie : '' + } + + this.receiveQuery = this.receiveQuery.bind(this); + } + + receiveQuery(query) { + this.setState({ + query: query + }) + console.log(query); } render(){ return ( -
- React cinema app +
+
) } diff --git a/src/components/Search.js b/src/components/Search.js new file mode 100644 index 0000000..736217e --- /dev/null +++ b/src/components/Search.js @@ -0,0 +1,37 @@ +import React from 'react'; + +class Search extends React.Component { + + constructor() { + super(); + + this.state= { + query: '' + } + + this.handleSubmit = this.handleSubmit.bind(this); + this.handleChange = this.handleChange.bind(this); + } + + handleChange(event) { + this.setState({ + query: event.target.value + }) + console.log(this.state.query); + } + + handleSubmit(event) { + event.preventDefault(); + this.props.receiveQuery(this.state.query) + } + + render(){ + return
+ +
+ } + +} +export default Search; \ No newline at end of file From cbdd4efa1a820b281dee2684d5cc48937c42c129 Mon Sep 17 00:00:00 2001 From: Phil B Date: Fri, 28 Sep 2018 12:52:43 +0100 Subject: [PATCH 02/12] results built but not passing anything to Result yet --- src/components/App.js | 38 +++++++++++++++++++++++++++++++++++--- src/components/Results.js | 14 ++++++++++++++ 2 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 src/components/Results.js diff --git a/src/components/App.js b/src/components/App.js index d73f60d..9c05028 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -1,5 +1,6 @@ import React from 'react'; import Search from './Search' +import Results from './Results' class App extends React.Component { constructor(){ @@ -8,23 +9,54 @@ class App extends React.Component { this.state = { query : '', results : [], - movie : '' + imbdID : '' } this.receiveQuery = this.receiveQuery.bind(this); + this.receiveMovie = this.receiveMovie.bind(this); + this.createUrl = this.createUrl.bind(this); + this.fetchResults = this.fetchResults.bind(this); + } + + // builds the url for omdb api request + createUrl(typeOfSearch, search) { + const baseURL = "http://www.omdbapi.com/"; + const apiKey = "95869d44"; + const page = "1"; + console.log(`${baseURL}?apikey=${apiKey}&${typeOfSearch}=${search}&page=${page}&type=movie`) + return `${baseURL}?apikey=${apiKey}&${typeOfSearch}=${search}&page=${page}&type=movie` +} + + fetchResults() { + fetch(this.createUrl('s', this.state.query)). + then(response => response.json()). + then(body => { + this.setState({ + results: body.Search + }) + console.log(this.state.results); + }) } receiveQuery(query) { this.setState({ query: query - }) - console.log(query); + },this.fetchResults) + console.log('hello' + query); + } + + receiveMovie(imdbID) { + this.setState({ + imbdID:imbdID + }.this.fetchMovie) + conso9le.log(imdbID) } render(){ return (
+
) } diff --git a/src/components/Results.js b/src/components/Results.js new file mode 100644 index 0000000..eccb12e --- /dev/null +++ b/src/components/Results.js @@ -0,0 +1,14 @@ +import React from 'react'; + +class Results extends React.Component { + render() { + return ( +
    + {this.props.results.map(result => { + {/* */} + })} +
) + } +} + +export default Results; \ No newline at end of file From 0989cc9fa9e0bc10d087e3755ae05e2fc42285ee Mon Sep 17 00:00:00 2001 From: Phil B Date: Fri, 28 Sep 2018 13:52:43 +0100 Subject: [PATCH 03/12] very basic search results being shown - just an unformatted poster --- src/components/Result.js | 15 +++++++++++++++ src/components/Results.js | 6 ++++-- 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 src/components/Result.js diff --git a/src/components/Result.js b/src/components/Result.js new file mode 100644 index 0000000..dd01c5f --- /dev/null +++ b/src/components/Result.js @@ -0,0 +1,15 @@ +import React from 'react'; + +class Result extends React.Component{ + + render() { + return ( +
  • + +
  • + ) + } +} + +export default Result; + diff --git a/src/components/Results.js b/src/components/Results.js index eccb12e..fad54d4 100644 --- a/src/components/Results.js +++ b/src/components/Results.js @@ -1,13 +1,15 @@ import React from 'react'; +import Result from './Result' class Results extends React.Component { render() { return (
      {this.props.results.map(result => { - {/* */} + return })} -
    ) + + ) } } From 1d760c0e0e4dcb68466f524f56a1cd29bbc6633b Mon Sep 17 00:00:00 2001 From: Phil B Date: Fri, 28 Sep 2018 14:51:28 +0100 Subject: [PATCH 04/12] search results working with a little styling. Clicked image being sent back to App component --- src/components/App.js | 8 ++++---- src/components/Result.js | 13 +++++++++++-- src/components/Results.js | 2 +- style.css | 18 ++++++++++++++++++ 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/components/App.js b/src/components/App.js index 9c05028..2aa4a6d 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -46,10 +46,10 @@ class App extends React.Component { } receiveMovie(imdbID) { - this.setState({ - imbdID:imbdID - }.this.fetchMovie) - conso9le.log(imdbID) + // this.setState({ + // imbdID:imbdID + // }.this.fetchMovie) + console.log(imdbID) } render(){ diff --git a/src/components/Result.js b/src/components/Result.js index dd01c5f..65e646a 100644 --- a/src/components/Result.js +++ b/src/components/Result.js @@ -2,10 +2,19 @@ import React from 'react'; class Result extends React.Component{ + constructor() { + super() + this.handleClick = this.handleClick.bind(this); + } + + handleClick (event) { + this.props.receiveMovie(this.props.result) + } + render() { return ( -
  • - +
  • +
  • ) } diff --git a/src/components/Results.js b/src/components/Results.js index fad54d4..13ff54f 100644 --- a/src/components/Results.js +++ b/src/components/Results.js @@ -4,7 +4,7 @@ import Result from './Result' class Results extends React.Component { render() { return ( -
      +
        {this.props.results.map(result => { return })} diff --git a/style.css b/style.css index e69de29..db07a91 100644 --- a/style.css +++ b/style.css @@ -0,0 +1,18 @@ +.results{ + display: flex; + flex-wrap: wrap; + width: 80vw; + margin: 0 auto; + list-style-type: none; + padding: 0; + background: gainsboro; + justify-content: center; +} + +.results__image{ + margin: 0.5rem; + border: 3px solid white; + width: 10rem; + height: 10rem; + object-fit: cover; +} \ No newline at end of file From e4f2599101280c6604fc4dd7f11dd4cf1c0c96db Mon Sep 17 00:00:00 2001 From: Phil B Date: Fri, 28 Sep 2018 16:49:08 +0100 Subject: [PATCH 05/12] can click on images to get more details but styling and data needs to be fine tuned --- src/components/App.js | 14 ++++++------- src/components/Movie.js | 40 +++++++++++++++++++++++++++++++++++++ src/components/Result.js | 5 +++-- src/components/Results.js | 2 +- src/components/Search.js | 2 +- style.css | 42 ++++++++++++++++++++++++++++++++++----- 6 files changed, 89 insertions(+), 16 deletions(-) create mode 100644 src/components/Movie.js diff --git a/src/components/App.js b/src/components/App.js index 2aa4a6d..aebb343 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -9,7 +9,7 @@ class App extends React.Component { this.state = { query : '', results : [], - imbdID : '' + selectedMovie : '' } this.receiveQuery = this.receiveQuery.bind(this); @@ -45,18 +45,18 @@ class App extends React.Component { console.log('hello' + query); } - receiveMovie(imdbID) { - // this.setState({ - // imbdID:imbdID - // }.this.fetchMovie) - console.log(imdbID) + receiveMovie(selectedMovie) { + this.setState({ + selectedMovie:selectedMovie + }) + console.log(selectedMovie) } render(){ return (
        - +
        ) } diff --git a/src/components/Movie.js b/src/components/Movie.js new file mode 100644 index 0000000..054e6a3 --- /dev/null +++ b/src/components/Movie.js @@ -0,0 +1,40 @@ +import React from 'react'; +class Movie extends React.Component { + + constructor() { + super() + this.state = { + movie:'' + } + + this.fetchResults = this.fetchResults.bind(this); + } + + fetchResults(imdbID) { + fetch(`http://www.omdbapi.com/?apikey=95869d44&i=${imdbID}&page=1&type=movie`). + then(response => response.json()). + then(body => { + this.setState({ + movie: body + }) + console.log(body); + }) + } + + componentDidMount() { + this.fetchResults(this.props.imdbID); + } + + render() { + return ( +
          +
        • {this.props.movie.Title}
        • +
        • {this.props.movie.Title}
        • +
        • {this.props.movie.Title}
        • +
        + ) + } + +} + +export default Movie \ No newline at end of file diff --git a/src/components/Result.js b/src/components/Result.js index 65e646a..6469c2f 100644 --- a/src/components/Result.js +++ b/src/components/Result.js @@ -1,4 +1,5 @@ import React from 'react'; +import Movie from './Movie'; class Result extends React.Component{ @@ -8,17 +9,17 @@ class Result extends React.Component{ } handleClick (event) { - this.props.receiveMovie(this.props.result) + this.props.receiveMovie(this.props.result.imdbID) } render() { return (
      • + {this.props.showInfo ? : null}
      • ) } } export default Result; - diff --git a/src/components/Results.js b/src/components/Results.js index 13ff54f..0e76865 100644 --- a/src/components/Results.js +++ b/src/components/Results.js @@ -6,7 +6,7 @@ class Results extends React.Component { return (
          {this.props.results.map(result => { - return + return })}
        ) diff --git a/src/components/Search.js b/src/components/Search.js index 736217e..d41867a 100644 --- a/src/components/Search.js +++ b/src/components/Search.js @@ -28,7 +28,7 @@ class Search extends React.Component { render(){ return
        } diff --git a/style.css b/style.css index db07a91..ad708a8 100644 --- a/style.css +++ b/style.css @@ -1,7 +1,22 @@ +* { + box-sizing: inherit; +} + +body { + box-sizing: border-box; + margin: 0; + font-family: "Open Sans", sans-serif; + min-height: 100vh; + background-color: rgb(216, 238, 245); + background-attachment: fixed; + align-content: center; + } + + .results{ display: flex; flex-wrap: wrap; - width: 80vw; + width: 100%; margin: 0 auto; list-style-type: none; padding: 0; @@ -10,9 +25,26 @@ } .results__image{ - margin: 0.5rem; + margin: 50px; border: 3px solid white; - width: 10rem; - height: 10rem; + width: 350px; + height: 350px; object-fit: cover; -} \ No newline at end of file +} + +input[type="search"] { + background: rgba(196, 196, 196, 0.43); + border: 2px solid white; + box-sizing: border-box; + box-shadow: inset 0px 4px 4px rgba(0, 0, 0, 0.25); + width: 185px; + height: 42px; + font-family: Roboto Slab; + font-style: normal; + font-weight: normal; + line-height: normal; + font-size: 18px; + text-align: center; + color: #FFFFFF; + margin-right:20px; + } \ No newline at end of file From 46523d8e95ae898c865ca7d7512ad3c02166d4db Mon Sep 17 00:00:00 2001 From: Phil B Date: Sat, 29 Sep 2018 15:56:52 +0100 Subject: [PATCH 06/12] More styling. All gonna be pretty monochrome this week --- index.html | 5 +- src/components/App.js | 10 ++- src/components/Movie.js | 7 +- src/components/Result.js | 12 ++-- src/components/Results.js | 4 +- src/components/Search.js | 11 +-- style.css | 140 +++++++++++++++++++++++++++----------- 7 files changed, 130 insertions(+), 59 deletions(-) diff --git a/index.html b/index.html index 5956140..33a1c35 100644 --- a/index.html +++ b/index.html @@ -2,8 +2,11 @@ + + + - Hello World + PhlX
        diff --git a/src/components/App.js b/src/components/App.js index aebb343..66344f6 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -45,17 +45,23 @@ class App extends React.Component { console.log('hello' + query); } + receiveMovie(selectedMovie) { this.setState({ selectedMovie:selectedMovie }) - console.log(selectedMovie) + console.log('ffff' + selectedMovie) } render(){ return (
        - +
        +
        + +

        PHLX

        +
        +
        ) diff --git a/src/components/Movie.js b/src/components/Movie.js index 054e6a3..eb795c0 100644 --- a/src/components/Movie.js +++ b/src/components/Movie.js @@ -27,10 +27,9 @@ class Movie extends React.Component { render() { return ( -
          -
        • {this.props.movie.Title}
        • -
        • {this.props.movie.Title}
        • -
        • {this.props.movie.Title}
        • +
            +
          • Plot: "{this.state.movie.Plot}"
          • +
          • Starring: {this.state.movie.Actors}
          ) } diff --git a/src/components/Result.js b/src/components/Result.js index 6469c2f..68ff536 100644 --- a/src/components/Result.js +++ b/src/components/Result.js @@ -8,16 +8,18 @@ class Result extends React.Component{ this.handleClick = this.handleClick.bind(this); } - handleClick (event) { - this.props.receiveMovie(this.props.result.imdbID) + handleClick () { + + this.props.receiveMovie(this.props.showInfo ? null : this.props.result.imdbID) } render() { return ( -
        • - +
          + +

          {this.props.result.Title}

          {this.props.showInfo ? : null} -
        • +
    ) } } diff --git a/src/components/Results.js b/src/components/Results.js index 0e76865..2c74462 100644 --- a/src/components/Results.js +++ b/src/components/Results.js @@ -4,11 +4,11 @@ import Result from './Result' class Results extends React.Component { render() { return ( - + ) } } diff --git a/src/components/Search.js b/src/components/Search.js index d41867a..482a8e6 100644 --- a/src/components/Search.js +++ b/src/components/Search.js @@ -26,11 +26,12 @@ class Search extends React.Component { } render(){ - return
    - -
    + return( +
    + + +
    + ) } } diff --git a/style.css b/style.css index ad708a8..792a030 100644 --- a/style.css +++ b/style.css @@ -1,50 +1,110 @@ -* { - box-sizing: inherit; -} - body { - box-sizing: border-box; margin: 0; font-family: "Open Sans", sans-serif; min-height: 100vh; - background-color: rgb(216, 238, 245); + background-color: rgb(212, 215, 216); background-attachment: fixed; align-content: center; } +/* .input { -.results{ - display: flex; - flex-wrap: wrap; - width: 100%; - margin: 0 auto; - list-style-type: none; - padding: 0; +} */ + +.app { + width:100%; + display:flex; + flex-direction:column; background: gainsboro; - justify-content: center; -} - -.results__image{ - margin: 50px; - border: 3px solid white; - width: 350px; - height: 350px; - object-fit: cover; -} - -input[type="search"] { - background: rgba(196, 196, 196, 0.43); - border: 2px solid white; - box-sizing: border-box; - box-shadow: inset 0px 4px 4px rgba(0, 0, 0, 0.25); - width: 185px; - height: 42px; - font-family: Roboto Slab; - font-style: normal; - font-weight: normal; - line-height: normal; - font-size: 18px; - text-align: center; - color: #FFFFFF; - margin-right:20px; - } \ No newline at end of file +} + + +.search { + position:fixed; + background: rgb(129, 126, 126); + width:100%; + display:flex; + flex:1; + height:65px; +} + +.search__inner-div { + display:flex; + flex:1; + flex-direction:row; + height:25px; + background: gainsboro; + z-index: 10; + margin:10px; + padding:10px; + +} + +.result { + display:flex; + flex-direction: column; + align-items:center; + width: 300px; + background: white; + border: solid 0px black; + margin:10px; + padding:10px; +} + +.result__image { + width: 300px; + height: 300px; + object-fit:cover; +} + +.search-results { + display:flex; + flex-direction:column; + align-items:center; + width: 100%; + margin-top:70px; +} + +.search__input { + width:150px; + height:25px; + border: solid 1px black; +} + +.search__form { + display: flex; +} + +.search__button { + font-size: 70%; + font-family: inherit; + border: solid 1px; + padding: 3px; + margin-left: 10px; +} + +h1 { + display:flex; + width:100px; + font-family: 'Roboto', sans-serif; + font-size: 1.5em; + padding:0px; + margin:0; + justify-content:flex-end; + align-items:center; +} + +h2 {font-family: 'Open Sans', sans-serif; + padding:0; + margin:0; + font-size:1em; +} + +.more-info { + padding-left: 0; + list-style-type: none; +} + +.more-info__item { + margin: 0 0 10px 0; +} \ No newline at end of file From a61da01cf6b53827a71a0c00f16821e10f9c4cce Mon Sep 17 00:00:00 2001 From: Phil B Date: Sun, 30 Sep 2018 02:04:16 +0100 Subject: [PATCH 07/12] next page is working. Design is somewhat responsive --- src/components/App.js | 31 ++++++++++++----- src/components/Result.js | 2 +- src/components/Results.js | 57 ++++++++++++++++++++++++++++--- style.css | 70 +++++++++++++++++++++++++++++++-------- 4 files changed, 133 insertions(+), 27 deletions(-) diff --git a/src/components/App.js b/src/components/App.js index 66344f6..e8e6817 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -9,11 +9,14 @@ class App extends React.Component { this.state = { query : '', results : [], - selectedMovie : '' + selectedMovie : '', + page: 1, + resultsLeft:0 } this.receiveQuery = this.receiveQuery.bind(this); this.receiveMovie = this.receiveMovie.bind(this); + this.receiveMoreMovies = this.receiveMoreMovies.bind(this); this.createUrl = this.createUrl.bind(this); this.fetchResults = this.fetchResults.bind(this); } @@ -22,7 +25,7 @@ class App extends React.Component { createUrl(typeOfSearch, search) { const baseURL = "http://www.omdbapi.com/"; const apiKey = "95869d44"; - const page = "1"; + const page = this.state.page; console.log(`${baseURL}?apikey=${apiKey}&${typeOfSearch}=${search}&page=${page}&type=movie`) return `${baseURL}?apikey=${apiKey}&${typeOfSearch}=${search}&page=${page}&type=movie` } @@ -31,16 +34,19 @@ class App extends React.Component { fetch(this.createUrl('s', this.state.query)). then(response => response.json()). then(body => { - this.setState({ - results: body.Search - }) - console.log(this.state.results); + console.log(body) + this.state.page===1? + (this.setState({results: body.Search})): + (this.setState({results: this.state.results.concat(body.Search)})) + this.setState({resultsLeft: body.totalResults-(this.state.page*10)}); + }) } receiveQuery(query) { this.setState({ - query: query + query: query, + page: 1 },this.fetchResults) console.log('hello' + query); } @@ -53,6 +59,13 @@ class App extends React.Component { console.log('ffff' + selectedMovie) } + receiveMoreMovies() { + this.setState({ + page:this.state.page+1 + },this.fetchResults) + + } + render(){ return (
    @@ -62,7 +75,9 @@ class App extends React.Component {

    PHLX

    - +
    + +
    ) } diff --git a/src/components/Result.js b/src/components/Result.js index 68ff536..9026f91 100644 --- a/src/components/Result.js +++ b/src/components/Result.js @@ -17,7 +17,7 @@ class Result extends React.Component{ return (
    -

    {this.props.result.Title}

    +

    {this.props.result.Title} ({this.props.result.Year})

    {this.props.showInfo ? : null}
    ) diff --git a/src/components/Results.js b/src/components/Results.js index 2c74462..75814e3 100644 --- a/src/components/Results.js +++ b/src/components/Results.js @@ -1,14 +1,63 @@ import React from 'react'; import Result from './Result' + class Results extends React.Component { + constructor() { + super() + + this.handleScroll = this.handleScroll.bind(this); + this.splitResults = this.splitResults.bind(this); + this.handleClickMore = this.handleClickMore.bind(this); + } + + handleScroll(event) { + console.log("scroll") + + if (event.target.scrollTop + 1000 > event.target.scrollHeight - event.target.clientHeight) { + console.log("scroll") + } + } + + handleClickMore(event) { + this.props.receiveMoreMovies() + } + + splitResults(column) { + let leftSide = []; + let rightSide = []; + for (let i=0; i - {this.props.results.map(result => { - return - })} +
    +
    +
    + {this.splitResults('left').map(result => { + return + })} +
    +
    + {this.splitResults('right').map(result => { + return + })} +
    +
    + {this.props.resultsLeft < 1? null: ( +
    + +
    ) + }
    + ) } } diff --git a/style.css b/style.css index 792a030..a392530 100644 --- a/style.css +++ b/style.css @@ -7,25 +7,28 @@ body { align-content: center; } -/* .input { - -} */ + .container { + margin:10px 10px; +} .app { width:100%; display:flex; flex-direction:column; background: gainsboro; + align-items:center; } .search { position:fixed; + z-index: 10; background: rgb(129, 126, 126); width:100%; display:flex; flex:1; height:65px; + padding:0px; } .search__inner-div { @@ -34,7 +37,6 @@ body { flex-direction:row; height:25px; background: gainsboro; - z-index: 10; margin:10px; padding:10px; @@ -44,7 +46,7 @@ body { display:flex; flex-direction: column; align-items:center; - width: 300px; + width: 90%; background: white; border: solid 0px black; margin:10px; @@ -52,7 +54,7 @@ body { } .result__image { - width: 300px; + width: 100%; height: 300px; object-fit:cover; } @@ -60,9 +62,17 @@ body { .search-results { display:flex; flex-direction:column; + margin:70px 0px 0px 0; + padding:0 10px; +} + +.search-results__column { + display:flex; + flex-direction:column; + flex:1; + padding:0; + margin:0; align-items:center; - width: 100%; - margin-top:70px; } .search__input { @@ -73,6 +83,7 @@ body { .search__form { display: flex; + flex:4; } .search__button { @@ -83,22 +94,37 @@ body { margin-left: 10px; } +.search-container { + display: flex; + flex-direction: column; +} + +.search-more { + display:flex; + flex:1; + padding:20px; + margin:10px; + justify-content:center; +} + +.search-more__button { + width:50%; + background-color: white; + border:0; + margin:0; +} + h1 { display:flex; - width:100px; font-family: 'Roboto', sans-serif; font-size: 1.5em; padding:0px; margin:0; justify-content:flex-end; align-items:center; + flex:1; } -h2 {font-family: 'Open Sans', sans-serif; - padding:0; - margin:0; - font-size:1em; -} .more-info { padding-left: 0; @@ -107,4 +133,20 @@ h2 {font-family: 'Open Sans', sans-serif; .more-info__item { margin: 0 0 10px 0; +} + +@media (min-width: 768px) { + .search-results { + display:flex; + flex-direction:row; + margin:70px 0px 0px 0; + padding:0 10px; + } +} + +@media (min-width: 960px) { + .container { + width: 940px; + } + } \ No newline at end of file From 8b96077c95198b566924a95db653a9b476b092c5 Mon Sep 17 00:00:00 2001 From: Phil B Date: Sun, 30 Sep 2018 14:16:22 +0100 Subject: [PATCH 08/12] favourites adding and deleting from object. Need to reflect changes in favourites star --- index.html | 1 + src/components/App.js | 37 +++++++++++++++++++++++++++++++++++-- src/components/Result.js | 9 +++++++-- src/components/Results.js | 5 +++-- style.css | 8 ++++++-- 5 files changed, 52 insertions(+), 8 deletions(-) diff --git a/index.html b/index.html index 33a1c35..5f11553 100644 --- a/index.html +++ b/index.html @@ -4,6 +4,7 @@ + PhlX diff --git a/src/components/App.js b/src/components/App.js index e8e6817..d4793b4 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -11,16 +11,33 @@ class App extends React.Component { results : [], selectedMovie : '', page: 1, - resultsLeft:0 + resultsLeft:0, + favouritesArray : [], + favouritesObject: {test:123} } this.receiveQuery = this.receiveQuery.bind(this); + this.receiveFavourite = this.receiveFavourite.bind(this); this.receiveMovie = this.receiveMovie.bind(this); this.receiveMoreMovies = this.receiveMoreMovies.bind(this); this.createUrl = this.createUrl.bind(this); this.fetchResults = this.fetchResults.bind(this); } + // componentWillMount() { + // this.setState({ + // favouritesObject : JSON.parse(localStorage.getItem('reactFavourites')) + // }) + + + + // this.setState({ + // favouritesArray : object.Keys(favouritesObject).map(key => favouritesObject[key]) + // }) + // } + + + // builds the url for omdb api request createUrl(typeOfSearch, search) { const baseURL = "http://www.omdbapi.com/"; @@ -66,6 +83,22 @@ class App extends React.Component { } + receiveFavourite(result) { + const favObject = this.state.favouritesObject + if (favObject.hasOwnProperty(result.imdbID)) { + console.log('delete'); + console.log(favObject) + console.log(result.imdbID) + delete favObject[result.imdbID] + } else { + favObject[result.imdbID] = result + console.log('add') + } + this.setState({ + favouritesObject:favObject + }) + } + render(){ return (
    @@ -76,7 +109,7 @@ class App extends React.Component {
    - +
    ) diff --git a/src/components/Result.js b/src/components/Result.js index 9026f91..d235dcf 100644 --- a/src/components/Result.js +++ b/src/components/Result.js @@ -6,18 +6,23 @@ class Result extends React.Component{ constructor() { super() this.handleClick = this.handleClick.bind(this); + this.handleClickFavourite = this.handleClickFavourite.bind(this); + // this.handleClickFavourite = this.handleClickFavourite.bind(this); } handleClick () { - this.props.receiveMovie(this.props.showInfo ? null : this.props.result.imdbID) } + handleClickFavourite() { + this.props.receiveFavourite(this.props.result) + } + render() { return (
    -

    {this.props.result.Title} ({this.props.result.Year})

    +

    {this.props.result.Title} ({this.props.result.Year})

    {this.props.showInfo ? : null}
    ) diff --git a/src/components/Results.js b/src/components/Results.js index 75814e3..3be231d 100644 --- a/src/components/Results.js +++ b/src/components/Results.js @@ -35,6 +35,7 @@ class Results extends React.Component { + render() { console.log(this.props.resultsLeft) return ( @@ -42,12 +43,12 @@ class Results extends React.Component {
    {this.splitResults('left').map(result => { - return + return })}
    {this.splitResults('right').map(result => { - return + return })}
    diff --git a/style.css b/style.css index a392530..54e8a64 100644 --- a/style.css +++ b/style.css @@ -2,7 +2,7 @@ body { margin: 0; font-family: "Open Sans", sans-serif; min-height: 100vh; - background-color: rgb(212, 215, 216); + background: gainsboro; background-attachment: fixed; align-content: center; } @@ -23,7 +23,7 @@ body { .search { position:fixed; z-index: 10; - background: rgb(129, 126, 126); + background: gainsboro; width:100%; display:flex; flex:1; @@ -136,6 +136,10 @@ h1 { } @media (min-width: 768px) { + .containt { + width: 740px; + } + .search-results { display:flex; flex-direction:row; From f61c28ff645223349798b70c1c2d8799312ffeb9 Mon Sep 17 00:00:00 2001 From: Phil B Date: Sun, 30 Sep 2018 20:27:53 +0100 Subject: [PATCH 09/12] fixed issue whereby new browsers were not creating an emppy object for local storage --- src/components/App.js | 31 +++++++++++++++---------------- src/components/Result.js | 9 +++++++-- src/components/Results.js | 10 ++++++++-- style.css | 4 +++- 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/components/App.js b/src/components/App.js index d4793b4..377bcd4 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -24,17 +24,19 @@ class App extends React.Component { this.fetchResults = this.fetchResults.bind(this); } - // componentWillMount() { - // this.setState({ - // favouritesObject : JSON.parse(localStorage.getItem('reactFavourites')) - // }) - + componentWillMount() { + let favObject = JSON.parse(localStorage.getItem('reactFavourites')) - - // this.setState({ - // favouritesArray : object.Keys(favouritesObject).map(key => favouritesObject[key]) - // }) - // } + if (favObject) { + this.setState({ + favouritesObject : favObject + }) + } + else { + console.log(false) + console.log(this.state.favouritesObject) + } + } @@ -43,7 +45,6 @@ class App extends React.Component { const baseURL = "http://www.omdbapi.com/"; const apiKey = "95869d44"; const page = this.state.page; - console.log(`${baseURL}?apikey=${apiKey}&${typeOfSearch}=${search}&page=${page}&type=movie`) return `${baseURL}?apikey=${apiKey}&${typeOfSearch}=${search}&page=${page}&type=movie` } @@ -51,7 +52,6 @@ class App extends React.Component { fetch(this.createUrl('s', this.state.query)). then(response => response.json()). then(body => { - console.log(body) this.state.page===1? (this.setState({results: body.Search})): (this.setState({results: this.state.results.concat(body.Search)})) @@ -65,7 +65,6 @@ class App extends React.Component { query: query, page: 1 },this.fetchResults) - console.log('hello' + query); } @@ -73,7 +72,6 @@ class App extends React.Component { this.setState({ selectedMovie:selectedMovie }) - console.log('ffff' + selectedMovie) } receiveMoreMovies() { @@ -96,7 +94,7 @@ class App extends React.Component { } this.setState({ favouritesObject:favObject - }) + },localStorage.setItem('reactFavourites', JSON.stringify(this.state.favouritesObject))) } render(){ @@ -105,11 +103,12 @@ class App extends React.Component {
    +

    Favourites

    PHLX

    - +
    ) diff --git a/src/components/Result.js b/src/components/Result.js index d235dcf..55c64ea 100644 --- a/src/components/Result.js +++ b/src/components/Result.js @@ -18,11 +18,16 @@ class Result extends React.Component{ this.props.receiveFavourite(this.props.result) } + render() { + console.log(this.props.isFavourite?'movies__fav-icon fas fa-star fa-2x':'movies__fav-icon far fa-star fa-2x') return (
    - -

    {this.props.result.Title} ({this.props.result.Year})

    + +

    + {this.props.result.Title} ({this.props.result.Year}) + +

    {this.props.showInfo ? : null}
    ) diff --git a/src/components/Results.js b/src/components/Results.js index 3be231d..dd842a2 100644 --- a/src/components/Results.js +++ b/src/components/Results.js @@ -9,6 +9,7 @@ class Results extends React.Component { this.handleScroll = this.handleScroll.bind(this); this.splitResults = this.splitResults.bind(this); this.handleClickMore = this.handleClickMore.bind(this); + this.isFavourite = this.isFavourite.bind(this); } handleScroll(event) { @@ -33,6 +34,10 @@ class Results extends React.Component { return column === 'left'?leftSide:rightSide; } + isFavourite(imdbID) { + return this.props.favObject[imdbID]?true:false + } + @@ -43,12 +48,13 @@ class Results extends React.Component {
    {this.splitResults('left').map(result => { - return + return })}
    {this.splitResults('right').map(result => { - return + return })}
    diff --git a/style.css b/style.css index 54e8a64..9a4519d 100644 --- a/style.css +++ b/style.css @@ -8,6 +8,7 @@ body { } .container { + width: 300px; margin:10px 10px; } @@ -129,6 +130,7 @@ h1 { .more-info { padding-left: 0; list-style-type: none; + width: 100%; } .more-info__item { @@ -136,7 +138,7 @@ h1 { } @media (min-width: 768px) { - .containt { + .container { width: 740px; } From 20fed8ade7b59cf0f505d1032a8cdfbac49ffeee Mon Sep 17 00:00:00 2001 From: Phil B Date: Sun, 30 Sep 2018 21:50:04 +0100 Subject: [PATCH 10/12] favourites working and counter showing - but header needs to be reformatted --- src/components/App.js | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/components/App.js b/src/components/App.js index 377bcd4..a2586e2 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -13,6 +13,7 @@ class App extends React.Component { page: 1, resultsLeft:0, favouritesArray : [], + favouritesLength: 0, favouritesObject: {test:123} } @@ -22,6 +23,8 @@ class App extends React.Component { this.receiveMoreMovies = this.receiveMoreMovies.bind(this); this.createUrl = this.createUrl.bind(this); this.fetchResults = this.fetchResults.bind(this); + this.showFavourites = this.showFavourites.bind(this) + this.updateFavouritesArray = this.updateFavouritesArray.bind(this) } componentWillMount() { @@ -38,6 +41,9 @@ class App extends React.Component { } } + componentDidMount() { + this.updateFavouritesArray(); + } // builds the url for omdb api request @@ -84,17 +90,32 @@ class App extends React.Component { receiveFavourite(result) { const favObject = this.state.favouritesObject if (favObject.hasOwnProperty(result.imdbID)) { - console.log('delete'); - console.log(favObject) - console.log(result.imdbID) delete favObject[result.imdbID] } else { favObject[result.imdbID] = result - console.log('add') } this.setState({ favouritesObject:favObject },localStorage.setItem('reactFavourites', JSON.stringify(this.state.favouritesObject))) + + this.updateFavouritesArray(); + } + + updateFavouritesArray() { + console.log(this.state.favouritesObject) + this.state.favouritesObject.hasOwnProperty('test')?delete this.state.favouritesObject.test:null + const favouritesKeys = Object.keys(this.state.favouritesObject); + this.state.favouritesArray = favouritesKeys.map(key => this.state.favouritesObject[key]) + console.log(this.state.favouritesArray); + this.setState({ + favouritesLength:this.state.favouritesArray.length + }) + } + + showFavourites() { + this.setState({ + results:this.state.favouritesArray + }) } render(){ @@ -103,7 +124,7 @@ class App extends React.Component {
    -

    Favourites

    +

    Favourites - {this.state.favouritesLength} -

    PHLX

    From 8b572fdfab0339fac85e2b34495624b9f90a52f5 Mon Sep 17 00:00:00 2001 From: Phil B Date: Sun, 30 Sep 2018 23:01:03 +0100 Subject: [PATCH 11/12] tidied some styling --- src/components/App.js | 49 +++++++++++++++++++++++++++++++-------- src/components/Result.js | 6 ++--- src/components/Results.js | 4 ++++ style.css | 36 ++++++++++++++++++++++++---- 4 files changed, 78 insertions(+), 17 deletions(-) diff --git a/src/components/App.js b/src/components/App.js index a2586e2..ca63cf0 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -27,6 +27,9 @@ class App extends React.Component { this.updateFavouritesArray = this.updateFavouritesArray.bind(this) } +//****************************************// +// Setting up local storage - putting any existing local storage into state + componentWillMount() { let favObject = JSON.parse(localStorage.getItem('reactFavourites')) @@ -35,17 +38,19 @@ class App extends React.Component { favouritesObject : favObject }) } - else { - console.log(false) - console.log(this.state.favouritesObject) - } } +//****************************************// +// creates an array of favourites. This is necessary to show the amount (.length) of favourites on top bar. + componentDidMount() { this.updateFavouritesArray(); } +//****************************************// +// Fetching data from omdb API + // builds the url for omdb api request createUrl(typeOfSearch, search) { const baseURL = "http://www.omdbapi.com/"; @@ -66,6 +71,11 @@ class App extends React.Component { }) } + +//****************************************// +// Receive search query from Search componenent + + receiveQuery(query) { this.setState({ query: query, @@ -73,6 +83,8 @@ class App extends React.Component { },this.fetchResults) } +//****************************************// +// Receive selected movie from Result component receiveMovie(selectedMovie) { this.setState({ @@ -80,6 +92,9 @@ class App extends React.Component { }) } +//****************************************// +// Request to add another page of results (sent from Results component) + receiveMoreMovies() { this.setState({ page:this.state.page+1 @@ -87,6 +102,9 @@ class App extends React.Component { } +//****************************************// +// Add a movie to favourites object (App state) + receiveFavourite(result) { const favObject = this.state.favouritesObject if (favObject.hasOwnProperty(result.imdbID)) { @@ -101,6 +119,9 @@ class App extends React.Component { this.updateFavouritesArray(); } +//****************************************// +// Create an array of favourites from favourites object. This is used to update the App/result state which will then show favourites instead of search + updateFavouritesArray() { console.log(this.state.favouritesObject) this.state.favouritesObject.hasOwnProperty('test')?delete this.state.favouritesObject.test:null @@ -112,23 +133,31 @@ class App extends React.Component { }) } +//****************************************// +// By setting the state of result to the favourites array favourites will now be shown instead of search results + showFavourites() { this.setState({ - results:this.state.favouritesArray + results:this.state.favouritesArray, + resultsLeft:0 }) } render(){ return (
    -
    -
    - -

    Favourites - {this.state.favouritesLength} -

    -

    PHLX

    +
    +

    Favourites ({this.state.favouritesLength})

    +
    +
    + +

    PHLX

    +
    +
    +
    diff --git a/src/components/Result.js b/src/components/Result.js index 55c64ea..c57e746 100644 --- a/src/components/Result.js +++ b/src/components/Result.js @@ -24,9 +24,9 @@ class Result extends React.Component{ return (
    -

    - {this.props.result.Title} ({this.props.result.Year}) - +

    + {this.props.result.Title} ({this.props.result.Year}) +

    {this.props.showInfo ? : null}
    diff --git a/src/components/Results.js b/src/components/Results.js index dd842a2..09b75b8 100644 --- a/src/components/Results.js +++ b/src/components/Results.js @@ -24,6 +24,10 @@ class Results extends React.Component { this.props.receiveMoreMovies() } +//****************************************// +// Splliting the results into 2 columns to stop result moving from left to right when more details are shown. +// Odd and evens are split into each column to keep the ordering the same as omdb (first results at top of page) + splitResults(column) { let leftSide = []; let rightSide = []; diff --git a/style.css b/style.css index 9a4519d..876ad9d 100644 --- a/style.css +++ b/style.css @@ -20,15 +20,27 @@ body { align-items:center; } - -.search { +.top { position:fixed; z-index: 10; + width:100%; + background: gainsboro; + +} + +.top__favourites { + margin:0; + padding:0; + text-align: right; + padding-right:10px; +} +.search { + background: gainsboro; width:100%; display:flex; flex:1; - height:65px; + height:45px; padding:0px; } @@ -38,7 +50,7 @@ body { flex-direction:row; height:25px; background: gainsboro; - margin:10px; + margin:0 10px; padding:10px; } @@ -60,6 +72,22 @@ body { object-fit:cover; } +.result__tab { + display:flex; + flex:1; + width:100% +} + +.result__title-year { + display:flex; + flex:5; +} + +.result__fav-star { + display:flex; + flex:1 +} + .search-results { display:flex; flex-direction:column; From 22aa1d34958b163090a3306c2ad0ad1fe06367d0 Mon Sep 17 00:00:00 2001 From: Phil Berryman <63644+philberryman@users.noreply.github.com> Date: Tue, 2 Oct 2018 18:24:39 +0100 Subject: [PATCH 12/12] Update README.md --- README.md | 63 ++++++++++++------------------------------------------- 1 file changed, 13 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index cec0904..46ec21d 100644 --- a/README.md +++ b/README.md @@ -1,58 +1,21 @@ # React Cinema -Let's revisit our first project where we built a movie search engine using the Open Movie Database. This time we want to implement it using React. It should be a Single Page App, that is all the functionality should be on a single page, rather switch between multiple pages. +This was the weekend project for Week 4 of the 12 week boot camp I have been doing at Constructor Labs. Earlier in the week we had our first introduction to using React and this was our chance to put our new found powers to good use by recreating the project from the previous week which was done using vanilla js. -Before starting to code produce a diagram using pen and paper of your application which shows both layout and a tree diagram of the components. +The goal of the project was to implement a movie search database (with favourites) using the omdb api and React. -What are some of the components you are going to need? Which components will fetch data and how will that data be displayed? Which components will store state and how will they pass data to other components? Which components should be re-used? Rather than re-implementing your previous solution again have a think about what you have learned in the past week and how you can apply it here. +The core features we were asked to add were: -You can start coding once your plan has been checked by a TA or instructor. +* Movie search +* More details when a film was selected +* Pagination where needed for search results +* Favourites (and local storage) -## The brief +At this point in the course we're still on purely browser based technology so this is all running on the front-end. -We want to create a movie search engine. To power it we will use the [Open Movie Database](http://www.omdbapi.com) API. +A few things I wish I'd done better with this project: +* Some of the naming isn't as obvious as it could be. Another 30 mins of planning upfront could have been useful. +* There was probably more logic than neccessary in some of the componenents that could have been kept in the main App component. +* Infinite scrolling would have been nice but nothind I did seemed to make it work. -To start using the OMDB API you will first need to sign up with them to receive and API key. The key issued to you will allow you 1000 requests per day and you will need to include this key as part of every request. - -To get started, fork and clone this repo. Please submit a pull request after your first commit and push commits regularly. - -You should complete as many of the following tasks as you can. - -- [ ] Work using mobile first, that is create the mobile version first and add tablet and desktop versions after. -- [ ] Create an HTML page which should have a `form` at the top which contains a text input and a submit button. Below it should have a placeholder element for the returned results. -- [ ] Use JavaScript to capture the `submit` event in your search form, extract the query string from the text input and use that to make an API call to the Open Movie Database API to search for films which match the query string using `fetch`. `console.log` the results -- [ ] Display the data returned by the API including title, year and poster picture - -**Movie details** - -- [ ] Adjust your layout to create room for a detailed view of movie information -- [ ] Capture clicks on your movie results items and use that information to make another request to the API for detailed movie information. Using event delegation will help you here. `console.log` the returned result -- [ ] Display the detailed movie result in the in the details view you created earlier -- [ ] Make your design responsive and ensure it looks great at different screen widths - -**Your own feature** - -- [ ] Implement any feature you would find useful or interesting - -**Stretch goals** - -- [ ] Implement pagination so that users can navigate between all movies in search results rather than just the first ten -- [ ] Create a favourites list. It's up to you how you would add items to favourites. You could add a button or otherwise. Display a list of favourites somewhere on your page. -- [ ] Make the favourites list sortable. Add `up` and `down` buttons to your favourites which on click will move the result in relevant direction -- [ ] Save favourites locally using `localStorage` so that favourites persist in browser after refresh -- [ ] Let's create a search preview. It should listen for input events and submit a search request with current query string. Display the search preview results in an absolute positioned container just below the search box. -Hint: You may want to kick of the searching after at least 3 characters have been typed. - -## Objectives - -* We want to see great looking webpages that work well at all screen widths -* Your code should have consistent indentation and sensible naming -* Use lots of concise, reusable functions with a clear purpose -* Add code comments where it is not immediately obvious what your code does -* Your code should not throw errors and handle edge cases gracefully. For example not break if server fails to return expected results -* Use BEM methodology to style your page -* Try to use pure functions as much as possible, but keep in mind it will not be possible to make all functions pure. - -## README.md - -When finished, include a README.md in your repo. Someone who is not familiar with the project should be able to look at it and understand what it is and what to do with it. Explain functionality created, mention any outstanding issues and possible features you would include if you had more time. List technologies used to create the app. Include a screenshot of your app in the README. +Overall I enjoyed building this project and was am pretty happy with how it turned out.