mirror of
https://github.com/KevinMidboe/seasonedRequest.git
synced 2025-10-29 18:00:13 +00:00
version 1.0
This commit is contained in:
296
src/App.vue
Normal file
296
src/App.vue
Normal file
@@ -0,0 +1,296 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<navigation></navigation>
|
||||
<header class="header">
|
||||
<div class="header__search">
|
||||
<input class="header__search-input" type="text" v-model.trim="searchQuery" @keyup.enter="search" @blur="search" placeholder="Search for a movie...">
|
||||
<svg class="header__search-icon">
|
||||
<use xlink:href="#iconSearch"></use>
|
||||
</svg>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<movie-popup v-if="moviePopupIsVisible" @close="closeMoviePopup" :id="moviePopupId"></movie-popup>
|
||||
|
||||
<section class="main">
|
||||
<transition name="fade" @after-leave="afterLeave">
|
||||
<router-view name="list-router-view" :type="'page'" :mode="'collection'" :key="$route.params.category"></router-view>
|
||||
<router-view name="search-router-view" :type="'page'" :mode="'search'" :key="$route.params.query"></router-view>
|
||||
<router-view name="page-router-view"></router-view>
|
||||
</transition>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
import storage from './storage.js'
|
||||
import Navigation from './components/Navigation.vue'
|
||||
import MoviePopup from './components/MoviePopup.vue'
|
||||
|
||||
export default {
|
||||
name: 'app',
|
||||
components: { Navigation, MoviePopup},
|
||||
data(){
|
||||
return{
|
||||
moviePopupIsVisible: false,
|
||||
moviePopupHistoryVisible: false,
|
||||
moviePopupId: 0,
|
||||
searchQuery: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
queryForRouter(){
|
||||
return encodeURI(this.searchQuery.replace(/ /g, "+"));
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// User Session Methods
|
||||
requestToken(){
|
||||
storage.sessionId = null;
|
||||
axios.get(`https://api.themoviedb.org/3/authentication/token/new?api_key=${storage.apiKey}`)
|
||||
.then(function(resp){
|
||||
if(typeof resp.data == 'string') {
|
||||
resp.data = JSON.parse(resp.data);
|
||||
}
|
||||
let data = resp.data;
|
||||
window.location.href = `https://www.themoviedb.org/authenticate/${data.request_token}?redirect_to=${location.protocol}//${location.host}/profile`
|
||||
}.bind(this));
|
||||
},
|
||||
setUserStatus(){
|
||||
storage.sessionId = localStorage.getItem('session_id') || null;
|
||||
storage.userId = localStorage.getItem('user_id') || null;
|
||||
},
|
||||
// Movie Popup Methods
|
||||
openMoviePopup(id, newMoviePopup){
|
||||
if(newMoviePopup){
|
||||
storage.backTitle = document.title;
|
||||
}
|
||||
storage.createMoviePopup = newMoviePopup;
|
||||
this.moviePopupIsVisible = true;
|
||||
this.moviePopupId = id;
|
||||
document.querySelector('body').classList.add('hidden');
|
||||
},
|
||||
closeMoviePopup(){
|
||||
storage.createMoviePopup = false;
|
||||
this.moviePopupIsVisible = false;
|
||||
document.querySelector('body').classList.remove('hidden');
|
||||
window.history.back();
|
||||
},
|
||||
onHistoryState(e){
|
||||
storage.moviePopupOnHistory = e.state ? e.state.hasOwnProperty('popup') : false;
|
||||
if(!storage.moviePopupOnHistory){
|
||||
this.moviePopupIsVisible = false;
|
||||
document.title = storage.backTitle;
|
||||
}
|
||||
},
|
||||
changeHistoryState(){
|
||||
if(history.state && history.state.popup){
|
||||
let newState = {
|
||||
popup: false
|
||||
};
|
||||
history.replaceState(newState , null, storage.moviePath);
|
||||
}
|
||||
},
|
||||
// Search Methods
|
||||
search(){
|
||||
if(!this.searchQuery.length) return;
|
||||
this.$router.push({ name: 'search', params: { query: this.queryForRouter }});
|
||||
},
|
||||
setSearchQuery(clear){
|
||||
if(clear){
|
||||
this.searchQuery = '';
|
||||
} else {
|
||||
let query = decodeURIComponent(this.$route.params.query);
|
||||
this.searchQuery = query ? query.replace(/\+/g, " ") : '';
|
||||
}
|
||||
},
|
||||
// Router After Leave
|
||||
afterLeave(){
|
||||
document.querySelector('body').scrollTop = 0;
|
||||
}
|
||||
},
|
||||
created(){
|
||||
window.addEventListener('popstate', this.onHistoryState);
|
||||
window.addEventListener('pagehide', this.changeHistoryState);
|
||||
eventHub.$on('openMoviePopup', this.openMoviePopup);
|
||||
eventHub.$on('setSearchQuery', this.setSearchQuery);
|
||||
eventHub.$on('requestToken', this.requestToken);
|
||||
eventHub.$on('setUserStatus', this.setUserStatus);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "./src/scss/variables";
|
||||
@import "./src/scss/media-queries";
|
||||
*{
|
||||
box-sizing: border-box;
|
||||
}
|
||||
html, body{
|
||||
height: 100%;
|
||||
}
|
||||
body{
|
||||
font-family: 'Roboto', sans-serif;
|
||||
line-height: 1.6;
|
||||
background: $c-light;
|
||||
color: $c-dark;
|
||||
&.hidden{
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
input, textarea, button{
|
||||
font-family: 'Roboto', sans-serif;
|
||||
}
|
||||
figure{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
img{
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
.loader{
|
||||
animation: load 1s linear infinite;
|
||||
border: 2px solid $c-white;
|
||||
border-radius: 50%;
|
||||
display: block;
|
||||
height: 30px;
|
||||
left: 50%;
|
||||
margin: -1.5em;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 30px;
|
||||
&:after {
|
||||
border: 5px solid $c-green;
|
||||
border-radius: 50%;
|
||||
content: '';
|
||||
left: 10px;
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
}
|
||||
}
|
||||
@keyframes load {
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
.wrapper{
|
||||
position: relative;
|
||||
}
|
||||
.header{
|
||||
position: fixed;
|
||||
background: $c-white;
|
||||
z-index: 15;
|
||||
display: flex;
|
||||
@include tablet-min{
|
||||
width: calc(100% - 170px);
|
||||
height: 75px;
|
||||
margin-left: 95px;
|
||||
border-top: 0;
|
||||
border-bottom: 0;
|
||||
top: 0;
|
||||
}
|
||||
&__search{
|
||||
height: 50px;
|
||||
display: flex;
|
||||
position: relative;
|
||||
z-index: 5;
|
||||
width: calc(100% - 55px);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
@include tablet-min{
|
||||
position: relative;
|
||||
height: 75px;
|
||||
}
|
||||
&-input{
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 15px 20px 15px 50px;
|
||||
outline: none;
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
color: $c-dark;
|
||||
font-weight: 300;
|
||||
font-size: 16px;
|
||||
@include tablet-min{
|
||||
padding: 15px 30px 15px 60px;
|
||||
}
|
||||
@include tablet-landscape-min{
|
||||
padding: 15px 30px 15px 80px;
|
||||
}
|
||||
@include desktop-min{
|
||||
padding: 15px 30px 15px 90px;
|
||||
}
|
||||
}
|
||||
&-icon{
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
fill: rgba($c-dark, 0.5);
|
||||
transition: fill 0.5s ease;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
margin-top: -7px;
|
||||
left: 20px;
|
||||
@include tablet-min{
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-top: -9px;
|
||||
left: 30px;
|
||||
}
|
||||
@include tablet-landscape-min{
|
||||
left: 50px;
|
||||
}
|
||||
@include desktop-min{
|
||||
left: 60px;
|
||||
}
|
||||
}
|
||||
&-input:focus + &-icon{
|
||||
fill: $c-dark;
|
||||
}
|
||||
}
|
||||
}
|
||||
.main{
|
||||
position: relative;
|
||||
padding: 100px 0 0;
|
||||
@include tablet-min{
|
||||
width: calc(100% - 95px);
|
||||
padding: 75px 0 0;
|
||||
margin-left: 95px;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
.button{
|
||||
display: inline-block;
|
||||
border: 1px solid $c-dark;
|
||||
text-transform: uppercase;
|
||||
background: $c-dark;
|
||||
font-weight: 300;
|
||||
font-size: 11px;
|
||||
line-height: 2;
|
||||
letter-spacing: 0.5px;
|
||||
padding: 5px 20px 4px 20px;
|
||||
cursor: pointer;
|
||||
color: $c-dark;
|
||||
background: transparent;
|
||||
outline: none;
|
||||
@include tablet-min{
|
||||
font-size: 12px;
|
||||
padding: 6px 20px 5px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// router view transition
|
||||
.fade-enter-active, .fade-leave-active {
|
||||
transition-property: opacity;
|
||||
transition-duration: 0.25s;
|
||||
}
|
||||
.fade-enter-active {
|
||||
transition-delay: 0.25s;
|
||||
}
|
||||
.fade-enter, .fade-leave-active {
|
||||
opacity: 0
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user