diff --git a/.gitignore b/.gitignore
index 891437f..68b8643 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
/node_modules
/dist
.DS_Store
+/images
+.env
\ No newline at end of file
diff --git a/Procfile b/Procfile
new file mode 100644
index 0000000..bef5264
--- /dev/null
+++ b/Procfile
@@ -0,0 +1 @@
+web: npm run start
\ No newline at end of file
diff --git a/README.md b/README.md
index cec0904..e2e5af1 100644
--- a/README.md
+++ b/README.md
@@ -1,58 +1,53 @@
-# 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.
+
+
+
+# Moviewer
+## A movie search enginee
+**Moviewer** is a movie search engine app which uses the Open Movie Database API. Enter a search term and see the search results instantly with full details of the movie. It has a responsive layout for mobile and desktop screen sizes giving a user-friendly experience.
+
+> [View the live demo](https://moviewer.herokuapp.com/)
+
+> [View the repo on Github](https://github.com/rolandjlevy/moview)
+
+## Installation and set up
++ Clone this repo
++ Run `npm install` to install dependencies
++ Run `npm run dev` to create a development build with webpack
++ Open index.html file in the browser
+
+## Functionality and features
++ The app first captures the search input and fetches data that matches the input from the [Open Movie Database](http://www.omdbapi.com) API.
++ The app then uses React and CSS to display the data returned by the API as pages which are lists of 10 links per page.
++ Each link has a unique ID which is used to identify the selected movie from the API.
++ Each time a movie is selected, the title, poster image, description and other details are displayed
+
+## Technology used
++ React
++ CSS
++ Classnames
++ Flex-box
++ Webpack
++ Open Movie Database API
+
+## Stages of development
++ Set up API and read the Open Movie Database API documentation
++ Created functionality for the initial search query
++ Created smart pagination, with scrolling to see all results
++ Retrieved the data for selected movie
++ Used React to display the poster image, year, IMDB rating, director and description
++ Used CSS to style the UI
+
+## Features
++ Responsive search preview - results are updated each time a letter is entered and shown below the search box
++ Smart pagination allows users to quickly navigate all pages of the search results
++ Form validation gives the user feedback and details of results:
+> + if the search input is more or less than 3 letters
+> + if the search input has returned a valid result or not
+> + How many results and pages of results have been found
+
+## Desired features with more time
++ Improve the desktop view for better responsiveness
++ Allow users to mark movies as favourites and use localStorage to save the favourites into a sortable list
++ Added a featured movies section
++ Include infinate scrolling with the initial results
++ Use the [Youtube API](https://developers.google.com/youtube/v3/) to load a trailer into the detailed results area
diff --git a/index.html b/index.html
index 5956140..96707b6 100644
--- a/index.html
+++ b/index.html
@@ -2,11 +2,27 @@
- React cinema app
+
+
+
+ { /* render Pagination component for 10 or more total pages */ }
+ {(this.state.pages > 10 && qLength > 2) ?
+
:
+
+ }
+
+ { /* render Search component */ }
+
+
+ { /* render message for errors or invalid input for SearchResults component */ }
+ {(errorMsg !== "" && searchDisplayOn) ?
+
{errorMsg}
:
+ (searchDisplayOn &&
+
)
+ }
+
+
+
+
+
+ { /* if a movie has NOT been selected render a loading message */ }
+ {(this.state.searchQuery === "") ?
+
Find movies quickly and easily
: ""
+ }
+
+ {/* if a movie has been selected render MovieDisplay component */}
+ {(this.state.searchQuery !== "") &&
}
+
+
+
)
}
}
-export default App;
+export default App;
\ No newline at end of file
diff --git a/src/components/MovieDisplay.js b/src/components/MovieDisplay.js
new file mode 100644
index 0000000..c1667a3
--- /dev/null
+++ b/src/components/MovieDisplay.js
@@ -0,0 +1,78 @@
+import React from 'react';
+import cx from "classnames";
+// @ts-ignore
+import noImage from '../images/no-image.png';
+
+class MovieDisplay extends React.Component {
+ constructor (props) {
+ super(props)
+ this.toggleTextDisplay = this.toggleTextDisplay.bind(this)
+ this.state = { textDisplay: false }
+ }
+
+ toggleTextDisplay () {
+ this.setState ({ textDisplay: !this.state.textDisplay })
+ }
+
+ render () {
+ // ignore these properties when looping through all the keys so they don't display in the content
+ const ignore = ["Website", "Poster", "Title", "Plot", "Response", "Ratings"];
+ const movie = this.props.currentMovie;
+ const imdbURL = `https://www.imdb.com/title/${movie.imdbID}`;
+ const imgURL = (!movie.Poster || movie.Poster === "N/A") ? noImage : movie.Poster;
+ const noPlot = !movie.Plot || movie.Plot === "N/A";
+
+ // toggle the visibility of the search results display
+ const classes = cx({
+ "article__text-full": this.state.textDisplay,
+ "article__text-none": !this.state.textDisplay
+ })
+
+ return (
+
+
+ {/* render HTML for displaying movie info */}
+
+
+ { movie &&

}
+
+
+
+ { movie &&

}
+
+
+ { (noPlot) ||
Plot
}
+ { (noPlot) || movie.Plot}
+ { movie &&
}
+
+
+ { // display details which ar not set to "N/A"
+ Object.keys(movie)
+ .filter(n => ignore.indexOf(n) < 0)
+ .reduce((acc, item) => {
+ if (movie[item] && movie[item] !== "N/A") {
+ acc.push(- {item}: {movie[item]}
)
+ }
+ return acc;
+ }, [])
+ }
+
+ {
+ (!movie.Website || movie.Website === "N/A") || - Visit website
+ }
+ {
+ movie && - View details on IMDB
+ }
+
+
+
+
+ )
+ }
+}
+
+export default MovieDisplay
\ No newline at end of file
diff --git a/src/components/Pagination.js b/src/components/Pagination.js
new file mode 100644
index 0000000..689cb6f
--- /dev/null
+++ b/src/components/Pagination.js
@@ -0,0 +1,53 @@
+import React from 'react';
+
+class Pagination extends React.Component {
+ constructor (props) {
+ super(props)
+ this.handleClick = this.handleClick.bind(this)
+ this.getClass = this.getClass.bind(this)
+ this.state = { activePage: 1 }
+ }
+
+ handleClick(pageNumber, event) {
+ this.props.receivePageNumber(event.target.id)
+ this.setState({ activePage: pageNumber });
+ }
+
+ // toggle selected button for pages
+ getClass(pageNumber) {
+ return (pageNumber === this.state.activePage) ? "page__button-selected" : "page__button-none"
+ }
+
+ render () {
+
+ const totalPages = this.props.pages || 1;
+ const totalButtons = Math.ceil(totalPages / 10);
+ // create an array of numbers between 1 and totalButtons
+ const totalArray = (max=1, n=1) => new Array(max).fill(0).map(e => e = n++);
+ return (
+
+ {
+ // display page n of max pages
+ // (totalButtons > 1) && (
Page currentPage of {totalButtons}
)
+ }
+
+ {
+
+ // generate page buttons
+ totalArray(totalButtons).map(item => {
+ return
this.handleClick(item, event)}>
+ {item}
+
+ })
+ }
+
+
+ )
+ }
+}
+
+export default Pagination
diff --git a/src/components/Search.js b/src/components/Search.js
new file mode 100644
index 0000000..fce560d
--- /dev/null
+++ b/src/components/Search.js
@@ -0,0 +1,47 @@
+import React from 'react';
+
+class Search extends React.Component {
+ constructor (props) {
+ super(props)
+ this.handleChange = this.handleChange.bind(this)
+ this.handleSubmit = this.handleSubmit.bind(this)
+ this.handleFocus = this.handleFocus.bind(this)
+ this.handleBlur = this.handleBlur.bind(this)
+ }
+
+ handleChange (event) {
+ this.props.receiveInput(event.target.value)
+ }
+
+ handleSubmit (event) {
+ event.preventDefault()
+ this.props.receiveSubmit()
+ }
+
+ handleFocus () {
+ this.props.receiveFocus()
+ }
+
+ handleBlur () {
+ this.props.receiveBlur()
+ }
+
+ render () {
+ return (
+
+ )
+ }
+}
+
+export default Search;
diff --git a/src/components/SearchResults.js b/src/components/SearchResults.js
new file mode 100644
index 0000000..d050f50
--- /dev/null
+++ b/src/components/SearchResults.js
@@ -0,0 +1,45 @@
+import React from 'react';
+import cx from "classnames";
+
+// show a list of 10 search results from user input
+
+class SearchResults extends React.Component {
+
+ constructor (props) {
+ super(props)
+ this.handleClick = this.handleClick.bind(this)
+ }
+
+ // send the selected ID to App
+ handleClick (event) {
+ this.props.receiveMovieID(event.target.id)
+ }
+
+ render () {
+ // toggle search results display with classNames
+ const classes = cx({
+ "search-results": this.props.searchDisplay,
+ "search-results-hidden": !this.props.searchDisplay
+ })
+
+ return (
+
+ {
+ // render 10 results as clickable buttons
+ this.props.resultsArray.map(movie => {
+ return
+ {movie.Title}
+
+ })
+ }
+
+ )
+ }
+}
+
+export default SearchResults
\ No newline at end of file
diff --git a/src/components/SetInnerHTML.js b/src/components/SetInnerHTML.js
new file mode 100644
index 0000000..4d54c72
--- /dev/null
+++ b/src/components/SetInnerHTML.js
@@ -0,0 +1,13 @@
+import React from 'react';
+
+class SetInnerHTML extends React.Component {
+
+ render () {
+ return (
+
+
+ )
+ }
+}
+
+export default SetInnerHTML;
diff --git a/src/images/no-image.png b/src/images/no-image.png
new file mode 100644
index 0000000..26d2cab
Binary files /dev/null and b/src/images/no-image.png differ
diff --git a/src/images/popcorn-bg-pink.png b/src/images/popcorn-bg-pink.png
new file mode 100644
index 0000000..2413711
Binary files /dev/null and b/src/images/popcorn-bg-pink.png differ
diff --git a/src/images/popcorn-bg-smaller-brighter-pink.afphoto b/src/images/popcorn-bg-smaller-brighter-pink.afphoto
new file mode 100644
index 0000000..37ed2e4
Binary files /dev/null and b/src/images/popcorn-bg-smaller-brighter-pink.afphoto differ
diff --git a/src/images/popcorn-bg-smaller-brighter.afphoto b/src/images/popcorn-bg-smaller-brighter.afphoto
new file mode 100644
index 0000000..fb42575
Binary files /dev/null and b/src/images/popcorn-bg-smaller-brighter.afphoto differ
diff --git a/src/images/popcorn-bg-smaller-brighter.png b/src/images/popcorn-bg-smaller-brighter.png
new file mode 100644
index 0000000..be7ecbb
Binary files /dev/null and b/src/images/popcorn-bg-smaller-brighter.png differ
diff --git a/src/images/popcorn-bg-smaller.afphoto b/src/images/popcorn-bg-smaller.afphoto
new file mode 100644
index 0000000..5c78193
Binary files /dev/null and b/src/images/popcorn-bg-smaller.afphoto differ
diff --git a/src/images/popcorn-bg-smaller.png b/src/images/popcorn-bg-smaller.png
new file mode 100644
index 0000000..15ddf15
Binary files /dev/null and b/src/images/popcorn-bg-smaller.png differ
diff --git a/src/images/popcorn-bg.afphoto b/src/images/popcorn-bg.afphoto
new file mode 100644
index 0000000..c98c65b
Binary files /dev/null and b/src/images/popcorn-bg.afphoto differ
diff --git a/src/images/popcorn-bg.png b/src/images/popcorn-bg.png
new file mode 100644
index 0000000..05a02d2
Binary files /dev/null and b/src/images/popcorn-bg.png differ
diff --git a/src/images/react-cinema-screenshot-ipad.afphoto b/src/images/react-cinema-screenshot-ipad.afphoto
new file mode 100644
index 0000000..525c7e0
Binary files /dev/null and b/src/images/react-cinema-screenshot-ipad.afphoto differ
diff --git a/src/images/react-cinema-screenshot-ipad.png b/src/images/react-cinema-screenshot-ipad.png
new file mode 100644
index 0000000..b566bf1
Binary files /dev/null and b/src/images/react-cinema-screenshot-ipad.png differ
diff --git a/src/images/react-cinema-screenshot-mobile.afphoto b/src/images/react-cinema-screenshot-mobile.afphoto
new file mode 100644
index 0000000..2ba33e9
Binary files /dev/null and b/src/images/react-cinema-screenshot-mobile.afphoto differ
diff --git a/src/images/react-cinema-screenshot-mobile.png b/src/images/react-cinema-screenshot-mobile.png
new file mode 100644
index 0000000..9d86872
Binary files /dev/null and b/src/images/react-cinema-screenshot-mobile.png differ
diff --git a/src/images/trailer.js b/src/images/trailer.js
new file mode 100644
index 0000000..2837152
--- /dev/null
+++ b/src/images/trailer.js
@@ -0,0 +1,28 @@
+let id = "tt0307987";
+let trailerURL = `https://api.themoviedb.org/3/movie/${movies.imdbID}/videos?api_key=8aed3c92a5c6ef5e792ffaf51ac22616&language=en-US`
+
+// https://api.themoviedb.org/3/movie/tt0307987/videos?api_key=8aed3c92a5c6ef5e792ffaf51ac22616&language=en-US
+
+fetchTrailer(trailerURL);
+
+function fetchTrailer(trailerURL){
+ fetch(trailerURL)
+ .then(function(response) {
+ return response.json();
+ })
+ .then(function(result){
+ if (result.Response === 'False') {
+ console.log(result)
+ } else {
+ trailerVideo(result);
+ }
+ });
+
+}
+
+function trailerVideo(result){
+ trailerClip = `https://www.youtube.com/watch?v=${result.results[0].key}`;
+ // https://www.youtube.com/watch?v=xQvaoRScND4
+};
+
+console.log(trailerClip);
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
index e0728fe..bdcdb9e 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,8 +1,9 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
+import "./styles.css";
ReactDOM.render(
,
document.getElementById('root')
-);
+);
\ No newline at end of file
diff --git a/src/styles.css b/src/styles.css
new file mode 100644
index 0000000..0173005
--- /dev/null
+++ b/src/styles.css
@@ -0,0 +1,562 @@
+:root {
+ --main-txt-color: #0a0a0a;
+ --light-color: rgb(255, 60, 128);
+ --bright-color:rgb(255, 0, 89);
+ --dark-color: rgb(0, 0, 0);
+ --header-color: rgb(0, 0, 0);
+ --footer-color: rgb(0, 0, 0);
+ --shadow-color: rgba(92, 58, 70, 0.639);
+ --content-color: rgb(171, 161, 161);
+ --lightest-color: rgb(255, 255, 255);
+ --main-padding: 1rem;
+ }
+
+* {
+ box-sizing: inherit;
+}
+
+html {
+ scroll-behavior:smooth;
+ background-color: var(--footer-color);
+}
+
+body {
+ font-family: 'Open Sans', Arial, Helvetica, sans-serif;
+ margin: 0;
+ box-sizing: border-box;
+ font-size: 1rem;
+ line-height: 1.7rem;
+ letter-spacing: 0.02rem;
+ background-color: var(--dark-color);
+}
+
+.content {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ margin: 0;
+ padding: 0;
+ background-color: var(--content-color);
+ background-image: url("./images/popcorn-bg-smaller-brighter.png");
+}
+
+.loading-message {
+ padding: 5rem 0;
+ font-weight: 700;
+ font-size: 3rem;
+ line-height: 3rem;
+ text-align: center;
+ color: var(--bright-color);
+ filter: drop-shadow(3px 3px 5px rgb(255, 255, 255));
+}
+
+/* HEADER ////////////////////////////////////////// */
+
+header {
+ display: flex;
+ flex-direction: row;
+ /* flex: 1; */
+ justify-content: center;
+ /* position: fixed; */
+ top: 0;
+ left: 0;
+ width: 100%;
+ margin: 0;
+ padding: 1rem;
+ vertical-align: bottom;
+ background-color: var(--header-color);
+ /* border-bottom: 2px solid var(--bright-color); */
+}
+
+h3 {
+ text-decoration: none;
+ border-bottom: 2px solid var(--bright-color);
+ display: initial;
+ width: 2.3rem;
+}
+
+.title {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ vertical-align: middle;
+ justify-content: center;
+ margin: 0;
+ list-style: none;
+ letter-spacing: 0.05rem;
+
+}
+
+.title li {
+ font-size: 2rem;
+}
+
+.title-light {
+ float: left;
+ font-style: inherit;
+ padding-left: 0.5rem;
+ padding-top: 0.1rem;
+ font-weight: 700;
+ font-size: 1rem;
+ /* color: rgb(136, 193, 255); */
+ color: var(--bright-color);
+ }
+
+.title-dark {
+ font-style: inherit;
+ padding-left: 0.5rem;
+ padding-top: 0.2rem;
+ font-weight: 400;
+ font-size: 1rem;
+ color: rgb(157, 204, 255);
+}
+
+.underline {
+ border-bottom: solid 0.1rem #ff2108;
+ padding-bottom: 0.3rem;
+}
+
+/* ROOT /////////////////////////////////////////////*/
+
+
+#root {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ flex: 4;
+ min-height: 600px;
+ margin: 0;
+ /* margin: 1rem 1rem 1rem 1rem; */
+}
+
+
+.app {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ padding: 0;
+ margin: 2em;
+}
+
+/* SEARCH ////////////////////////////////////////// */
+
+.search-wrapper {
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+}
+
+input[type=text]:focus {
+ background-color: white;
+}
+
+input[type=text]:blur {
+ filter: drop-shadow(5px 5px 0 var(--shadow-color));
+ width: 100%;
+}
+
+.search {
+ font-size: 1rem;
+ line-height: 1.5rem;
+ height: 3rem;
+ padding-left: 1rem;
+ border: none;
+ box-sizing: border-box;
+ background-color: white;
+ filter: drop-shadow(8px 8px 0 var(--shadow-color));
+ border: 1px solid lightgrey;
+ color: var(--bright-color);
+}
+
+.search-results, .error {
+ font-size: 1rem;
+ line-height: 1.5rem;
+ border: 1px solid lightgrey;
+ border-top: 0;
+ border-bottom: 0;
+ width: 20rem;
+ background-color: white;
+ color: rgb(69, 69, 69);
+ /* min-width: 300px;
+ max-width: 450px; */
+ filter: drop-shadow(9px 9px 1px var(--shadow-color));
+}
+
+.search, .search-results, .error {
+ width: 100%;
+ min-width: 300px;
+ max-width: 300px;
+}
+
+.search-results-hidden {
+ display: none;
+}
+
+.error {
+ color: var(--dark-color);
+}
+
+.search-item, .error {
+ border-bottom: 1px solid lightgrey;
+ padding: 0.5rem 0.5rem 0.5rem 1rem;
+}
+
+.search-item {
+ cursor: pointer;
+ display: block;
+ color: rgb(69, 69, 69);
+ text-decoration: none;
+}
+
+.search-item:hover {
+ color: var(--bright-color);
+ background: rgb(245, 245, 245);
+}
+
+/* MOVIE DISPLAY ////////////////////////////////////////// */
+
+.movie-display {
+ background-color: rgb(0, 0, 0);
+ margin: 1rem 0;
+ padding: 1.5rem;
+ color: white;
+}
+
+.article__main {
+ display: flex;
+ justify-content: flex-start;
+ flex-direction: column;
+ padding: 0;
+ margin: 2rem 0 1rem 0;
+ filter: drop-shadow(8px 8px 0 var(--shadow-color));
+ width: 100%;
+ min-width: 300px;
+ max-width: 300px;
+}
+
+.article__main li {
+ padding: 0.3em 0;
+}
+
+.article__main li a {
+ list-style: none;
+}
+
+.article__main a, a.article__main li {
+ list-style: none;
+}
+
+.article__header {
+ display: block;
+ font-size: 2.2rem;
+ background-color:rgb(227, 227, 227);
+ color: var(--bright-color);
+ padding: 1.5rem;
+ height: 30%;
+ text-decoration: none;
+ border-bottom: 1px solid #ddd;
+ background: #eee;
+ line-height: 3rem;
+}
+
+.article__header a {
+ color: black;
+ background: #eee;
+ text-decoration: none;
+ list-style: none;
+}
+
+.article__header a:hover {
+ background: #eee;
+ text-decoration: underline;
+}
+
+.article__image-mobile {
+ display: initial;
+}
+
+.article__image-ipad {
+ display: none;
+}
+
+.article__image__src {
+ display: block;
+ object-fit: cover;
+ width: 100%;
+ min-width: 300px;
+ max-width: 300px;
+}
+
+.article__text {
+ display: flex;
+ justify-content: flex-start;
+ flex-direction: column;
+ flex: 3;
+ font-size: 1rem;
+ background: #fff;
+ color: black;
+ padding: 1.5rem;
+ margin: 0;
+ list-style: none;
+}
+
+.article__text-full {
+ display: block;
+}
+
+.article__text-none {
+ display: none;
+}
+
+.article__text a {
+ text-decoration: none;
+ font-weight: normal;
+ list-style: none;
+ height: 60%;
+ display: initial;
+ background-color: #ddd;
+ padding: 0.5em 1rem 0.5rem 1rem;
+ margin: 1.5em 0 0 0;
+ line-height: 3rem;
+ color: black;
+ list-style: none;
+ border-radius: 0.2rem;
+ cursor: pointer;
+}
+
+.article__text a:hover {
+ background: var(--bright-color);
+ color: white;
+ /* border: solid 1px #ff2108; */
+}
+
+.article__text div {
+ padding: 0.5em 0;
+ border: 0;
+}
+
+.article__text ul {
+ padding: 0;
+ margin: 0;
+}
+
+.article__text ul li {
+ line-height: 2rem;
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.article__text ul li a, a.article__text ul, a.article__text li {
+ list-style: none;
+}
+
+/* FOOTER ////////////////////////////////////////// */
+
+.footer {
+ display: flex;
+ /* flex: 1; */
+ flex-direction: column;
+ text-align: center;
+ margin: 0;
+ font-size: 1rem;
+ line-height: 2rem;
+ background-color: var(--footer-color);
+ color:white;
+ padding: 0;
+ border: 0;
+ }
+
+ .footer__contact {
+ text-align: center;
+ border: 0;
+ }
+
+ .pad-top {
+ padding-top: 1.5rem;
+ }
+ .pad-bottom {
+ padding-bottom: 2.5rem;
+ }
+
+ .footer__contact a {
+ font-weight: 700;
+ padding: 0.2rem 0.3rem 0.1rem 0.3rem;
+ text-decoration: none;
+ }
+
+ .footer__contact a:link,
+ .footer__contact a:visited {
+ background: rgb(0, 0, 0);
+ color:var(--bright-color);
+ }
+
+ .footer__contact a:hover {
+ text-decoration-line: none;
+ background: var(--bright-color);
+ color:white;
+ }
+
+
+/* PAGINATION ////////////////////////////////////////// */
+
+.pagination {
+ display: flex;
+ flex-direction: row;
+ overflow: auto;
+ white-space: nowrap;
+ width: 100%;
+ height: 60px;
+ max-width: 300px;
+ padding: 0 0 0.5rem 0;
+ margin: 0 0 0.5rem 0;
+}
+
+.page__button-none, .page__button-selected {
+ padding: 0 0.5rem;
+ margin: 0 0.2rem;
+ border-radius: 3px;
+ color: white;
+ cursor: pointer;
+ height: 28px;
+ filter: drop-shadow(0 0 3px rgb(255, 255, 255));
+}
+
+.page__button-none {
+ background-color: var(--bright-color);
+}
+
+.page__button-selected {
+ background-color: var(--dark-color);
+}
+
+.page__button-none:hover {
+ background-color: var(--dark-color);
+}
+
+ @media (min-width: 768px) {
+
+ #root {
+ min-height: auto;
+ }
+
+ .results-list, input {
+ width: 100%;
+ min-width:350px;
+ max-width:350px;
+ }
+
+ .results-pages {
+ padding-top: 1rem;
+ padding-bottom: 1rem;
+ }
+
+ .app {
+ display: flex;
+ flex-direction: row;
+ vertical-align: top;
+ /* flex-direction: column;
+ justify-content: center;
+ align-items: center; */
+ padding: 0;
+ margin: 2em;
+ }
+
+ /* delete .search-wrapper? */
+
+ .search-wrapper {
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ min-height: 650px;
+ }
+
+ .article__main {
+ width: 100%;
+ /* min-width: 350px; */
+ min-height: 650px;
+ max-width: 350px;
+ margin: 0 0 0 2rem;
+ }
+
+ .article__image__src {
+ display: initial;
+ object-fit: cover;
+ width: 150px;
+ min-width: 75px;
+ max-width: 150px;
+ }
+
+ .show-for-mobile {
+ display: none;
+ margin-left: 2.5rem;
+ margin-top: 1rem;
+ }
+
+ .hide-for-mobile {
+ display: initial;
+ margin-top: 1rem;
+ /* border: 3px solid rgb(25, 0, 255); */
+ }
+
+ .article__photo__wrapper {
+ display: flex;
+ flex-direction: row;
+ background: white;
+ }
+
+ .article__image-mobile {
+ display: none;
+ }
+
+ .article__image-ipad {
+ display: initial;
+ padding: 1rem 0 0 1rem;
+ margin: 0;
+ background-color: white;
+ }
+
+ .article__photo__keypoint{
+ color: #000;
+ padding-right: 1em;
+ }
+ li.article__photo__keypoint {
+ padding-left: 0;
+ margin-left: 0;
+ line-height: 2rem;
+ }
+
+ h3 {
+ margin-top: 2em;
+ }
+
+ .film-content, .film-content.on {
+ display: none;
+ }
+
+ .film-content-ipad {
+ display: block;
+ background: black;
+ color: rgb(165, 165, 165);
+ padding:2rem;
+ margin: 1rem 1rem 2rem 1rem;
+ width: 100%;
+ }
+
+ .article__text li {
+ line-height: 2rem;
+ }
+
+ .loading-message {
+ padding: 4rem 2rem;
+ font-weight: 700;
+ font-size: 3rem;
+ line-height: 3rem;
+ text-align: center;
+ color: var(--bright-color);
+ filter: drop-shadow(3px 3px 5px rgb(255, 255, 255));
+ min-height: 650px
+ }
+
+}
\ No newline at end of file
diff --git a/style.css b/style.css
deleted file mode 100644
index e69de29..0000000
diff --git a/webpack.config.js b/webpack.config.js
index 9355dc3..beb1aed 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,10 +1,27 @@
const path = require('path');
+const webpack = require('webpack');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
+const CleanWebpackPlugin = require('clean-webpack-plugin');
+
+require('dotenv').config();
module.exports = {
+ mode: process.env.NODE_ENV,
entry: './src/index.js',
devtool: 'source-map',
+ plugins: [
+ new CleanWebpackPlugin(['dist']),
+ new webpack.DefinePlugin({
+ 'process.env': {
+ API_KEY: JSON.stringify(process.env.API_KEY)
+ }
+ }),
+ new HtmlWebpackPlugin({
+ template: path.resolve(__dirname, './src/assets/index.template.html')
+ })
+ ],
output: {
- filename: 'bundle.js',
+ filename: 'bundle.[hash].js',
path: path.resolve(__dirname, 'dist')
},
module: {
@@ -13,7 +30,16 @@ module.exports = {
test: /\.js$/,
exclude: /(node_modules)/,
loader: require.resolve('babel-loader')
+ },
+ {
+ test: /\.css$/,
+ use: ['style-loader', 'css-loader']
+ },
+ {
+ test: /\.(png|svg|jpg|gif)$/,
+ use: ['file-loader']
}
+
]
}
};