diff --git a/README.md b/README.md index cec0904..6ebb10c 100644 --- a/README.md +++ b/README.md @@ -1,58 +1,33 @@ -# React Cinema +# Now Playing -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 project, titled Now Playing, has been created as a means for movie fans to search for information on films, be it their favourites or ones they simply wish to see. Now playing also allows for the compilation and curation of the users favourite films, where they are able to store and sort titles for reference. -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. +**Design Objectives** -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. +This project was created with the purpose of implimenting React and React Components to create a modular user interface, with parts that we are able to re-use or re-constitute as the needs of the user change, or as the trends of user interfaces progress. -You can start coding once your plan has been checked by a TA or instructor. +**Searching for films** -## The brief +Now Playing allows users to search for films by using their search terms to make queries with the [Open Movie Database](http://www.omdbapi.com), a large external API that stores details about possibly every film. From there, should a user wish to know more about a particular film, Now Playing makes a seperate API call to the Open Movie Database, searching for the film by its IMDB id. This then returns more details information about the film, which is then displayed to the user. For this project it was important to establish components that made as few API calls as possible to accomodate for as many connection speeds as possible. -We want to create a movie search engine. To power it we will use the [Open Movie Database](http://www.omdbapi.com) API. +**Pagination** -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. +Now Playing automatically generates functionality that allows the user to search through all returned results, 10 results to a page. As this initial API call is made, Now Playing takes the number of results, divides it by the number of results returned per page, and shows the user what page they are viewing out of how many they can view. Previous projects that have implimented pagination generated as many buttons as pages, which can clutter the page view. Now Playing instead displays arrows that allow the user to move forwards or backwards one page at a time, clearing up the page visually. -To get started, fork and clone this repo. Please submit a pull request after your first commit and push commits regularly. +**Favourites Feature** -You should complete as many of the following tasks as you can. +Now Playing allows the user to store and curate a list of their favourite films. Each returned search item has a button on it that, when pressed, passes the film information into the Favourites component, and stores that information in Local Storage within the browser so that the user's favourites persist between page refreshes. -- [ ] 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 +As of now, functionality is in place that allows the user to remove individual films from their favourites, or to clear their entire favourties list. These features are subject to a CSS bug at present that closes the favourites menu when a button is pressed. Equally, the buttons that move films up and down in the favourites list is working to an extent, but has a bug with its conditional logic that needs revising as it causes replication in list items in some cases. -**Movie details** +**Future goals and improvements** -- [ ] 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 +- Improve favourites functionality so that it is implimented fully with no bugs. -**Your own feature** +- Create a search preview feature that lets the user see what some of the possible returned search items will be ahead of them submitting a search. -- [ ] Implement any feature you would find useful or interesting +- Import film trailers where available -**Stretch goals** +- Create provisions for more user errors i.e. submitting a blank search, submitting an incorrect search. -- [ ] 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. +- Improve pagination so that the user can both go between pages one at a time and go to a page of thier choosing. \ No newline at end of file diff --git a/images/felix-mooneeram-222805-unsplash.jpg b/images/felix-mooneeram-222805-unsplash.jpg new file mode 100644 index 0000000..60e5037 Binary files /dev/null and b/images/felix-mooneeram-222805-unsplash.jpg differ diff --git a/images/kilyan-sockalingum-478724-unsplash.jpg b/images/kilyan-sockalingum-478724-unsplash.jpg new file mode 100644 index 0000000..2d5eee7 Binary files /dev/null and b/images/kilyan-sockalingum-478724-unsplash.jpg differ diff --git a/images/krists-luhaers-543526-unsplash.jpg b/images/krists-luhaers-543526-unsplash.jpg new file mode 100644 index 0000000..c093125 Binary files /dev/null and b/images/krists-luhaers-543526-unsplash.jpg differ diff --git a/index.html b/index.html index 5956140..f8c9b5c 100644 --- a/index.html +++ b/index.html @@ -1,12 +1,18 @@ - - - - Hello World - - -
- - - + + + + + + + + Now Playing + + + +
+ + + + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 8ca987c..4208251 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1915,6 +1915,16 @@ } } }, + "classname": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/classname/-/classname-0.0.0.tgz", + "integrity": "sha1-Q9FxtITjVMeik6W3gATfaFLbINY=" + }, + "classnames": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", + "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" + }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", diff --git a/package.json b/package.json index 26c045b..76ab9b7 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,8 @@ ] }, "dependencies": { + "classname": "0.0.0", + "classnames": "^2.2.6", "react": "^16.2.0", "react-dom": "^16.2.0" }, diff --git a/src/components/App.js b/src/components/App.js index 9520f77..bbba24f 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -1,16 +1,199 @@ -import React from 'react'; +import React from "react"; +import Search from "./Search"; +import Results from "./Results"; +import Pages from "./Pages"; +import Favourites from "./Favourites"; +import Header from "./Header"; class App extends React.Component { - constructor(){ + constructor() { super(); + this.state = { + searchTerm: "", + movieArray: [], + pagesObject: {}, + currentPage: 1, + favouritesArray: [], + apiKey: "e2c4cd31" + }; + this.receiveSearchTerm = this.receiveSearchTerm.bind(this); + this.fetchMovies = this.fetchMovies.bind(this); + this.receiveCurrentPage = this.receiveCurrentPage.bind(this); + this.receiveFavouritesInfo = this.receiveFavouritesInfo.bind(this); } - render(){ + receiveSearchTerm(term) { + this.setState({ + searchTerm: term + }); + } + + fetchMovies() { + if (this.state.searchTerm === "") { + this.setState({ + movieArray: [] + }); + } else { + fetch( + `http://www.omdbapi.com/?s=${this.state.searchTerm}&page=${ + this.state.currentPage + }&apikey=${this.state.apiKey}` + ) + .then(response => response.json()) + .then(body => { + this.setState({ + pagesObject: body, + movieArray: body.Search + }); + }); + } + } + + componentDidMount() { + this.setState( + { + favouritesArray: + localStorage.getItem("favourites") === null + ? [] + : JSON.parse(localStorage.getItem("favourites")) + } + // localStorage.clear() + ); + } + + receiveCurrentPage(page) { + this.setState( + { + currentPage: page + }, + () => this.fetchMovies() + ); + } + + receiveFavouritesInfo(id, favourite) { + if ( + id === "add__to__favourites" && + this.state.favouritesArray.indexOf(favourite) === -1 + ) { + this.setState( + { + favouritesArray: this.state.favouritesArray.concat([favourite]) + }, + () => + localStorage.setItem( + "favourites", + JSON.stringify(this.state.favouritesArray) + ) + ); + } else if (id === "favourites__clear__favourites") { + this.setState( + { + favouritesArray: [] + }, + () => localStorage.clear() + ); + } else if (id === "favourites__delete__favourite") { + const favouritesToBeRemoved = this.state.favouritesArray; + favouritesToBeRemoved.splice( + this.state.favouritesArray.indexOf(favourite), + 1 + ); + this.setState( + { + favouritesArray: favouritesToBeRemoved + }, + () => + localStorage.setItem( + "favourites", + JSON.stringify(this.state.favouritesArray) + ) + ); + } else if (id === "favourites__move__up") { + let favouriteIndex = this.state.favouritesArray.indexOf(favourite); + let firstHalfFavourites = this.state.favouritesArray.slice( + 0, + favouriteIndex - 1 + ); + let favouritesToSwap = this.state.favouritesArray.slice( + favouriteIndex - 1, + favouriteIndex + 1 + ); + let secondHalfFavourites = this.state.favouritesArray.slice( + favouriteIndex + 1 + ); + favouritesToSwap.reverse(); + let rearrangedFavourites = firstHalfFavourites.concat( + favouritesToSwap, + secondHalfFavourites + ); + this.setState( + { + favouritesArray: rearrangedFavourites + }, + () => + localStorage.setItem( + "favourites", + JSON.stringify(this.state.favouritesArray) + ) + ); + } else if (id === "favourites__move__down") { + let favouriteIndex = this.state.favouritesArray.indexOf(favourite); + let firstHalfFavourites = this.state.favouritesArray.slice( + 0, + favouriteIndex + ); + let favouritesToSwap = this.state.favouritesArray.slice( + favouriteIndex, + favouriteIndex + 2 + ); + let secondHalfFavourites = this.state.favouritesArray.slice( + favouriteIndex + 2 + ); + favouritesToSwap.reverse(); + let rearrangedFavourites = firstHalfFavourites.concat( + favouritesToSwap, + secondHalfFavourites + ); + this.setState( + { + favouritesArray: rearrangedFavourites + }, + () => + localStorage.setItem( + "favourites", + JSON.stringify(this.state.favouritesArray) + ) + ); + } + } + + render() { return (
- React cinema app +
+ + + +
- ) + ); } } diff --git a/src/components/Favourites.js b/src/components/Favourites.js new file mode 100644 index 0000000..17b0081 --- /dev/null +++ b/src/components/Favourites.js @@ -0,0 +1,37 @@ +import React from "react"; +import FavouritesItem from "./FavouritesItem"; + +class Favourites extends React.Component { + constructor() { + super(); + this.handleClick = this.handleClick.bind(this); + } + + handleClick(event) { + event.stopPropagation(); + this.props.receiveFavouritesInfo(event.target.id); + } + + render() { + return ( +
+ +
+ ); + } +} + +export default Favourites; diff --git a/src/components/FavouritesItem.js b/src/components/FavouritesItem.js new file mode 100644 index 0000000..9803830 --- /dev/null +++ b/src/components/FavouritesItem.js @@ -0,0 +1,52 @@ +import React from "react"; +import cx from "classnames"; +class FavouritesItem extends React.Component { + constructor() { + super(); + this.handleClick = this.handleClick.bind(this); + } + + handleClick(event) { + this.props.receiveFavouritesInfo(event.target.id, this.props.favourite); + } + + render() { + const classesUp = cx("favouritesMove", { + "button--notVisable": + this.props.favouritesArray.indexOf(this.props.favourite) === 0 + }); + + const classesDown = cx("favouritesMove", { + "button--notVisable": + this.props.favouritesArray.indexOf(this.props.favourite) === + this.props.favouritesArray.length - 1 + }); + + return ( +
+
  • {this.props.favourite.Title}
  • +
    + + + +
    +
    + ); + } +} + +export default FavouritesItem; diff --git a/src/components/Header.js b/src/components/Header.js new file mode 100644 index 0000000..42ea9c5 --- /dev/null +++ b/src/components/Header.js @@ -0,0 +1,24 @@ +import React from "react"; + +class Header extends React.Component { + constructor() { + super(); + } + + render() { + return ( +
    +
    +

    Now Playing

    +

    An "Internet Movie Database"

    +
    + +
    + ); + } +} + +export default Header; diff --git a/src/components/Pages.js b/src/components/Pages.js new file mode 100644 index 0000000..67c0245 --- /dev/null +++ b/src/components/Pages.js @@ -0,0 +1,52 @@ +import React from "react"; +import cx from "classnames"; + +class Pages extends React.Component { + constructor() { + super(); + this.handleClick = this.handleClick.bind(this); + } + + handleClick(event) { + if (event.target.className === "previousPage") { + this.props.receiveCurrentPage(this.props.currentPage - 1); + } else if (event.target.className === "nextPage") { + this.props.receiveCurrentPage(this.props.currentPage + 1); + } + } + + render() { + let totalPages = Math.ceil( + this.props.pagesObject.totalResults / this.props.movieArray.length + ); + + const pagesClasses = cx("pages", { + "pages--notVisable": this.props.movieArray.length === 0, + "pages--visable": this.props.movieArray.length > 0 + }); + + const previousPageClass = cx("previousPage", { + "button--notVisable": this.props.currentPage === 1 + }); + + const nextPageClass = cx("nextPage", { + "button--notVisable": this.props.currentPage === totalPages + }); + + return ( +
    + +

    + {this.props.currentPage} of {isNaN(totalPages) ? 0 : totalPages} pages +

    + +
    + ); + } +} + +export default Pages; diff --git a/src/components/READMEbrief.md b/src/components/READMEbrief.md new file mode 100644 index 0000000..cec0904 --- /dev/null +++ b/src/components/READMEbrief.md @@ -0,0 +1,58 @@ +# 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. + +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. + +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. + +You can start coding once your plan has been checked by a TA or instructor. + +## The brief + +We want to create a movie search engine. To power it we will use the [Open Movie Database](http://www.omdbapi.com) API. + +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. diff --git a/src/components/ResultItem.js b/src/components/ResultItem.js new file mode 100644 index 0000000..996e820 --- /dev/null +++ b/src/components/ResultItem.js @@ -0,0 +1,62 @@ +import React from "react"; +import cx from "classnames"; +import ResultItemDetails from "./ResultItemDetails"; + +class ResultItem extends React.Component { + constructor() { + super(); + this.state = { detailsShow: false, filmDetails: {} }; + this.handleClick = this.handleClick.bind(this); + this.fetchMovieDetails = this.fetchMovieDetails.bind(this); + } + + fetchMovieDetails(movie) { + fetch( + `http://www.omdbapi.com/?i=${movie.imdbID}&apikey=${this.props.apiKey}` + ) + .then(response => response.json()) + .then(body => { + this.setState({ filmDetails: body }); + }); + } + + handleClick(event) { + if (event.target.className === "favourite__button") { + this.props.receiveFavouritesInfo(event.target.id, this.props.movie); + } else { + if (this.state.detailsShow === true) { + this.setState({ + detailsShow: !this.state.detailsShow + }); + } else { + this.fetchMovieDetails(this.props.movie); + this.setState({ + detailsShow: !this.state.detailsShow + }); + } + } + } + + render() { + const classes = cx("result__item__details", { + "result__item__details--active": this.state.detailsShow, + "result__item__details--inactive": !this.state.detailsShow + }); + + return ( +
    +

    {this.props.movie.Title}

    + + + +
    + ); + } +} + +export default ResultItem; diff --git a/src/components/ResultItemDetails.js b/src/components/ResultItemDetails.js new file mode 100644 index 0000000..2ba83f8 --- /dev/null +++ b/src/components/ResultItemDetails.js @@ -0,0 +1,21 @@ +import React from "react"; + +class ResultItemDetails extends React.Component { + constructor() { + super(); + } + + render() { + return ( +
    +

    Year: {this.props.filmDetails.Year}

    +

    Cast: {this.props.filmDetails.Actors}

    +

    Synopsis: {this.props.filmDetails.Plot}

    +

    Directed by: {this.props.filmDetails.Director}

    +

    IMDB Rating: {this.props.filmDetails.imdbRating}

    +
    + ); + } +} + +export default ResultItemDetails; diff --git a/src/components/Results.js b/src/components/Results.js new file mode 100644 index 0000000..7938c4f --- /dev/null +++ b/src/components/Results.js @@ -0,0 +1,26 @@ +import React from "react"; +import ResultItem from "./ResultItem"; + +class Results extends React.Component { + constructor() { + super(); + } + + render() { + return ( +
    + {this.props.movieArray.map(movie => ( + + ))} +
    + ); + } +} + +export default Results; diff --git a/src/components/Search.js b/src/components/Search.js new file mode 100644 index 0000000..22c029b --- /dev/null +++ b/src/components/Search.js @@ -0,0 +1,38 @@ +import React from "react"; + +class Search extends React.Component { + constructor() { + super(); + this.state = { searchTerm: "" }; + this.handleSubmit = this.handleSubmit.bind(this); + this.handleChange = this.handleChange.bind(this); + } + + handleSubmit(event) { + event.preventDefault(); + this.props.receiveSearchTerm(event.target.firstChild.value); + this.props.fetchMovies(); + } + + handleChange(event) { + this.props.receiveSearchTerm(event.target.value); + } + + render() { + return ( +
    +
    + + +
    +
    + ); + } +} + +export default Search; diff --git a/style.css b/style.css index e69de29..7657ac4 100644 --- a/style.css +++ b/style.css @@ -0,0 +1,307 @@ +html, body { + margin: 0; + padding: 0; +} + +body{ + font-family: 'K2D', sans-serif; + width: 100vw; + display: flex; + justify-contet: center; + align-items: center; + background-color: black; + color: white; + min-height: 100vh; +} + +header { + font-family: 'Abril Fatface', cursive; + display: flex; + flex-direction: column; + align-items: center; + margin-bottom: 20px; +} + +.header__text{ + position: absolute; +} + +.header__title{ + color: #B9090B; + width: 100vw; + display: flex; + justify-content: center; + font-size: 15vw; + margin-bottom: 10px; + margin-top: 20px; +} + +.header__subtitle{ + font-family: 'K2D', sans-serif; + display: flex; + justify-content: center; + margin-top: 0; +} + +.header__image { + display: flex; + width: 100vw; +} + +.search__form { + display: flex; + width: 100vw; + justify-content: center; +} + +.search__input { + width: 70vw; + height: 25px; + background-color: black; + color: white; + border: 1px solid grey; + border-radius: 15px; + font-size: 1.2em; + padding-left: 10px + +} + +.search__button { + width: 20%; + background-color: #B9090B; + color: white; + border: 0.5px solid grey; + border-radius: 15px; + font-size: 1.2em; + margin-left: 7px; +} + +.search__button:hover{ + background-color: white; + color: #B9090B; +} + +.favourites { + margin-top: 15px; + position: relative; + height: 40px; + justify-content: center; +} + +.favourites:before { + content: "Favourites"; + margin-top: 20px; + margin-left: 5vw; + border: 1px solid white; + padding: 3px; + border-radius: 5px; + background-color: #B9090B; +} + +.favourites:focus { + pointer-events: none; +} + +.favourites:focus .favourites__list { + visibility: visible; + display: flex; + flex-direction: column; + opacity: 1; + pointer-events: auto; +} + +.favourites__list{ + visibility: hidden; + transition: visibility 0.2s; + z-index: 1; + opacity: 0; + position: initial; + background-color: black; + border: 1px solid white; + width: 80vw; +} + +.favourites__list__item { + list-style: none; + display: flex; + flex-direction: row; + justify-content: space-between; + border: 1px solid white; + border-radius: 5px; + margin: 2px; + margin-top: 0; + width: 80%; + height: 30px; + background-color: #B9090B; +} + +.favourites__list__item__buttons { + display: flex; +} + +#favourites__move__up, +#favourites__move__down, +#favourites__delete__favourite { + background-color: #B9090B; + color: white; + border-top: 0; + border-bottom: 0; + border-right: 0; +} + +#favourites__clear__favourites{ + background-color: #B9090B; + color: white; + border-radius: 3px; + font-size: 0.9em; + width: 200px; + justify-content: center; +} + +.result__item { + display: flex; + justify-content: center; + flex-wrap: wrap; + align-items: center; + margin-bottom: 20px; +} + +.result__title { + width: 50vw; + display: flex; + justify-content: center; + margin-left: 5vw; +} + +.result__image { + width: 60vw; +} + +.favourite__button { + background-color: #B9090B; + color: white; + height: 5vh; + font-size: 1.2em; + border-radius: 25%; + border: 1px solid grey; +} + + +.favourite__button:hover { + background-color: white; + color: #B9090B; +} + +.result__item__details{ + border: 1px solid white; + margin-top: 5px; +} + +.result__item__details--active { + display: flex; + flex-direction: column; + margin-left: 10px; + margin-right: 10px; + padding-left: 5px; +} + +.result__item__details--inactive { + display: none; +} + + +.pages--notVisable { + display: none +} + +.pages--visable { + display: flex; + justify-content: center; + align-items: center; +} + +.previousPage { + height: 30px; + margin-right: 30px; + width: 15%; + background-color: #B9090B; + color: white; + font-size: 1em; + border-radius: 4px; +} + +.nextPage { + height: 30px; + margin-left: 30px; + width: 15%; + background-color: #B9090B; + color: white; + font-size: 1em; + border-radius: 4px; +} + +.button--notVisable { + display: none; +} + + +@media (min-width: 768px) { + + .result { + display: flex; + flex-wrap: wrap; + justify-content: space-around + } + + .result__item { + display: flex; + justify-content: center; + flex-wrap: wrap; + align-items: center; + align-self: flex-start; + margin-bottom: 20px; + width: 40%; + flex-grow: 0; + } + + .result__image { + margin-top: 10px; + } + + .result__item__details--active { + display: flex; + flex-direction: column; + margin-left: 0; + margin-right: 0; + padding-left: 5px; + width: 100%; + } + +} + + +@media (min-width: 960px) { + + .result { + display: flex; + flex-wrap: wrap; + justify-content: space-around; + } + + .result__item { + display: flex; + justify-content: center; + flex-wrap: wrap; + align-items: center; + margin-bottom: 20px; + width: 20%; + flex-grow: 0; + margin-right: 10px; + } + + .result__image { + margin-top: 10px; + width: 100%; + } + +} \ No newline at end of file