From 1d683f20ca8c7c0e8852a3c2555a120ac4d281a6 Mon Sep 17 00:00:00 2001 From: anton-karlovskiy-g Date: Sun, 20 Dec 2020 18:13:22 +0300 Subject: [PATCH] push the original project --- .editorconfig | 13 + .env.sample | 17 + .eslintrc.js | 25 + .gitignore | 18 + Procfile | 1 + README.md | 24 +- api/index.js | 516 + assets/README.md | 9 + assets/css/base/_base.scss | 106 + assets/css/base/_forms.scss | 75 + assets/css/base/_layout.scss | 19 + assets/css/base/_lazyload.scss | 10 + assets/css/base/_normalize.scss | 344 + assets/css/base/_transitions.scss | 26 + assets/css/base/_typography.scss | 16 + assets/css/components/_alert.scss | 94 + assets/css/components/_card.scss | 102 + assets/css/components/_carousel.scss | 188 + assets/css/components/_listing.scss | 105 + assets/css/global.scss | 12 + assets/css/utilities/_helpers.scss | 15 + assets/css/utilities/_variables.scss | 24 + assets/images/loader.svg | 1 + assets/images/select-arrow.svg | 1 + assets/images/stars-filled.png | Bin 0 -> 2988 bytes assets/images/stars.png | Bin 0 -> 2751 bytes components/Card.vue | 81 + components/Credits.vue | 74 + components/CreditsItem.vue | 117 + components/ExternalLinks.vue | 81 + components/Hero.vue | 373 + components/Images.vue | 147 + components/ImagesItem.vue | 120 + components/Listing.vue | 113 + components/ListingCarousel.vue | 110 + components/MediaNav.vue | 94 + components/Modal.vue | 472 + components/README.md | 7 + components/Videos.vue | 155 + components/VideosItem.vue | 216 + components/global/CookieConsent.vue | 81 + components/global/Footer.vue | 100 + components/global/InstallPrompt.vue | 80 + components/global/Nav.vue | 141 + components/global/SearchForm.vue | 140 + components/global/TopNav.vue | 86 + components/movie/MovieInfo.vue | 319 + components/person/CreditsHistory.vue | 302 + components/person/CreditsHistoryGroup.vue | 44 + components/person/CreditsHistoryItem.vue | 112 + components/person/PersonInfo.vue | 322 + components/search/SearchResults.vue | 83 + components/tv/Episodes.vue | 135 + components/tv/EpisodesItem.vue | 136 + components/tv/TvInfo.vue | 332 + layouts/README.md | 9 + layouts/default.vue | 39 + layouts/error.vue | 84 + layouts/no-footer.vue | 16 + middleware/README.md | 10 + mixins/Carousel.js | 73 + mixins/Details.js | 150 + mixins/Functions.js | 34 + nuxt.config.js | 109 + package.json | 40 + pages/README.md | 8 + pages/genre/_id/movie.vue | 89 + pages/genre/_id/tv.vue | 89 + pages/index.vue | 72 + pages/movie/_id.vue | 195 + pages/movie/category/_name.vue | 88 + pages/movie/index.vue | 101 + pages/person/_id.vue | 195 + pages/search/index.vue | 135 + pages/tv/_id.vue | 212 + pages/tv/category/_name.vue | 88 + pages/tv/index.vue | 101 + plugins/README.md | 9 + plugins/filters.js | 104 + plugins/ga.js | 48 + plugins/lazyload.js | 81 + static/README.md | 12 + static/favicon.ico | Bin 0 -> 398 bytes static/icon-medium.png | Bin 0 -> 1311 bytes static/icon.png | Bin 0 -> 5503 bytes store/README.md | 11 + store/search.js | 22 + yarn.lock | 10491 ++++++++++++++++++++ 88 files changed, 19048 insertions(+), 1 deletion(-) create mode 100644 .editorconfig create mode 100644 .env.sample create mode 100644 .eslintrc.js create mode 100644 .gitignore create mode 100644 Procfile create mode 100644 api/index.js create mode 100644 assets/README.md create mode 100644 assets/css/base/_base.scss create mode 100644 assets/css/base/_forms.scss create mode 100644 assets/css/base/_layout.scss create mode 100644 assets/css/base/_lazyload.scss create mode 100644 assets/css/base/_normalize.scss create mode 100644 assets/css/base/_transitions.scss create mode 100644 assets/css/base/_typography.scss create mode 100644 assets/css/components/_alert.scss create mode 100644 assets/css/components/_card.scss create mode 100644 assets/css/components/_carousel.scss create mode 100644 assets/css/components/_listing.scss create mode 100644 assets/css/global.scss create mode 100644 assets/css/utilities/_helpers.scss create mode 100644 assets/css/utilities/_variables.scss create mode 100644 assets/images/loader.svg create mode 100644 assets/images/select-arrow.svg create mode 100644 assets/images/stars-filled.png create mode 100644 assets/images/stars.png create mode 100644 components/Card.vue create mode 100644 components/Credits.vue create mode 100644 components/CreditsItem.vue create mode 100644 components/ExternalLinks.vue create mode 100644 components/Hero.vue create mode 100644 components/Images.vue create mode 100644 components/ImagesItem.vue create mode 100644 components/Listing.vue create mode 100644 components/ListingCarousel.vue create mode 100644 components/MediaNav.vue create mode 100644 components/Modal.vue create mode 100644 components/README.md create mode 100644 components/Videos.vue create mode 100644 components/VideosItem.vue create mode 100644 components/global/CookieConsent.vue create mode 100644 components/global/Footer.vue create mode 100644 components/global/InstallPrompt.vue create mode 100644 components/global/Nav.vue create mode 100644 components/global/SearchForm.vue create mode 100644 components/global/TopNav.vue create mode 100644 components/movie/MovieInfo.vue create mode 100644 components/person/CreditsHistory.vue create mode 100644 components/person/CreditsHistoryGroup.vue create mode 100644 components/person/CreditsHistoryItem.vue create mode 100644 components/person/PersonInfo.vue create mode 100644 components/search/SearchResults.vue create mode 100644 components/tv/Episodes.vue create mode 100644 components/tv/EpisodesItem.vue create mode 100644 components/tv/TvInfo.vue create mode 100644 layouts/README.md create mode 100644 layouts/default.vue create mode 100644 layouts/error.vue create mode 100644 layouts/no-footer.vue create mode 100644 middleware/README.md create mode 100644 mixins/Carousel.js create mode 100644 mixins/Details.js create mode 100644 mixins/Functions.js create mode 100644 nuxt.config.js create mode 100644 package.json create mode 100644 pages/README.md create mode 100644 pages/genre/_id/movie.vue create mode 100644 pages/genre/_id/tv.vue create mode 100644 pages/index.vue create mode 100644 pages/movie/_id.vue create mode 100644 pages/movie/category/_name.vue create mode 100644 pages/movie/index.vue create mode 100644 pages/person/_id.vue create mode 100644 pages/search/index.vue create mode 100644 pages/tv/_id.vue create mode 100644 pages/tv/category/_name.vue create mode 100644 pages/tv/index.vue create mode 100644 plugins/README.md create mode 100644 plugins/filters.js create mode 100644 plugins/ga.js create mode 100644 plugins/lazyload.js create mode 100644 static/README.md create mode 100644 static/favicon.ico create mode 100644 static/icon-medium.png create mode 100644 static/icon.png create mode 100644 store/README.md create mode 100644 store/search.js create mode 100644 yarn.lock diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..5d12634 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +# editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..b2601a2 --- /dev/null +++ b/.env.sample @@ -0,0 +1,17 @@ +# FRONTEND_URL +FRONTEND_URL=http://localhost:3000 + +# API key from the movie db +API_KEY= + +# API lang +API_LANG=en-US + +# API country +API_COUNTRY=GB + +# YouTube API key +API_YOUTUBE_KEY= + +# Google Analytics +GA=UA-000000000-0 diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..03b3511 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,25 @@ +module.exports = { + root: true, + env: { + browser: true, + node: true + }, + parserOptions: { + parser: 'babel-eslint' + }, + extends: [ + '@nuxtjs' + ], + // add your custom rules here + rules: { + 'vue/html-closing-bracket-newline': ['error', { + 'singleline': 'never', + 'multiline': 'never', + }], + 'vue/no-v-html': ['never'], + 'comma-dangle': ['error', 'always-multiline'], + 'semi': ['error', 'always'], + 'space-before-function-paren': ['error', 'always'], + 'no-console': ['warn'], + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..073f80d --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +# dependencies +node_modules + +# logs +npm-debug.log +yarn-error.log + +# Nuxt build +.nuxt + +# Nuxt generate +dist + +# Environment files +.env + +# @nuxtjs/pwa +sw.* diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..28fe750 --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: npm run start diff --git a/README.md b/README.md index ddb33e4..80854fd 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,24 @@ # nuxt-movies -Nuxt.js Movies + +Progressive web app featuring movies and tv shows from [The Movie Database (TMDb)](https://developers.themoviedb.org/3) API. Built using [Vue.js](https://github.com/vuejs/vue) and [Nuxt.js](https://github.com/nuxt/nuxt.js). + +Live demo hosted on Heroku can be found at [https://movies.jason.codes](https://movies.jason.codes). + +Built as a side project to learn some new skills 🔥🔥 + +## Quick setup + +1. Take a copy of `.env.sample` and re-name to `.env` +2. Get your [TMDb](https://developers.themoviedb.org/3) API key +3. Get your [YouTube](https://developers.google.com/youtube/v3/getting-started) API key (optional, used for video data) +4. Enter the details into the `.env` file + +## Running + +``` bash +# install dependencies +$ npm install # Or yarn install + +# serve with hot reload at localhost:3000 +$ npm run dev +``` diff --git a/api/index.js b/api/index.js new file mode 100644 index 0000000..d9e4732 --- /dev/null +++ b/api/index.js @@ -0,0 +1,516 @@ +import axios from 'axios'; + +/** + * API url + */ +const apiUrl = 'https://api.themoviedb.org/3'; + +/** + * Image url + */ +export const apiImgUrl = 'https://image.tmdb.org/t/p'; + +/** + * Different types of lists + */ +const lists = { + movie: [ + { title: 'Trending Movies', query: 'trending' }, + { title: 'Popular Movies', query: 'popular' }, + { title: 'Top Rated Movies', query: 'top_rated' }, + { title: 'Upcoming Movies', query: 'upcoming' }, + { title: 'Now Playing Movies', query: 'now_playing' }, + ], + tv: [ + { title: 'Trending TV Shows', query: 'trending' }, + { title: 'Popular TV Shows', query: 'popular' }, + { title: 'Top Rated TV Shows', query: 'top_rated' }, + { title: 'Currently Airing TV Shows', query: 'on_the_air' }, + { title: 'TV Shows Airing Today', query: 'airing_today' }, + ], +}; + +/** + * Different languages with full name + */ +export const languages = [ + { 'iso_639_1': 'xx', 'english_name': 'No Language' }, + { 'iso_639_1': 'aa', 'english_name': 'Afar' }, + { 'iso_639_1': 'af', 'english_name': 'Afrikaans' }, + { 'iso_639_1': 'ak', 'english_name': 'Akan' }, + { 'iso_639_1': 'an', 'english_name': 'Aragonese' }, + { 'iso_639_1': 'as', 'english_name': 'Assamese' }, + { 'iso_639_1': 'av', 'english_name': 'Avaric' }, + { 'iso_639_1': 'ae', 'english_name': 'Avestan' }, + { 'iso_639_1': 'ay', 'english_name': 'Aymara' }, + { 'iso_639_1': 'az', 'english_name': 'Azerbaijani' }, + { 'iso_639_1': 'ba', 'english_name': 'Bashkir' }, + { 'iso_639_1': 'bm', 'english_name': 'Bambara' }, + { 'iso_639_1': 'bi', 'english_name': 'Bislama' }, + { 'iso_639_1': 'bo', 'english_name': 'Tibetan' }, + { 'iso_639_1': 'br', 'english_name': 'Breton' }, + { 'iso_639_1': 'ca', 'english_name': 'Catalan' }, + { 'iso_639_1': 'cs', 'english_name': 'Czech' }, + { 'iso_639_1': 'ce', 'english_name': 'Chechen' }, + { 'iso_639_1': 'cu', 'english_name': 'Slavic' }, + { 'iso_639_1': 'cv', 'english_name': 'Chuvash' }, + { 'iso_639_1': 'kw', 'english_name': 'Cornish' }, + { 'iso_639_1': 'co', 'english_name': 'Corsican' }, + { 'iso_639_1': 'cr', 'english_name': 'Cree' }, + { 'iso_639_1': 'cy', 'english_name': 'Welsh' }, + { 'iso_639_1': 'da', 'english_name': 'Danish' }, + { 'iso_639_1': 'de', 'english_name': 'German' }, + { 'iso_639_1': 'dv', 'english_name': 'Divehi' }, + { 'iso_639_1': 'dz', 'english_name': 'Dzongkha' }, + { 'iso_639_1': 'eo', 'english_name': 'Esperanto' }, + { 'iso_639_1': 'et', 'english_name': 'Estonian' }, + { 'iso_639_1': 'eu', 'english_name': 'Basque' }, + { 'iso_639_1': 'fo', 'english_name': 'Faroese' }, + { 'iso_639_1': 'fj', 'english_name': 'Fijian' }, + { 'iso_639_1': 'fi', 'english_name': 'Finnish' }, + { 'iso_639_1': 'fr', 'english_name': 'French' }, + { 'iso_639_1': 'fy', 'english_name': 'Frisian' }, + { 'iso_639_1': 'ff', 'english_name': 'Fulah' }, + { 'iso_639_1': 'gd', 'english_name': 'Gaelic' }, + { 'iso_639_1': 'ga', 'english_name': 'Irish' }, + { 'iso_639_1': 'gl', 'english_name': 'Galician' }, + { 'iso_639_1': 'gv', 'english_name': 'Manx' }, + { 'iso_639_1': 'gn', 'english_name': 'Guarani' }, + { 'iso_639_1': 'gu', 'english_name': 'Gujarati' }, + { 'iso_639_1': 'ht', 'english_name': 'Haitian; Haitian Creole' }, + { 'iso_639_1': 'ha', 'english_name': 'Hausa' }, + { 'iso_639_1': 'sh', 'english_name': 'Serbo-Croatian' }, + { 'iso_639_1': 'hz', 'english_name': 'Herero' }, + { 'iso_639_1': 'ho', 'english_name': 'Hiri Motu' }, + { 'iso_639_1': 'hr', 'english_name': 'Croatian' }, + { 'iso_639_1': 'hu', 'english_name': 'Hungarian' }, + { 'iso_639_1': 'ig', 'english_name': 'Igbo' }, + { 'iso_639_1': 'io', 'english_name': 'Ido' }, + { 'iso_639_1': 'ii', 'english_name': 'Yi' }, + { 'iso_639_1': 'iu', 'english_name': 'Inuktitut' }, + { 'iso_639_1': 'ie', 'english_name': 'Interlingue' }, + { 'iso_639_1': 'ia', 'english_name': 'Interlingua' }, + { 'iso_639_1': 'id', 'english_name': 'Indonesian' }, + { 'iso_639_1': 'ik', 'english_name': 'Inupiaq' }, + { 'iso_639_1': 'is', 'english_name': 'Icelandic' }, + { 'iso_639_1': 'it', 'english_name': 'Italian' }, + { 'iso_639_1': 'jv', 'english_name': 'Javanese' }, + { 'iso_639_1': 'ja', 'english_name': 'Japanese' }, + { 'iso_639_1': 'kl', 'english_name': 'Kalaallisut' }, + { 'iso_639_1': 'kn', 'english_name': 'Kannada' }, + { 'iso_639_1': 'ks', 'english_name': 'Kashmiri' }, + { 'iso_639_1': 'kr', 'english_name': 'Kanuri' }, + { 'iso_639_1': 'kk', 'english_name': 'Kazakh' }, + { 'iso_639_1': 'km', 'english_name': 'Khmer' }, + { 'iso_639_1': 'ki', 'english_name': 'Kikuyu' }, + { 'iso_639_1': 'rw', 'english_name': 'Kinyarwanda' }, + { 'iso_639_1': 'ky', 'english_name': 'Kirghiz' }, + { 'iso_639_1': 'kv', 'english_name': 'Komi' }, + { 'iso_639_1': 'kg', 'english_name': 'Kongo' }, + { 'iso_639_1': 'ko', 'english_name': 'Korean' }, + { 'iso_639_1': 'kj', 'english_name': 'Kuanyama' }, + { 'iso_639_1': 'ku', 'english_name': 'Kurdish' }, + { 'iso_639_1': 'lo', 'english_name': 'Lao' }, + { 'iso_639_1': 'la', 'english_name': 'Latin' }, + { 'iso_639_1': 'lv', 'english_name': 'Latvian' }, + { 'iso_639_1': 'li', 'english_name': 'Limburgish' }, + { 'iso_639_1': 'ln', 'english_name': 'Lingala' }, + { 'iso_639_1': 'lt', 'english_name': 'Lithuanian' }, + { 'iso_639_1': 'lb', 'english_name': 'Letzeburgesch' }, + { 'iso_639_1': 'lu', 'english_name': 'Luba-Katanga' }, + { 'iso_639_1': 'lg', 'english_name': 'Ganda' }, + { 'iso_639_1': 'mh', 'english_name': 'Marshall' }, + { 'iso_639_1': 'ml', 'english_name': 'Malayalam' }, + { 'iso_639_1': 'mr', 'english_name': 'Marathi' }, + { 'iso_639_1': 'mg', 'english_name': 'Malagasy' }, + { 'iso_639_1': 'mt', 'english_name': 'Maltese' }, + { 'iso_639_1': 'mo', 'english_name': 'Moldavian' }, + { 'iso_639_1': 'mn', 'english_name': 'Mongolian' }, + { 'iso_639_1': 'mi', 'english_name': 'Maori' }, + { 'iso_639_1': 'ms', 'english_name': 'Malay' }, + { 'iso_639_1': 'my', 'english_name': 'Burmese' }, + { 'iso_639_1': 'na', 'english_name': 'Nauru' }, + { 'iso_639_1': 'nv', 'english_name': 'Navajo' }, + { 'iso_639_1': 'nr', 'english_name': 'Ndebele' }, + { 'iso_639_1': 'nd', 'english_name': 'Ndebele' }, + { 'iso_639_1': 'ng', 'english_name': 'Ndonga' }, + { 'iso_639_1': 'ne', 'english_name': 'Nepali' }, + { 'iso_639_1': 'nl', 'english_name': 'Dutch' }, + { 'iso_639_1': 'nn', 'english_name': 'Norwegian Nynorsk' }, + { 'iso_639_1': 'nb', 'english_name': 'Norwegian Bokmål' }, + { 'iso_639_1': 'no', 'english_name': 'Norwegian' }, + { 'iso_639_1': 'ny', 'english_name': 'Chichewa; Nyanja' }, + { 'iso_639_1': 'oc', 'english_name': 'Occitan' }, + { 'iso_639_1': 'oj', 'english_name': 'Ojibwa' }, + { 'iso_639_1': 'or', 'english_name': 'Oriya' }, + { 'iso_639_1': 'om', 'english_name': 'Oromo' }, + { 'iso_639_1': 'os', 'english_name': 'Ossetian; Ossetic' }, + { 'iso_639_1': 'pi', 'english_name': 'Pali' }, + { 'iso_639_1': 'pl', 'english_name': 'Polish' }, + { 'iso_639_1': 'pt', 'english_name': 'Portuguese' }, + { 'iso_639_1': 'qu', 'english_name': 'Quechua' }, + { 'iso_639_1': 'rm', 'english_name': 'Raeto-Romance' }, + { 'iso_639_1': 'ro', 'english_name': 'Romanian' }, + { 'iso_639_1': 'rn', 'english_name': 'Rundi' }, + { 'iso_639_1': 'ru', 'english_name': 'Russian' }, + { 'iso_639_1': 'sg', 'english_name': 'Sango' }, + { 'iso_639_1': 'sa', 'english_name': 'Sanskrit' }, + { 'iso_639_1': 'si', 'english_name': 'Sinhalese' }, + { 'iso_639_1': 'sk', 'english_name': 'Slovak' }, + { 'iso_639_1': 'sl', 'english_name': 'Slovenian' }, + { 'iso_639_1': 'se', 'english_name': 'Northern Sami' }, + { 'iso_639_1': 'sm', 'english_name': 'Samoan' }, + { 'iso_639_1': 'sn', 'english_name': 'Shona' }, + { 'iso_639_1': 'sd', 'english_name': 'Sindhi' }, + { 'iso_639_1': 'so', 'english_name': 'Somali' }, + { 'iso_639_1': 'st', 'english_name': 'Sotho' }, + { 'iso_639_1': 'es', 'english_name': 'Spanish' }, + { 'iso_639_1': 'sq', 'english_name': 'Albanian' }, + { 'iso_639_1': 'sc', 'english_name': 'Sardinian' }, + { 'iso_639_1': 'sr', 'english_name': 'Serbian' }, + { 'iso_639_1': 'ss', 'english_name': 'Swati' }, + { 'iso_639_1': 'su', 'english_name': 'Sundanese' }, + { 'iso_639_1': 'sw', 'english_name': 'Swahili' }, + { 'iso_639_1': 'sv', 'english_name': 'Swedish' }, + { 'iso_639_1': 'ty', 'english_name': 'Tahitian' }, + { 'iso_639_1': 'ta', 'english_name': 'Tamil' }, + { 'iso_639_1': 'tt', 'english_name': 'Tatar' }, + { 'iso_639_1': 'te', 'english_name': 'Telugu' }, + { 'iso_639_1': 'tg', 'english_name': 'Tajik' }, + { 'iso_639_1': 'tl', 'english_name': 'Tagalog' }, + { 'iso_639_1': 'th', 'english_name': 'Thai' }, + { 'iso_639_1': 'ti', 'english_name': 'Tigrinya' }, + { 'iso_639_1': 'to', 'english_name': 'Tonga' }, + { 'iso_639_1': 'tn', 'english_name': 'Tswana' }, + { 'iso_639_1': 'ts', 'english_name': 'Tsonga' }, + { 'iso_639_1': 'tk', 'english_name': 'Turkmen' }, + { 'iso_639_1': 'tr', 'english_name': 'Turkish' }, + { 'iso_639_1': 'tw', 'english_name': 'Twi' }, + { 'iso_639_1': 'ug', 'english_name': 'Uighur' }, + { 'iso_639_1': 'uk', 'english_name': 'Ukrainian' }, + { 'iso_639_1': 'ur', 'english_name': 'Urdu' }, + { 'iso_639_1': 'uz', 'english_name': 'Uzbek' }, + { 'iso_639_1': 've', 'english_name': 'Venda' }, + { 'iso_639_1': 'vi', 'english_name': 'Vietnamese' }, + { 'iso_639_1': 'vo', 'english_name': 'Volapük' }, + { 'iso_639_1': 'wa', 'english_name': 'Walloon' }, + { 'iso_639_1': 'wo', 'english_name': 'Wolof' }, + { 'iso_639_1': 'xh', 'english_name': 'Xhosa' }, + { 'iso_639_1': 'yi', 'english_name': 'Yiddish' }, + { 'iso_639_1': 'za', 'english_name': 'Zhuang' }, + { 'iso_639_1': 'zu', 'english_name': 'Zulu' }, + { 'iso_639_1': 'ab', 'english_name': 'Abkhazian' }, + { 'iso_639_1': 'zh', 'english_name': 'Mandarin' }, + { 'iso_639_1': 'ps', 'english_name': 'Pushto' }, + { 'iso_639_1': 'am', 'english_name': 'Amharic' }, + { 'iso_639_1': 'ar', 'english_name': 'Arabic' }, + { 'iso_639_1': 'bg', 'english_name': 'Bulgarian' }, + { 'iso_639_1': 'cn', 'english_name': 'Cantonese' }, + { 'iso_639_1': 'mk', 'english_name': 'Macedonian' }, + { 'iso_639_1': 'el', 'english_name': 'Greek' }, + { 'iso_639_1': 'fa', 'english_name': 'Persian' }, + { 'iso_639_1': 'he', 'english_name': 'Hebrew' }, + { 'iso_639_1': 'hi', 'english_name': 'Hindi' }, + { 'iso_639_1': 'hy', 'english_name': 'Armenian' }, + { 'iso_639_1': 'en', 'english_name': 'English' }, + { 'iso_639_1': 'ee', 'english_name': 'Ewe' }, + { 'iso_639_1': 'ka', 'english_name': 'Georgian' }, + { 'iso_639_1': 'pa', 'english_name': 'Punjabi' }, + { 'iso_639_1': 'bn', 'english_name': 'Bengali' }, + { 'iso_639_1': 'bs', 'english_name': 'Bosnian' }, + { 'iso_639_1': 'ch', 'english_name': 'Chamorro' }, + { 'iso_639_1': 'be', 'english_name': 'Belarusian' }, + { 'iso_639_1': 'yo', 'english_name': 'Yoruba' }, +]; + +/** + * Get list item + */ +export function getListItem (type, query) { + if (type === 'movie') { + return lists.movie.find(list => list.query === query); + } else if (type === 'tv') { + return lists.tv.find(list => list.query === query); + } +}; + +/** + * Get movies (listing) + */ +export function getMovies (query, page = 1) { + return new Promise((resolve, reject) => { + axios.get(`${apiUrl}/movie/${query}`, { + params: { + api_key: process.env.API_KEY, + language: process.env.API_LANG, + page, + }, + }).then((response) => { + resolve(response.data); + }) + .catch((error) => { + reject(error); + }); + }); +}; + +/** + * Get movie (single) + */ +export function getMovie (id) { + return new Promise((resolve, reject) => { + axios.get(`${apiUrl}/movie/${id}`, { + params: { + api_key: process.env.API_KEY, + language: process.env.API_LANG, + append_to_response: 'videos,credits,images,external_ids,release_dates', + include_image_language: 'en', + }, + }).then((response) => { + resolve(response.data); + }) + .catch((error) => { + reject(error); + }); + }); +}; + +/** + * Get movie recommended (single) + */ +export function getMovieRecommended (id, page = 1) { + return new Promise((resolve, reject) => { + axios.get(`${apiUrl}/movie/${id}/recommendations`, { + params: { + api_key: process.env.API_KEY, + language: process.env.API_LANG, + page, + }, + }).then((response) => { + resolve(response.data); + }) + .catch((error) => { + reject(error); + }); + }); +}; + +/** + * Get TV shows (listing) + */ +export function getTvShows (query, page = 1) { + return new Promise((resolve, reject) => { + axios.get(`${apiUrl}/tv/${query}`, { + params: { + api_key: process.env.API_KEY, + language: process.env.API_LANG, + page, + }, + }).then((response) => { + resolve(response.data); + }) + .catch((error) => { + reject(error); + }); + }); +}; + +/** + * Get TV show (single) + */ +export function getTvShow (id) { + return new Promise((resolve, reject) => { + axios.get(`${apiUrl}/tv/${id}`, { + params: { + api_key: process.env.API_KEY, + language: process.env.API_LANG, + append_to_response: 'videos,credits,images,external_ids,content_ratings', + include_image_language: 'en', + }, + }).then((response) => { + resolve(response.data); + }) + .catch((error) => { + reject(error); + }); + }); +}; + +/** + * Get TV show recommended (single) + */ +export function getTvShowRecommended (id, page = 1) { + return new Promise((resolve, reject) => { + axios.get(`${apiUrl}/tv/${id}/recommendations`, { + params: { + api_key: process.env.API_KEY, + language: process.env.API_LANG, + page, + }, + }).then((response) => { + resolve(response.data); + }) + .catch((error) => { + reject(error); + }); + }); +}; + +/** + * Get TV show episodes from season (single) + */ +export function getTvShowEpisodes (id, season) { + return new Promise((resolve, reject) => { + axios.get(`${apiUrl}/tv/${id}/season/${season}`, { + params: { + api_key: process.env.API_KEY, + language: process.env.API_LANG, + }, + }).then((response) => { + resolve(response.data); + }) + .catch((error) => { + reject(error); + }); + }); +}; + +/** + * Get trending + */ +export function getTrending (media, page = 1) { + return new Promise((resolve, reject) => { + axios.get(`${apiUrl}/trending/${media}/week`, { + params: { + api_key: process.env.API_KEY, + language: process.env.API_LANG, + page, + }, + }).then((response) => { + resolve(response.data); + }) + .catch((error) => { + reject(error); + }); + }); +}; + +/** + * Discover media by genre + */ +export function getMediaByGenre (media, genre, page = 1) { + return new Promise((resolve, reject) => { + axios.get(`${apiUrl}/discover/${media}`, { + params: { + api_key: process.env.API_KEY, + language: process.env.API_LANG, + with_genres: genre, + page, + }, + }).then((response) => { + resolve(response.data); + }) + .catch((error) => { + reject(error); + }); + }); +}; + +/** +* Get credits +*/ +export function getCredits (id, type) { + return new Promise((resolve, reject) => { + axios.get(`${apiUrl}/person/${id}/${type}`, { + params: { + api_key: process.env.API_KEY, + language: process.env.API_LANG, + }, + }).then((response) => { + resolve(response.data); + }) + .catch((error) => { + reject(error); + }); + }); +}; + +/** + * Get genre list + */ +export function getGenreList (media) { + return new Promise((resolve, reject) => { + axios.get(`${apiUrl}/genre/${media}/list`, { + params: { + api_key: process.env.API_KEY, + }, + }).then((response) => { + resolve(response.data.genres); + }) + .catch((error) => { + reject(error); + }); + }); +}; + +/** + * Get person (single) + */ +export function getPerson (id) { + return new Promise((resolve, reject) => { + axios.get(`${apiUrl}/person/${id}`, { + params: { + api_key: process.env.API_KEY, + language: process.env.API_LANG, + append_to_response: 'images,combined_credits,external_ids', + include_image_language: 'en', + }, + }).then((response) => { + resolve(response.data); + }) + .catch((error) => { + reject(error); + }); + }); +}; + +/** + * Search (searches movies, tv and people) + */ +export function search (query, page = 1) { + return new Promise((resolve, reject) => { + axios.get(`${apiUrl}/search/multi`, { + params: { + api_key: process.env.API_KEY, + language: process.env.API_LANG, + query, + page, + }, + }).then((response) => { + resolve(response.data); + }) + .catch((error) => { + reject(error); + }); + }); +}; + +/** + * Get YouTube video info + */ +export function getYouTubeVideo (id) { + return new Promise((resolve, reject) => { + axios.get(`https://www.googleapis.com/youtube/v3/videos`, { + params: { + key: process.env.API_YOUTUBE_KEY, + id, + part: 'contentDetails', + }, + }).then((response) => { + resolve(response.data); + }) + .catch((error) => { + reject(error); + }); + }); +}; diff --git a/assets/README.md b/assets/README.md new file mode 100644 index 0000000..7657cf2 --- /dev/null +++ b/assets/README.md @@ -0,0 +1,9 @@ +# ASSETS + +This directory contains your un-compiled assets such as LESS, SASS, or JavaScript. + +More information about the usage of this directory in the documentation: +https://nuxtjs.org/guide/assets#webpacked + +**This directory is not required, you can delete it if you don't want to use it.** + diff --git a/assets/css/base/_base.scss b/assets/css/base/_base.scss new file mode 100644 index 0000000..a144afc --- /dev/null +++ b/assets/css/base/_base.scss @@ -0,0 +1,106 @@ +@import '~/assets/css/utilities/_variables.scss'; + +*, +*:before, +*:after { + box-sizing: border-box; +} + +html { + font-family: $base-font-family; + font-size: $base-font-size; + font-style: $base-font-style; + font-weight: $base-font-weight; + line-height: $base-line-height; + color: $base-font-color; + background: $base-bg; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/** +* Remove text-shadow in selection highlight: +* https://twitter.com/miketaylr/status/12228805301 +* +* These selection rule sets have to be separate. +* Customize the background color to match your design. +*/ + +::-moz-selection { + text-shadow: none; + background: #b3d4fc; +} + +::selection { + text-shadow: none; + background: #b3d4fc; +} + +/** +* A better looking default horizontal rule +*/ + +hr { + display: block; + height: 1px; + padding: 0; + margin: 1em 0; + border: 0; + border-top: 1px solid #ccc; +} + +/** +* Remove the gap between audio, canvas, iframes, +* images, videos and the bottom of their containers: +* https://github.com/h5bp/base5-boilerplate/issues/440 +*/ + +audio, +canvas, +iframe, +img, +svg, +video { + vertical-align: middle; +} + +/** +* Remove default fieldset styles. +*/ + +fieldset { + padding: 0; + margin: 0; + border: 0; +} + +/** +* Allow only vertical resizing of textareas. +*/ + +textarea { + resize: vertical; +} + +/** +* Responsive images +*/ + +img { + display: inline-block; + max-width: 100%; + height: auto; + vertical-align: middle; + -ms-interpolation-mode: bicubic; +} + +table { + width: 100%; + border-collapse: collapse; + + th, + td { + padding: 0.5rem 0; + text-align: left; + } +} diff --git a/assets/css/base/_forms.scss b/assets/css/base/_forms.scss new file mode 100644 index 0000000..2da3d87 --- /dev/null +++ b/assets/css/base/_forms.scss @@ -0,0 +1,75 @@ +@import '~/assets/css/utilities/_variables.scss'; + +.button, +a.button { + display: inline-block; + padding: 1.5rem 2.5rem; + font-size: 1.5rem; + font-weight: 500; + line-height: 1; + color: #fff; + letter-spacing: 0.05em; + cursor: pointer; + background-color: $secondary-color; + transition: all 0.2s; + + &:hover, + &:focus { + background-color: #2f2f2f; + } + + &:disabled, + &[disabled] { + color: #666; + cursor: default; + background-color: #000; + } + + .icon { + margin-right: 1rem; + } +} + +.button--icon { + display: inline-flex; + align-items: center; +} + +select { + padding: 0.8rem 3.5rem 0.8rem 1.5rem; + font-size: 1.3rem; + color: #fff; + background: $secondary-color url('~assets/images/select-arrow.svg') no-repeat 100% 45%; + background-size: 30px 60px; + border-color: $secondary-color; + appearance: none; + border-radius: 0; + + &:disabled, + &[disabled] { + cursor: default; + opacity: 0.4; + } +} + +// Make sure we are not setting a height / background to multi select +select[multiple="multiple"] { + height: auto; + background-image: none; +} + +// IE hide the select arrow +select::-ms-expand { + display: none; +} + +input { + font-size: 1.3rem; + border-radius: 0; +} + +button { + text-align: center; + border: 0; + border-radius: 0; +} diff --git a/assets/css/base/_layout.scss b/assets/css/base/_layout.scss new file mode 100644 index 0000000..bc1948f --- /dev/null +++ b/assets/css/base/_layout.scss @@ -0,0 +1,19 @@ +@import '~/assets/css/utilities/_variables.scss'; + +@media (min-width: $breakpoint-large) { + body { + padding-left: 10rem; + } +} + +.spacing { + margin: 2.5rem 1.5rem; + + @media (min-width: $breakpoint-small) { + margin: 2.5rem 4rem; + } + + @media (min-width: $breakpoint-large) { + margin: 5rem; + } +} diff --git a/assets/css/base/_lazyload.scss b/assets/css/base/_lazyload.scss new file mode 100644 index 0000000..f4eea90 --- /dev/null +++ b/assets/css/base/_lazyload.scss @@ -0,0 +1,10 @@ +.lazyload { + display: block; + min-height: 1px; + opacity: 0; + transition: all 0.3s ease-in-out; +} + +.lazyloaded .lazyload { + opacity: 1; +} diff --git a/assets/css/base/_normalize.scss b/assets/css/base/_normalize.scss new file mode 100644 index 0000000..3d6aa21 --- /dev/null +++ b/assets/css/base/_normalize.scss @@ -0,0 +1,344 @@ +/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ + +html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers. + */ + +body { + margin: 0; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Remove the gray background on active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: 500; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove the border on images inside links in IE 10. + */ + +img { + border-style: none; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { + /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { + /* 1 */ + text-transform: none; +} + +/** + * Correct the inability to style clickable types in iOS and Safari. + */ + +button, +[type='button'], +[type='reset'], +[type='submit'] { + -webkit-appearance: button; + cursor: pointer; +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type='button']::-moz-focus-inner, +[type='reset']::-moz-focus-inner, +[type='submit']::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type='button']:-moz-focusring, +[type='reset']:-moz-focusring, +[type='submit']:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + vertical-align: baseline; +} + +/** + * Remove the default vertical scrollbar in IE 10+. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ + +[type='checkbox'], +[type='radio'] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type='number']::-webkit-inner-spin-button, +[type='number']::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type='search'] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ + +[type='search']::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ + +details { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Misc + ========================================================================== */ + +/** + * Add the correct display in IE 10+. + */ + +template { + display: none; +} + +/** + * Add the correct display in IE 10. + */ + +[hidden] { + display: none; +} diff --git a/assets/css/base/_transitions.scss b/assets/css/base/_transitions.scss new file mode 100644 index 0000000..ff02073 --- /dev/null +++ b/assets/css/base/_transitions.scss @@ -0,0 +1,26 @@ +// Entire page load +.page-enter-active, +.page-leave-active { + transition: all .25s ease-out; +} + +.page-enter, +.page-leave-active { + opacity: 0; +} + +// Slide down +.slidedown-leave-active, +.slidedown-enter-active { + transition: 0.3s; +} + +.slidedown-enter, +.slidedown-leave-to { + transform: translateY(-100%); +} + +.slidedown-enter-to, +.slidedown-leave { + transform: translateY(0); +} diff --git a/assets/css/base/_typography.scss b/assets/css/base/_typography.scss new file mode 100644 index 0000000..da40fd0 --- /dev/null +++ b/assets/css/base/_typography.scss @@ -0,0 +1,16 @@ +@import '~/assets/css/utilities/_variables.scss'; + +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 0; + font-weight: 400; +} + +a { + color: $base-font-color; + text-decoration: none; +} diff --git a/assets/css/components/_alert.scss b/assets/css/components/_alert.scss new file mode 100644 index 0000000..c526936 --- /dev/null +++ b/assets/css/components/_alert.scss @@ -0,0 +1,94 @@ +@import '~/assets/css/utilities/_variables.scss'; + +.alert { + font-size: 1.4rem; + color: #fff; + background-color: $secondary-color; + + p { + margin: 0; + } + + a { + color: #fff; + text-decoration: underline; + } + + button { + font-size: 1.4rem; + } +} + +.alert + .alert { + border-top: 1px solid #000; +} + +.alert__close { + display: flex; + flex: 0 0 auto; + align-items: center; + padding: 0 3rem; + background: none; + border-left: 1px solid #000; +} + +.alert__btn--primary { + background-color: $primary-color; + + &:hover, + &:focus { + background-color: #146fb7; + } +} + +.alert__btn--secondary { + background-color: #000; + + &:hover, + &:focus { + background-color: #2f2f2f; + } +} + +.alert--default { + display: flex; + + p { + flex: 1; + padding: 1.5rem; + + @media (min-width: $breakpoint-small) { + padding: 1.5rem 2rem; + } + } +} + +.alert--alt { + padding: 1.5rem; + + @media (min-width: $breakpoint-small) { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1.5rem 2rem; + } + + p { + @media (min-width: $breakpoint-small) { + margin-right: 1rem; + } + } + + div { + flex-shrink: 0; + } + + .alert__btn { + margin: 1.5rem 1rem 0 0; + + @media (min-width: $breakpoint-small) { + flex-shrink: 0; + margin: 0 0 0 1rem; + } + } +} diff --git a/assets/css/components/_card.scss b/assets/css/components/_card.scss new file mode 100644 index 0000000..3b19a9b --- /dev/null +++ b/assets/css/components/_card.scss @@ -0,0 +1,102 @@ +@import '~/assets/css/utilities/_variables.scss'; + +.card { + margin-bottom: 1.5rem; + line-height: $base-line-height; + + @media (min-width: $breakpoint-xsmall) { + margin-bottom: 2rem; + } +} + +.card__img { + position: relative; + height: 0; + padding-top: 150.27%; + overflow: hidden; + background-color: $secondary-color; + transition: transform 0.3s ease-in-out; + + img, + span { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + transform: scale(0.97); + } + + span { + display: flex; + align-items: center; + justify-content: center; + font-size: 1.3rem; + + @media (min-width: $breakpoint-large) { + font-size: 1.6rem; + } + } + + &.lazyloaded img { + transform: scale(1); + } +} + +.card__link:hover, +.card__link:focus { + .card__img { + transform: scale(1.02); + } +} + +.card__name { + margin-top: 1rem; + overflow: hidden; + font-size: 1.3rem; + text-overflow: ellipsis; + letter-spacing: $letter-spacing; + white-space: nowrap; + + @media (min-width: $breakpoint-large) { + margin-bottom: 0.5rem; + font-size: 1.5rem; + } +} + +.card__rating { + display: flex; + align-items: center; +} + +.card__vote { + margin-left: 1rem; + font-size: 1.2rem; + color: $text-color-grey; + + @media (min-width: $breakpoint-large) { + font-size: 1.4rem; + } +} + +.card__stars { + width: 7.3rem; + height: 1.2rem; + background-image: url('~assets/images/stars.png'); + background-repeat: no-repeat; + background-size: auto 100%; + + > div { + height: 100%; + background-image: url('~assets/images/stars-filled.png'); + background-repeat: no-repeat; + background-size: auto 100%; + } +} + +@media (max-width: $breakpoint-xsmall - 1) { + .card__name, + .card__rating { + display: none; + } +} diff --git a/assets/css/components/_carousel.scss b/assets/css/components/_carousel.scss new file mode 100644 index 0000000..aa939af --- /dev/null +++ b/assets/css/components/_carousel.scss @@ -0,0 +1,188 @@ +@import '~/assets/css/utilities/_variables.scss'; + +.carousel { + position: relative; + overflow: hidden; +} + +.carousel__nav { + position: absolute; + top: 0; + bottom: 48px; + z-index: 1; + width: 30px; + padding: 0; + margin: 0; + text-align: center; + background: rgba(0, 0, 0, 0.5); + outline: 0; + transition: opacity 0.25s ease, background-color 0.25s ease; + + @media (max-width: $breakpoint-small - 1) { + display: none; + } + + @media (min-width: $breakpoint-small) { + width: 40px; + } + + @media (min-width: $breakpoint-large) { + bottom: 60px; + width: 50px; + } + + &:hover, + &:focus { + background: rgba(0, 0, 0, 0.75); + } + + &[disabled] { + cursor: default; + opacity: 0; + } +} + +.carousel__nav--left { + left: 0; +} + +.carousel__nav--right { + right: 0; +} + +.carousel__items { + width: 100%; + overflow: hidden; + overflow-x: scroll; + line-height: 0; + white-space: nowrap; + transform: translateZ(0); + -webkit-overflow-scrolling: touch; + -ms-overflow-style: none; + scroll-snap-type: x mandatory; + scroll-padding: 15px; + + @media (min-width: $breakpoint-small) { + scroll-padding: 40px; + } + + @media (min-width: $breakpoint-large) { + scroll-padding: 50px; + } + + &::-webkit-scrollbar { + display: none; + } +} + +.carousel__items .card { + display: inline-block; + width: calc(.33333 * (100% - 22px)); + padding-right: 8px; + margin: 0; + white-space: normal; + vertical-align: top; + scroll-snap-align: start; + + @media (min-width: $breakpoint-xsmall) { + width: calc(.25 * (100% - 72px)); + } + + @media (min-width: $breakpoint-medium) { + width: calc(.2 * (100% - 72px)); + } + + @media (min-width: $breakpoint-large) { + width: calc(.2 * (100% - 92px)); + } + + @media (min-width: 1500px) { + width: calc(.16667 * (100% - 92px)); + } + + @media (min-width: 1800px) { + width: calc(.14286 * (100% - 92px)); + } + + @media (min-width: 2500px) { + width: calc(.125 * (100% - 92px)); + } + + &:first-child { + margin-left: 15px; + + @media (min-width: $breakpoint-small) { + margin-left: 40px; + } + + @media (min-width: $breakpoint-large) { + margin-left: 50px; + } + } + + &:last-child { + margin-right: 7px; + + @media (min-width: $breakpoint-small) { + margin-right: 32px; + } + + @media (min-width: $breakpoint-large) { + margin-right: 42px; + } + } +} + +.carousel__items .credits-item { + display: inline-block; + width: calc(.33333 * (100% - 22px)); + padding-right: 8px; + margin: 0; + white-space: normal; + vertical-align: top; + scroll-snap-align: start; + + @media (min-width: $breakpoint-small) { + width: calc(.25 * (100% - 72px)); + } + + @media (min-width: 930px) { + width: calc(.2 * (100% - 72px)); + } + + @media (min-width: 1130px) { + width: calc(.16667 * (100% - 72px)); + } + + @media (min-width: $breakpoint-large) { + width: calc(.16667 * (100% - 92px)); + } + + @media (min-width: 1450px) { + width: calc(.14286 * (100% - 92px)); + } + + &:first-child { + margin-left: 15px; + + @media (min-width: $breakpoint-small) { + margin-left: 40px; + } + + @media (min-width: $breakpoint-large) { + margin-left: 50px; + } + } + + &:last-child { + margin-right: 7px; + + @media (min-width: $breakpoint-small) { + margin-right: 32px; + } + + @media (min-width: $breakpoint-large) { + margin-right: 42px; + } + } +} diff --git a/assets/css/components/_listing.scss b/assets/css/components/_listing.scss new file mode 100644 index 0000000..81d5b09 --- /dev/null +++ b/assets/css/components/_listing.scss @@ -0,0 +1,105 @@ +@import '~/assets/css/utilities/_variables.scss'; + +.listing { + margin: 2.5rem 1.5rem; + + @media (min-width: $breakpoint-xsmall) { + margin: 3rem 1.5rem; + } + + @media (min-width: $breakpoint-large) { + margin: 5rem; + } +} + +.listing__head { + display: flex; + align-items: baseline; + margin-bottom: 1.5rem; + + @media (min-width: $breakpoint-large) { + margin-bottom: 2rem; + } +} + +.listing__title { + font-size: 1.8rem; + letter-spacing: $letter-spacing; + + @media (min-width: $breakpoint-large) { + font-size: 2.4rem; + } +} + +.listing__explore { + margin-left: 1rem; + font-size: 1.2rem; + color: $primary-color; + letter-spacing: $letter-spacing; + + @media (min-width: $breakpoint-large) { + font-size: 1.4rem; + } + + &:hover, + &:focus { + opacity: 0.8; + } +} + +.listing__items { + display: flex; + flex-wrap: wrap; + margin-right: -0.4rem; + margin-left: -0.4rem; +} + +.listing__nav { + padding: 4rem 0; + text-align: center; +} + +.listing--carousel { + margin-right: 0; + margin-left: 0; + + .listing__head { + margin-right: 1.5rem; + margin-left: 1.5rem; + + @media (min-width: $breakpoint-small) { + margin-right: 4rem; + margin-left: 4rem; + } + + @media (min-width: $breakpoint-large) { + margin-right: 5rem; + margin-left: 5rem; + } + } +} + +.listing__items .card { + width: 33.3333333%; + padding: 0 0.4rem; + + @media (min-width: $breakpoint-xsmall) { + width: 25%; + } + + @media (min-width: $breakpoint-medium) { + width: 20%; + } + + @media (min-width: 1500px) { + width: 16.6666667%; + } + + @media (min-width: 1800px) { + width: 14.2857143%; + } + + @media (min-width: 2500px) { + width: 12.5%; + } +} diff --git a/assets/css/global.scss b/assets/css/global.scss new file mode 100644 index 0000000..d7060b1 --- /dev/null +++ b/assets/css/global.scss @@ -0,0 +1,12 @@ +@import './base/_normalize.scss'; +@import './base/_base.scss'; +@import './base/_transitions.scss'; +@import './base/_typography.scss'; +@import './base/_forms.scss'; +@import './base/_layout.scss'; +@import './base/_lazyload.scss'; +@import './utilities/_helpers.scss'; +@import './components/_alert.scss'; +@import './components/_listing.scss'; +@import './components/_carousel.scss'; +@import './components/_card.scss'; diff --git a/assets/css/utilities/_helpers.scss b/assets/css/utilities/_helpers.scss new file mode 100644 index 0000000..2daa2cf --- /dev/null +++ b/assets/css/utilities/_helpers.scss @@ -0,0 +1,15 @@ +.nolist { + padding: 0; + margin: 0; + list-style: none; +} + +.visuallyhidden { + position: absolute; + height: 1px; width: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0 0 0 0); + border: 0; +} diff --git a/assets/css/utilities/_variables.scss b/assets/css/utilities/_variables.scss new file mode 100644 index 0000000..a5a436a --- /dev/null +++ b/assets/css/utilities/_variables.scss @@ -0,0 +1,24 @@ +$font-family--sans-serif: 'Roboto', 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; + +// 1rem = 10px +$base-font-size: 62.5%; +$base-line-height: 1.6; +$base-bg: #141414; +$base-font-color: #fff; +$base-font-family: $font-family--sans-serif; +$base-font-weight: 400; +$base-font-style: normal; + +$letter-spacing: 0.4px; + +$primary-color: #2196f3; +$secondary-color: #202124; + +$text-color: #fafafa; +$text-color-grey: #80868b; + +$breakpoint-xsmall: 640px; +$breakpoint-small: 768px; +$breakpoint-medium: 1024px; +$breakpoint-large: 1200px; +$breakpoint-xlarge: 1400px; diff --git a/assets/images/loader.svg b/assets/images/loader.svg new file mode 100644 index 0000000..617dd67 --- /dev/null +++ b/assets/images/loader.svg @@ -0,0 +1 @@ + diff --git a/assets/images/select-arrow.svg b/assets/images/select-arrow.svg new file mode 100644 index 0000000..c5667b0 --- /dev/null +++ b/assets/images/select-arrow.svg @@ -0,0 +1 @@ + diff --git a/assets/images/stars-filled.png b/assets/images/stars-filled.png new file mode 100644 index 0000000000000000000000000000000000000000..cbb03e20f708de2bfa5c2c580d860fd28e812d0b GIT binary patch literal 2988 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 G#Qy<9+}51{ literal 0 HcmV?d00001 diff --git a/assets/images/stars.png b/assets/images/stars.png new file mode 100644 index 0000000000000000000000000000000000000000..78426f0feeca74ce0fe4f4905a7d2e9d4876610b GIT binary patch literal 2751 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 O0sHe8&polek? +
+ +
+ + + + + + +
+ +

+ {{ name }} +

+ +
+
+
+
+ +
+ {{ item.vote_average | rating }} +
+
+ +
+ + + diff --git a/components/Credits.vue b/components/Credits.vue new file mode 100644 index 0000000..a2a8171 --- /dev/null +++ b/components/Credits.vue @@ -0,0 +1,74 @@ + + + diff --git a/components/CreditsItem.vue b/components/CreditsItem.vue new file mode 100644 index 0000000..e8aaa2f --- /dev/null +++ b/components/CreditsItem.vue @@ -0,0 +1,117 @@ + + + + + diff --git a/components/ExternalLinks.vue b/components/ExternalLinks.vue new file mode 100644 index 0000000..b73fca8 --- /dev/null +++ b/components/ExternalLinks.vue @@ -0,0 +1,81 @@ + + + diff --git a/components/Hero.vue b/components/Hero.vue new file mode 100644 index 0000000..652e35f --- /dev/null +++ b/components/Hero.vue @@ -0,0 +1,373 @@ + + + + + + + diff --git a/components/Images.vue b/components/Images.vue new file mode 100644 index 0000000..547d9a9 --- /dev/null +++ b/components/Images.vue @@ -0,0 +1,147 @@ + + + + + diff --git a/components/ImagesItem.vue b/components/ImagesItem.vue new file mode 100644 index 0000000..d4056c9 --- /dev/null +++ b/components/ImagesItem.vue @@ -0,0 +1,120 @@ + + + + + diff --git a/components/Listing.vue b/components/Listing.vue new file mode 100644 index 0000000..c10f1b0 --- /dev/null +++ b/components/Listing.vue @@ -0,0 +1,113 @@ + + + diff --git a/components/ListingCarousel.vue b/components/ListingCarousel.vue new file mode 100644 index 0000000..f20acda --- /dev/null +++ b/components/ListingCarousel.vue @@ -0,0 +1,110 @@ + + + diff --git a/components/MediaNav.vue b/components/MediaNav.vue new file mode 100644 index 0000000..4366e0e --- /dev/null +++ b/components/MediaNav.vue @@ -0,0 +1,94 @@ + + + + + diff --git a/components/Modal.vue b/components/Modal.vue new file mode 100644 index 0000000..180dd50 --- /dev/null +++ b/components/Modal.vue @@ -0,0 +1,472 @@ +