Now root template only contains elements that exist for every page; navigation, search and popover along with the router view. Removed most all the logic except for prototype functions/variable attached to the vue instance and controlls the state of moviepopup given a id and type.
This commit is contained in:
		
							
								
								
									
										247
									
								
								src/App.vue
									
									
									
									
									
								
							
							
						
						
									
										247
									
								
								src/App.vue
									
									
									
									
									
								
							@@ -1,122 +1,42 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div id="app">
 | 
			
		||||
 | 
			
		||||
    <!-- Header and hamburger navigation -->
 | 
			
		||||
    <navigation></navigation>
 | 
			
		||||
 | 
			
		||||
    <!-- Header with search field -->
 | 
			
		||||
    <header class="header">
 | 
			
		||||
      <div class="header__search">
 | 
			
		||||
        <input class="header__search-input" type="text" v-model.trim="searchQuery" @keyup.enter="search" placeholder="Search for a movie or show...">
 | 
			
		||||
        <svg class="header__search-icon">
 | 
			
		||||
          <use xlink:href="#iconSearch"></use>
 | 
			
		||||
        </svg>
 | 
			
		||||
      </div>
 | 
			
		||||
      <search-input v-model="query"></search-input>
 | 
			
		||||
    </header>
 | 
			
		||||
 | 
			
		||||
    <!-- Movie popup that will show above existing rendered content -->
 | 
			
		||||
    <movie-popup v-if="moviePopupIsVisible" :id="popupID" :type="popupType"></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="user-requests-router-view" :type="'page'" :mode="'user-requests'"></router-view>
 | 
			
		||||
        <router-view name="page-router-view"></router-view>
 | 
			
		||||
      </transition>
 | 
			
		||||
    </section>
 | 
			
		||||
    <!-- Display the component assigned to the given route (default: home) -->
 | 
			
		||||
    <router-view class="content"></router-view>
 | 
			
		||||
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import axios from 'axios'
 | 
			
		||||
import storage from './storage.js'
 | 
			
		||||
import Vue from 'vue'
 | 
			
		||||
import Navigation from './components/Navigation.vue'
 | 
			
		||||
import MoviePopup from './components/MoviePopup.vue'
 | 
			
		||||
import SearchInput from './components/search/SearchInput.vue'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'app',
 | 
			
		||||
  components: { Navigation, MoviePopup},
 | 
			
		||||
  data(){
 | 
			
		||||
    return{
 | 
			
		||||
  components: {
 | 
			
		||||
    Navigation,
 | 
			
		||||
    MoviePopup,
 | 
			
		||||
    SearchInput
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      query: '',
 | 
			
		||||
      moviePopupIsVisible: false,
 | 
			
		||||
      moviePopupHistoryVisible: false,
 | 
			
		||||
      moviePopupId: 0,
 | 
			
		||||
      moviePopupType: 'movie',
 | 
			
		||||
      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.token = localStorage.getItem('token') || null;
 | 
			
		||||
      storage.username = localStorage.getItem('username') || null;
 | 
			
		||||
      storage.admin = localStorage.getItem('admin') || null;
 | 
			
		||||
    },
 | 
			
		||||
    // Movie Popup Methods
 | 
			
		||||
    openMoviePopup(id, type, newMoviePopup){
 | 
			
		||||
      console.log('app openMoviePopup:', type)
 | 
			
		||||
      if(newMoviePopup){
 | 
			
		||||
        storage.backTitle = document.title;
 | 
			
		||||
      }
 | 
			
		||||
      storage.createMoviePopup = newMoviePopup;
 | 
			
		||||
      this.moviePopupIsVisible = true;
 | 
			
		||||
      this.moviePopupId = id;
 | 
			
		||||
      this.moviePopupType = type;
 | 
			
		||||
      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;
 | 
			
		||||
    },
 | 
			
		||||
    // Detect if touch device
 | 
			
		||||
    isTouchDevice() {
 | 
			
		||||
      return 'ontouchstart' in document.documentElement;
 | 
			
		||||
      popupID: 0,
 | 
			
		||||
      popupType: 'movie'
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  created(){
 | 
			
		||||
@@ -141,7 +61,21 @@ export default {
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
@import "./src/scss/media-queries";
 | 
			
		||||
@import "./src/scss/variables";
 | 
			
		||||
.content {
 | 
			
		||||
    @include tablet-min{
 | 
			
		||||
    width: calc(100% - 95px);
 | 
			
		||||
    padding-top: $header-size;
 | 
			
		||||
    margin-left: 95px;
 | 
			
		||||
    position: relative;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
@import "./src/scss/main";
 | 
			
		||||
@import "./src/scss/variables";
 | 
			
		||||
@import "./src/scss/media-queries";
 | 
			
		||||
*{
 | 
			
		||||
@@ -168,32 +102,10 @@ figure{
 | 
			
		||||
}
 | 
			
		||||
img{
 | 
			
		||||
  display: block;
 | 
			
		||||
  max-width: 100%;
 | 
			
		||||
  // 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;
 | 
			
		||||
}
 | 
			
		||||
@@ -202,20 +114,20 @@ img{
 | 
			
		||||
  background: $c-white;
 | 
			
		||||
  z-index: 15;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
 | 
			
		||||
  @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% - 110px);
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    position: fixed;
 | 
			
		||||
    top: 0;
 | 
			
		||||
    right: 55px;
 | 
			
		||||
@@ -244,27 +156,22 @@ img{
 | 
			
		||||
        padding: 15px 30px 15px 90px;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    &-icon{
 | 
			
		||||
      width: 19px;
 | 
			
		||||
    &-arrow {
 | 
			
		||||
      height: 19px;
 | 
			
		||||
      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;
 | 
			
		||||
      width: 30px;
 | 
			
		||||
      display: flex;
 | 
			
		||||
      align-self: center;
 | 
			
		||||
      margin-right: 30px;
 | 
			
		||||
 | 
			
		||||
      -moz-transition: all 0.5s ease;
 | 
			
		||||
      -webkit-transition: all 0.5s ease;
 | 
			
		||||
      transition: all 0.5s ease;
 | 
			
		||||
 | 
			
		||||
      &.down {
 | 
			
		||||
        -ms-transform: rotate(180deg);
 | 
			
		||||
        -moz-transform: rotate(180deg);
 | 
			
		||||
        -webkit-transform: rotate(180deg);
 | 
			
		||||
        transform: rotate(180deg);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    &-input:focus + &-icon{
 | 
			
		||||
@@ -272,50 +179,6 @@ img{
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.main{
 | 
			
		||||
  position: relative;
 | 
			
		||||
  padding: 50px 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;
 | 
			
		||||
  transition: background 0.5s ease, color 0.5s ease;
 | 
			
		||||
  @include tablet-min{
 | 
			
		||||
    font-size: 12px;
 | 
			
		||||
    padding: 6px 20px 5px 20px;
 | 
			
		||||
  }
 | 
			
		||||
  &:active, &:hover{
 | 
			
		||||
    background: $c-dark;
 | 
			
		||||
    color: $c-white;
 | 
			
		||||
  }
 | 
			
		||||
  body:not(.touch) &:hover, &:focus{
 | 
			
		||||
    background: $c-dark;
 | 
			
		||||
    color: $c-white;
 | 
			
		||||
  }
 | 
			
		||||
  &__active {
 | 
			
		||||
    @extend .button;
 | 
			
		||||
    background: $c-dark;
 | 
			
		||||
    color: $c-white;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// router view transition
 | 
			
		||||
.fade-enter-active, .fade-leave-active {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user