Re implemented header navigation
This commit is contained in:
		
							
								
								
									
										190
									
								
								src/App.vue
									
									
									
									
									
								
							
							
						
						
									
										190
									
								
								src/App.vue
									
									
									
									
									
								
							| @@ -1,123 +1,151 @@ | |||||||
|  | <style lang="scss" scoped> | ||||||
|  | @import "./src/scss/media-queries"; | ||||||
|  | #app { | ||||||
|  |   display: grid; | ||||||
|  |   // grid-template-columns: 90px 1fr 90px; | ||||||
|  |   grid-template-rows: var(--header-size); | ||||||
|  |   grid-template-columns: var(--header-size) 1fr; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .header { | ||||||
|  |   position: fixed; | ||||||
|  |   top: 0; | ||||||
|  |   width: 100%; | ||||||
|  |   grid-column: 1 / 3; | ||||||
|  |   grid-row: 1; | ||||||
|  |   z-index: 15; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .content { | ||||||
|  |   grid-column: 2 / 3; | ||||||
|  |   grid-row: 2; | ||||||
|  |   z-index: 5; | ||||||
|  |  | ||||||
|  |   @include mobile { | ||||||
|  |     grid-column: 1 / 3; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .desktop-menu { | ||||||
|  |   grid-column: 1 / 2; | ||||||
|  |   grid-row: 2; | ||||||
|  |   width: var(--header-size); | ||||||
|  |   position: fixed; | ||||||
|  |   top: var(--header-size); | ||||||
|  |   left: 0; | ||||||
|  | } | ||||||
|  | </style> | ||||||
|  |  | ||||||
| <template> | <template> | ||||||
|   <div id="app"> |   <div id="app"> | ||||||
|  |  | ||||||
|     <!-- Header and hamburger navigation --> |     <!-- Header and hamburger navigation --> | ||||||
|     <navigation></navigation> |     <NavigationHeader class="header"></NavigationHeader> | ||||||
|  |     <NavigationIcons class="desktop-menu desktop-only" /> | ||||||
|     <!-- Header with search field --> |  | ||||||
|  |  | ||||||
|     <!-- TODO move this to the navigation component --> |  | ||||||
|     <header class="header"> |  | ||||||
|       <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> |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     <darkmode-toggle /> |  | ||||||
|  |  | ||||||
|     <!-- Display the component assigned to the given route (default: home) --> |     <!-- Display the component assigned to the given route (default: home) --> | ||||||
|     <router-view class="content" :key="$route.fullPath"></router-view> |     <router-view class="content" :key="$route.fullPath"></router-view> | ||||||
|  |  | ||||||
|  |     <!-- Movie popup that will show above existing rendered content --> | ||||||
|  |     <movie-popup | ||||||
|  |       v-if="moviePopupIsVisible" | ||||||
|  |       :id="popupID" | ||||||
|  |       :type="popupType" | ||||||
|  |     ></movie-popup> | ||||||
|  |  | ||||||
|  |     <darkmode-toggle /> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script> | <script> | ||||||
| import Vue from 'vue' | import Vue from "vue"; | ||||||
| import Navigation from '@/components/Navigation' | import NavigationHeader from "@/components/NavigationHeader"; | ||||||
| import MoviePopup from '@/components/MoviePopup' | import NavigationIcons from "@/components/NavigationIcons"; | ||||||
| import SearchInput from '@/components/SearchInput' | import MoviePopup from "@/components/MoviePopup"; | ||||||
| import DarkmodeToggle from '@/components/ui/darkmodeToggle' | import DarkmodeToggle from "@/components/ui/darkmodeToggle"; | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   name: 'app', |   name: "app", | ||||||
|   components: { |   components: { | ||||||
|     Navigation, |     NavigationHeader, | ||||||
|  |     NavigationIcons, | ||||||
|     MoviePopup, |     MoviePopup, | ||||||
|     SearchInput, |  | ||||||
|     DarkmodeToggle |     DarkmodeToggle | ||||||
|   }, |   }, | ||||||
|   data() { |   data() { | ||||||
|     return { |     return { | ||||||
|       query: '', |       query: "", | ||||||
|       moviePopupIsVisible: false, |       moviePopupIsVisible: false, | ||||||
|       popupID: 0, |       popupID: 0, | ||||||
|       popupType: 'movie' |       popupType: "movie" | ||||||
|     } |     }; | ||||||
|   }, |   }, | ||||||
|   created(){ |   created() { | ||||||
|     let that = this |     let that = this; | ||||||
|     Vue.prototype.$popup = { |     Vue.prototype.$popup = { | ||||||
|       get isOpen() { |       get isOpen() { | ||||||
|         return that.moviePopupIsVisible |         return that.moviePopupIsVisible; | ||||||
|       }, |       }, | ||||||
|       open: (id, type) => { |       open: (id, type) => { | ||||||
|         this.popupID = id || this.popupID |         this.popupID = id || this.popupID; | ||||||
|         this.popupType = type || this.popupType |         this.popupType = type || this.popupType; | ||||||
|         this.moviePopupIsVisible = true |         this.moviePopupIsVisible = true; | ||||||
|         console.log('opened') |         console.log("opened"); | ||||||
|       }, |       }, | ||||||
|       close: () => { |       close: () => { | ||||||
|         this.moviePopupIsVisible = false |         this.moviePopupIsVisible = false; | ||||||
|         console.log('closed') |         console.log("closed"); | ||||||
|       } |       } | ||||||
|     } |     }; | ||||||
|     console.log('MoviePopup registered at this.$popup and has state: ', this.$popup.isOpen) |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| </script> |  | ||||||
|  |  | ||||||
| <style lang="scss" scoped> |     const movieId = new URLSearchParams(window.location.search).get("movie"); | ||||||
| @import "./src/scss/media-queries"; |     if (movieId) { | ||||||
| @import "./src/scss/variables"; |       this.$popup.open(movieId, "movie"); | ||||||
| .content { |  | ||||||
|     @include tablet-min{ |  | ||||||
|     width: calc(100% - 95px); |  | ||||||
|     margin-top: $header-size; |  | ||||||
|     margin-left: 95px; |  | ||||||
|     position: relative; |  | ||||||
|     } |     } | ||||||
| } |   } | ||||||
| </style> | }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
| <style lang="scss"> | <style lang="scss"> | ||||||
| // @import "./src/scss/main"; | // @import "./src/scss/main"; | ||||||
| @import "./src/scss/variables"; | @import "./src/scss/variables"; | ||||||
| @import "./src/scss/media-queries"; | @import "./src/scss/media-queries"; | ||||||
|  |  | ||||||
| *{ | * { | ||||||
|   box-sizing: border-box; |   box-sizing: border-box; | ||||||
| } | } | ||||||
| html { | html { | ||||||
|   height: 100%; |   height: 100%; | ||||||
| } | } | ||||||
| body{ | body { | ||||||
|   margin: 0; |   margin: 0; | ||||||
|   padding: 0; |   padding: 0; | ||||||
|   font-family: 'Roboto', sans-serif; |   font-family: "Roboto", sans-serif; | ||||||
|   line-height: 1.6; |   line-height: 1.6; | ||||||
|   background: $background-color; |   background: $background-color; | ||||||
|   color: $text-color; |   color: $text-color; | ||||||
|   transition: background-color .5s ease, color .5s ease; |   transition: background-color 0.5s ease, color 0.5s ease; | ||||||
|   &.hidden{ |  | ||||||
|  |   * { | ||||||
|  |     transition: background-color 0.5s ease, color 0.5s ease; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   &.hidden { | ||||||
|     overflow: hidden; |     overflow: hidden; | ||||||
|   } |   } | ||||||
| } | } | ||||||
| h1,h2,h3 { |  | ||||||
|   transition: color .5s ease; |  | ||||||
| } |  | ||||||
| a:any-link { | a:any-link { | ||||||
|   color: inherit; |   color: inherit; | ||||||
| } | } | ||||||
| input, textarea, button{ | input, | ||||||
|   font-family: 'Roboto', sans-serif; | textarea, | ||||||
|  | button { | ||||||
|  |   font-family: "Roboto", sans-serif; | ||||||
| } | } | ||||||
| figure{ | figure { | ||||||
|   padding: 0; |   padding: 0; | ||||||
|   margin: 0; |   margin: 0; | ||||||
| } | } | ||||||
| img{ | img { | ||||||
|   display: block; |   display: block; | ||||||
|   // max-width: 100%; |   // max-width: 100%; | ||||||
|   height: auto; |   height: auto; | ||||||
| @@ -127,33 +155,35 @@ img{ | |||||||
|   overflow: hidden; |   overflow: hidden; | ||||||
| } | } | ||||||
|  |  | ||||||
| .wrapper{ | .wrapper { | ||||||
|   position: relative; |   position: relative; | ||||||
| } | } | ||||||
| .header{ | // .header { | ||||||
|   position: fixed; | //   position: fixed; | ||||||
|   z-index: 15; | //   z-index: 15; | ||||||
|   display: flex; | //   display: flex; | ||||||
|   flex-direction: column; | //   flex-direction: column; | ||||||
|  |  | ||||||
|   @include tablet-min{ | //   @include tablet-min { | ||||||
|     width: calc(100% - 170px); | //     width: calc(100% - 170px); | ||||||
|     margin-left: 95px; | //     margin-left: 95px; | ||||||
|     border-top: 0; | //     border-top: 0; | ||||||
|     border-bottom: 0; | //     border-bottom: 0; | ||||||
|     top: 0; | //     top: 0; | ||||||
|   } | //   } | ||||||
| } | // } | ||||||
|  |  | ||||||
| // router view transition | // router view transition | ||||||
| .fade-enter-active, .fade-leave-active { | .fade-enter-active, | ||||||
|  | .fade-leave-active { | ||||||
|   transition-property: opacity; |   transition-property: opacity; | ||||||
|   transition-duration: 0.25s; |   transition-duration: 0.25s; | ||||||
| } | } | ||||||
| .fade-enter-active { | .fade-enter-active { | ||||||
|   transition-delay: 0.25s; |   transition-delay: 0.25s; | ||||||
| } | } | ||||||
| .fade-enter, .fade-leave-active { | .fade-enter, | ||||||
|   opacity: 0 | .fade-leave-active { | ||||||
|  |   opacity: 0; | ||||||
| } | } | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -1,314 +0,0 @@ | |||||||
| <template> |  | ||||||
|   <div> |  | ||||||
|     <nav class="nav"> |  | ||||||
|       <router-link class="nav__logo" :to="{name: 'home'}" exact title="Vue.js — TMDb App"> |  | ||||||
|         <svg class="nav__logo-image"> |  | ||||||
|           <use xlink:href="#svgLogo"></use> |  | ||||||
|         </svg> |  | ||||||
|       </router-link> |  | ||||||
|  |  | ||||||
|       <div class="nav__hamburger" @click="toggleNav"> |  | ||||||
|         <div v-for="_ in 3" class="bar"></div> |  | ||||||
|       </div> |  | ||||||
|  |  | ||||||
|       <ul class="nav__list"> |  | ||||||
|         <li class="nav__item" v-for="item in listTypes"> |  | ||||||
|           <router-link class="nav__link" :to="'/list/' + item.route"> |  | ||||||
|             <div class="nav__link-wrap"> |  | ||||||
|               <svg class="nav__link-icon"> |  | ||||||
|                 <use :xlink:href="'#icon_' + item.route"></use> |  | ||||||
|               </svg> |  | ||||||
|               <span class="nav__link-title">{{ item.title }}</span> |  | ||||||
|             </div> |  | ||||||
|           </router-link> |  | ||||||
|         </li> |  | ||||||
|  |  | ||||||
|         <li class="nav__item nav__item--profile"> |  | ||||||
|           <router-link class="nav__link nav__link--profile" :to="{name: 'signin'}" v-if="!userLoggedIn"> |  | ||||||
|             <div class="nav__link-wrap"> |  | ||||||
|               <svg class="nav__link-icon"> |  | ||||||
|                 <use xlink:href="#iconLogin"></use> |  | ||||||
|               </svg> |  | ||||||
|               <span class="nav__link-title">Sign in</span> |  | ||||||
|             </div> |  | ||||||
|           </router-link> |  | ||||||
|  |  | ||||||
|           <router-link class="nav__link nav__link--profile" :to="{name: 'profile'}" v-if="userLoggedIn"> |  | ||||||
|             <div class="nav__link-wrap"> |  | ||||||
|               <svg class="nav__link-icon"> |  | ||||||
|                 <use xlink:href="#iconLogin"></use> |  | ||||||
|               </svg> |  | ||||||
|               <span class="nav__link-title">Profile</span> |  | ||||||
|             </div> |  | ||||||
|           </router-link> |  | ||||||
|         </li> |  | ||||||
|       </ul> |  | ||||||
|     </nav> |  | ||||||
|  |  | ||||||
|     <div class="spacer"></div> |  | ||||||
|   </div> |  | ||||||
| </template> |  | ||||||
|  |  | ||||||
| <script> |  | ||||||
| import storage from '@/storage' |  | ||||||
|  |  | ||||||
| export default { |  | ||||||
|   data(){ |  | ||||||
|     return { |  | ||||||
|       listTypes: storage.homepageLists, |  | ||||||
|       userLoggedIn: localStorage.getItem('token') ? true : false |  | ||||||
|     } |  | ||||||
|   }, |  | ||||||
|   methods: { |  | ||||||
|     setUserStatus(){ |  | ||||||
|       this.userLoggedIn = localStorage.getItem('token') ? true : false; |  | ||||||
|     }, |  | ||||||
|     toggleNav(){ |  | ||||||
|       document.querySelector('.nav__hamburger').classList.toggle('nav__hamburger--active'); |  | ||||||
|       document.querySelector('.nav__list').classList.toggle('nav__list--active'); |  | ||||||
|     } |  | ||||||
|   }, |  | ||||||
|   created(){ |  | ||||||
|     // TODO move this to state manager |  | ||||||
|     eventHub.$on('setUserStatus', this.setUserStatus); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| </script> |  | ||||||
|  |  | ||||||
| <style lang="scss" scoped> |  | ||||||
| @import "./src/scss/variables"; |  | ||||||
| @import "./src/scss/media-queries"; |  | ||||||
|  |  | ||||||
| .icon { |  | ||||||
|   width: 30px; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .spacer { |  | ||||||
|   @include mobile-only { |  | ||||||
|     width: 100%; |  | ||||||
|     height: $header-size; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .nav { |  | ||||||
|   transition: background .5s ease; |  | ||||||
|   position: fixed; |  | ||||||
|   top: 0; |  | ||||||
|   left: 0; |  | ||||||
|   width: 100%; |  | ||||||
|   height: 50px; |  | ||||||
|   z-index: 10; |  | ||||||
|   display: block; |  | ||||||
|   color: $text-color; |  | ||||||
|   background-color: $background-color-secondary; |  | ||||||
|  |  | ||||||
|   @include tablet-min{ |  | ||||||
|     width: 95px; |  | ||||||
|     height: 100vh; |  | ||||||
|   } |  | ||||||
|   &__logo { |  | ||||||
|     width: 55px; |  | ||||||
|     height: $header-size; |  | ||||||
|     display: flex; |  | ||||||
|     align-items: center; |  | ||||||
|     justify-content: center; |  | ||||||
|     background: $background-nav-logo; |  | ||||||
|     @include tablet-min{ |  | ||||||
|       width: 95px; |  | ||||||
|     } |  | ||||||
|     &-image{ |  | ||||||
|       width: 35px; |  | ||||||
|       height: 31px; |  | ||||||
|       fill: $green; |  | ||||||
|       transition: transform 0.5s ease; |  | ||||||
|       @include tablet-min{ |  | ||||||
|         width: 45px; |  | ||||||
|         height: 40px; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     &:hover &-image { |  | ||||||
|       transform: scale(1.04); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   &__hamburger { |  | ||||||
|     display: block; |  | ||||||
|     position: fixed; |  | ||||||
|     width: 55px; |  | ||||||
|     height: 50px; |  | ||||||
|     top: 0; |  | ||||||
|     right: 0; |  | ||||||
|     cursor: pointer; |  | ||||||
|     z-index: 10; |  | ||||||
|     border-left: 1px solid $background-color; |  | ||||||
|     @include tablet-min{ |  | ||||||
|       display: none; |  | ||||||
|     } |  | ||||||
|     .bar { |  | ||||||
|       position: absolute; |  | ||||||
|       width: 23px; |  | ||||||
|       height: 1px; |  | ||||||
|       background-color: $text-color-70; |  | ||||||
|       transition: all 300ms ease; |  | ||||||
|       &:nth-child(1) { |  | ||||||
|         left: 16px; |  | ||||||
|         top: 17px; |  | ||||||
|       } |  | ||||||
|       &:nth-child(2) { |  | ||||||
|         left: 16px; |  | ||||||
|         top: 25px; |  | ||||||
|         &:after { |  | ||||||
|           content: ""; |  | ||||||
|           position: absolute; |  | ||||||
|           left: 0px; |  | ||||||
|           top: 0px; |  | ||||||
|           width: 23px; |  | ||||||
|           height: 1px; |  | ||||||
|           transition: all 300ms ease; |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       &:nth-child(3) { |  | ||||||
|         right: 15px; |  | ||||||
|         top: 33px; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     &--active { |  | ||||||
|       .bar{ |  | ||||||
|         &:nth-child(1), |  | ||||||
|         &:nth-child(3){ |  | ||||||
|           width: 0; |  | ||||||
|         } |  | ||||||
|         &:nth-child(2) { |  | ||||||
|           transform: rotate(-45deg); |  | ||||||
|         } |  | ||||||
|         &:nth-child(2):after { |  | ||||||
|           transform: rotate(-90deg); |  | ||||||
|           // background: rgba($c-dark, 0.5); |  | ||||||
|           background-color: $text-color-70; |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   &__list { |  | ||||||
|     list-style: none; |  | ||||||
|     padding: 0; |  | ||||||
|     margin: 0; |  | ||||||
|     text-align: center; |  | ||||||
|     width: 100%; |  | ||||||
|     position: fixed; |  | ||||||
|     left: 0; |  | ||||||
|     top: 50px; |  | ||||||
|     border-top: 1px solid $background-color; |  | ||||||
|     @include mobile-only { |  | ||||||
|       display: flex; |  | ||||||
|       flex-wrap: wrap; |  | ||||||
|       font-size: 0; |  | ||||||
|       opacity: 0; |  | ||||||
|       visibility: hidden; |  | ||||||
|       background-color: $background-95; |  | ||||||
|       text-align: left; |  | ||||||
|       &--active{ |  | ||||||
|         opacity: 1; |  | ||||||
|         visibility: visible; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     @include tablet-min { |  | ||||||
|       display: flex; |  | ||||||
|       position: relative; |  | ||||||
|       display: block; |  | ||||||
|       width: 100%; |  | ||||||
|       border-top: 0; |  | ||||||
|       top: 0; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   &__item { |  | ||||||
|     transition: background .5s ease, color .5s ease, border .5s ease; |  | ||||||
|     background-color: $background-color-secondary; |  | ||||||
|     color: $text-color-70; |  | ||||||
|  |  | ||||||
|     @include mobile-only { |  | ||||||
|       flex: 0 0 50%; |  | ||||||
|       text-align: center; |  | ||||||
|       border-bottom: 1px solid $background-color; |  | ||||||
|       &:nth-child(odd){ |  | ||||||
|         border-right: 1px solid $background-color; |  | ||||||
|  |  | ||||||
|         &:last-child { |  | ||||||
|           // flex: 0 0 100%; |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     @include tablet-min { |  | ||||||
|       width: 100%; |  | ||||||
|       border-bottom: 1px solid $text-color-5; |  | ||||||
|  |  | ||||||
|       &--profile { |  | ||||||
|         position: fixed; |  | ||||||
|         right: 0; |  | ||||||
|         top: 0; |  | ||||||
|         width: $header-size; |  | ||||||
|         height: $header-size; |  | ||||||
|         border-bottom: 0; |  | ||||||
|         border-left: 1px solid $background-color; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     &:hover, .is-active { |  | ||||||
|       color: $text-color; |  | ||||||
|       background-color: $background-color; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   &__link { |  | ||||||
|     background-color: inherit; // a elements have a transparent background |  | ||||||
|     width: 100%; |  | ||||||
|     display: flex; |  | ||||||
|     flex-wrap: wrap; |  | ||||||
|     align-items: center; |  | ||||||
|     justify-content: center; |  | ||||||
|     font-size: 7px; |  | ||||||
|     font-weight: 300; |  | ||||||
|     text-decoration: none; |  | ||||||
|     text-transform: uppercase; |  | ||||||
|     letter-spacing: 0.5px; |  | ||||||
|     position: relative; |  | ||||||
|     cursor: pointer; |  | ||||||
|     &-wrap { |  | ||||||
|       display: flex; |  | ||||||
|       flex-direction: column; |  | ||||||
|       align-items: center; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @include mobile-only { |  | ||||||
|       font-size: 10px; |  | ||||||
|       padding: 20px 0; |  | ||||||
|     } |  | ||||||
|     @include tablet-min { |  | ||||||
|       width: 95px; |  | ||||||
|       height: 95px; |  | ||||||
|       font-size: 9px; |  | ||||||
|       &--profile { |  | ||||||
|         width: 75px; |  | ||||||
|         height: 75px; |  | ||||||
|         background-color: $background-color-secondary; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     &-icon { |  | ||||||
|       width: 20px; |  | ||||||
|       height: 20px; |  | ||||||
|       fill: $text-color-70; |  | ||||||
|       @include tablet-min { |  | ||||||
|         width: 20px; |  | ||||||
|         height: 20px; |  | ||||||
|         margin-bottom: 5px; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|     } |  | ||||||
|     &-title { |  | ||||||
|       margin-top: 5px; |  | ||||||
|       display: block; |  | ||||||
|       width: 100%; |  | ||||||
|     } |  | ||||||
|     &:hover &-icon, &.is-active &-icon { |  | ||||||
|       fill: $text-color; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
							
								
								
									
										344
									
								
								src/components/NavigationHeader.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										344
									
								
								src/components/NavigationHeader.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,344 @@ | |||||||
|  | <template> | ||||||
|  |   <nav> | ||||||
|  |     <router-link class="nav__logo" to="/home" exact> | ||||||
|  |       <TmdbLogo class="logo" /> | ||||||
|  |     </router-link> | ||||||
|  |  | ||||||
|  |     <SearchInput /> | ||||||
|  |  | ||||||
|  |     <div class="nav__hamburger" @click="toggleNav"> | ||||||
|  |       <div v-for="_ in 3" class="bar"></div> | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     <router-link class="profile desktop-only" to="/profile"> | ||||||
|  |       <li class="navigation-link"> | ||||||
|  |         <icon-profile class="navigation-icon" /> | ||||||
|  |         <span>{{ !userLoggedIn ? "Signin" : "Profile" }}</span> | ||||||
|  |       </li> | ||||||
|  |     </router-link> | ||||||
|  |     <!-- <NavigationIcons class="desktop-only" /> --> | ||||||
|  |  | ||||||
|  |     <div class="nav__list mobile-only"> | ||||||
|  |       <NavigationIcons> | ||||||
|  |         <router-link | ||||||
|  |           v-if="userLoggedIn" | ||||||
|  |           class="settings" | ||||||
|  |           to="/profile?settings=true" | ||||||
|  |         > | ||||||
|  |           <li class="navigation-link"> | ||||||
|  |             <icon-settings class="navigation-icon stroke" /> | ||||||
|  |             <span>Settings</span> | ||||||
|  |           </li> | ||||||
|  |         </router-link> | ||||||
|  |  | ||||||
|  |         <router-link | ||||||
|  |           v-if="userLoggedIn" | ||||||
|  |           class="profile" | ||||||
|  |           to="/profile?activity=true" | ||||||
|  |         > | ||||||
|  |           <li class="navigation-link"> | ||||||
|  |             <icon-activity class="navigation-icon stroke" /> | ||||||
|  |             <span>Activity</span> | ||||||
|  |           </li> | ||||||
|  |         </router-link> | ||||||
|  |  | ||||||
|  |         <router-link class="profile" to="/profile"> | ||||||
|  |           <li class="navigation-link"> | ||||||
|  |             <icon-profile class="navigation-icon" /> | ||||||
|  |             <span>{{ !userLoggedIn ? "Signin" : "Profile" }}</span> | ||||||
|  |           </li> | ||||||
|  |         </router-link> | ||||||
|  |       </NavigationIcons> | ||||||
|  |  | ||||||
|  |       <!--       <li class="nav__item nav__item--profile"> | ||||||
|  |         <router-link | ||||||
|  |           class="nav__link nav__link--profile" | ||||||
|  |           :to="{ name: 'signin' }" | ||||||
|  |           v-if="!userLoggedIn" | ||||||
|  |         > | ||||||
|  |           <div class="nav__link-wrap"> | ||||||
|  |             <svg class="nav__link-icon"> | ||||||
|  |               <use xlink:href="#iconLogin"></use> | ||||||
|  |             </svg> | ||||||
|  |             <span class="nav__link-title">Sign in</span> | ||||||
|  |           </div> | ||||||
|  |         </router-link> | ||||||
|  |  | ||||||
|  |         <router-link | ||||||
|  |           class="nav__link nav__link--profile" | ||||||
|  |           :to="{ name: 'profile' }" | ||||||
|  |           v-if="userLoggedIn" | ||||||
|  |         > | ||||||
|  |           <div class="nav__link-wrap"> | ||||||
|  |             <svg class="nav__link-icon"> | ||||||
|  |               <use xlink:href="#iconLogin"></use> | ||||||
|  |             </svg> | ||||||
|  |             <span class="nav__link-title">Profile</span> | ||||||
|  |           </div> | ||||||
|  |         </router-link> | ||||||
|  |       </li> --> | ||||||
|  |     </div> | ||||||
|  |     <div style="z-index: -1"></div> | ||||||
|  |   </nav> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  | import storage from "@/storage"; | ||||||
|  | import TmdbLogo from "../icons/tmdb-logo"; | ||||||
|  | import IconProfile from "../icons/IconProfile"; | ||||||
|  | import IconSettings from "../icons/IconSettings"; | ||||||
|  | import IconActivity from "../icons/IconActivity"; | ||||||
|  | import SearchInput from "@/components/SearchInput"; | ||||||
|  | import NavigationIcons from "src/components/NavigationIcons"; | ||||||
|  |  | ||||||
|  | export default { | ||||||
|  |   components: { | ||||||
|  |     NavigationIcons, | ||||||
|  |     SearchInput, | ||||||
|  |     TmdbLogo, | ||||||
|  |     IconProfile, | ||||||
|  |     IconSettings, | ||||||
|  |     IconActivity | ||||||
|  |   }, | ||||||
|  |   data() { | ||||||
|  |     return { | ||||||
|  |       listTypes: storage.homepageLists, | ||||||
|  |       userLoggedIn: localStorage.getItem("token") ? true : false | ||||||
|  |     }; | ||||||
|  |   }, | ||||||
|  |   methods: { | ||||||
|  |     setUserStatus() { | ||||||
|  |       this.userLoggedIn = localStorage.getItem("token") ? true : false; | ||||||
|  |     }, | ||||||
|  |     toggleNav() { | ||||||
|  |       document | ||||||
|  |         .querySelector(".nav__hamburger") | ||||||
|  |         .classList.toggle("nav__hamburger--active"); | ||||||
|  |       document | ||||||
|  |         .querySelector(".nav__list") | ||||||
|  |         .classList.toggle("nav__list--active"); | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   created() { | ||||||
|  |     // TODO move this to state manager | ||||||
|  |     eventHub.$on("setUserStatus", this.setUserStatus); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style lang="scss"> | ||||||
|  | @import "./src/scss/media-queries"; | ||||||
|  |  | ||||||
|  | .navigation-link { | ||||||
|  |   display: grid; | ||||||
|  |   place-items: center; | ||||||
|  |   list-style: none; | ||||||
|  |   padding: 1rem 0.15rem; | ||||||
|  |   margin: 0; | ||||||
|  |   text-align: center; | ||||||
|  |   background-color: var(--background-color-secondary); | ||||||
|  |   transition: transform 0.3s ease, color 0.3s ease, stoke 0.3s ease, | ||||||
|  |     fill 0.3s ease, background-color 0.5s ease; | ||||||
|  |  | ||||||
|  |   height: var(--header-size); | ||||||
|  |  | ||||||
|  |   @include mobile { | ||||||
|  |     padding: 1rem; | ||||||
|  |     width: 50vw; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   &:hover { | ||||||
|  |     transform: scale(1.05); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   &:hover, | ||||||
|  |   &.active { | ||||||
|  |     background-color: var(--background-color); | ||||||
|  |  | ||||||
|  |     span, | ||||||
|  |     .navigation-icon { | ||||||
|  |       color: var(--text-color); | ||||||
|  |       fill: var(--text-color); | ||||||
|  |  | ||||||
|  |       &.stroke { | ||||||
|  |         stroke: var(--text-color); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   span { | ||||||
|  |     text-transform: uppercase; | ||||||
|  |     margin-top: 0.75rem; | ||||||
|  |     font-size: 11px; | ||||||
|  |     color: var(--text-color-70); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | a { | ||||||
|  |   text-decoration: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .navigation-icon { | ||||||
|  |   width: 28px; | ||||||
|  |   fill: var(--text-color-70); | ||||||
|  |   transition: inherit; | ||||||
|  |  | ||||||
|  |   &.stroke { | ||||||
|  |     stroke: var(--text-color-70); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||
|  | <style lang="scss" scoped> | ||||||
|  | @import "./src/scss/variables"; | ||||||
|  | @import "./src/scss/media-queries"; | ||||||
|  |  | ||||||
|  | .spacer { | ||||||
|  |   @include mobile-only { | ||||||
|  |     width: 100%; | ||||||
|  |     height: $header-size; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | nav { | ||||||
|  |   display: grid; | ||||||
|  |   grid-template-columns: var(--header-size) 1fr var(--header-size); | ||||||
|  |  | ||||||
|  |   > * { | ||||||
|  |     z-index: 10; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .logo { | ||||||
|  |   padding: 1rem; | ||||||
|  |   fill: var(--color-green); | ||||||
|  |   transition: transform 0.3s ease; | ||||||
|  |  | ||||||
|  |   &:hover { | ||||||
|  |     transform: scale(1.08); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @include mobile { | ||||||
|  |     padding: 0.5rem; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav { | ||||||
|  |   // transition: background 0.5s ease; | ||||||
|  |   // position: fixed; | ||||||
|  |   // top: 0; | ||||||
|  |   // left: 0; | ||||||
|  |   // width: 100%; | ||||||
|  |   // height: 50px; | ||||||
|  |   // z-index: 10; | ||||||
|  |   // display: block; | ||||||
|  |   // color: $text-color; | ||||||
|  |   // background-color: $background-color-secondary; | ||||||
|  |  | ||||||
|  |   &__logo { | ||||||
|  |     width: var(--header-size); | ||||||
|  |     height: var(--header-size); | ||||||
|  |     display: flex; | ||||||
|  |     align-items: center; | ||||||
|  |     justify-content: center; | ||||||
|  |     background: $background-nav-logo; | ||||||
|  |  | ||||||
|  |     // &-image { | ||||||
|  |     //   width: 35px; | ||||||
|  |     //   height: 31px; | ||||||
|  |     //   fill: $green; | ||||||
|  |     //   transition: transform 0.5s ease; | ||||||
|  |     //   @include tablet-min { | ||||||
|  |     //     width: 45px; | ||||||
|  |     //     height: 40px; | ||||||
|  |     //   } | ||||||
|  |     // } | ||||||
|  |     // &:hover &-image { | ||||||
|  |     //   transform: scale(1.04); | ||||||
|  |     // } | ||||||
|  |   } | ||||||
|  |   &__hamburger { | ||||||
|  |     display: block; | ||||||
|  |     position: relative; | ||||||
|  |     width: var(--header-size); | ||||||
|  |     height: var(--header-size); | ||||||
|  |     cursor: pointer; | ||||||
|  |     border-left: 1px solid $background-color; | ||||||
|  |     background-color: var(--background-color-secondary); | ||||||
|  |  | ||||||
|  |     @include tablet-min { | ||||||
|  |       display: none; | ||||||
|  |     } | ||||||
|  |     .bar { | ||||||
|  |       position: absolute; | ||||||
|  |       width: 23px; | ||||||
|  |       height: 1px; | ||||||
|  |       background-color: $text-color-70; | ||||||
|  |       transition: all 300ms ease; | ||||||
|  |       &:nth-child(1) { | ||||||
|  |         left: 16px; | ||||||
|  |         top: 17px; | ||||||
|  |       } | ||||||
|  |       &:nth-child(2) { | ||||||
|  |         left: 16px; | ||||||
|  |         top: 25px; | ||||||
|  |         &:after { | ||||||
|  |           content: ""; | ||||||
|  |           position: absolute; | ||||||
|  |           left: 0px; | ||||||
|  |           top: 0px; | ||||||
|  |           width: 23px; | ||||||
|  |           height: 1px; | ||||||
|  |           transition: all 300ms ease; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       &:nth-child(3) { | ||||||
|  |         right: 15px; | ||||||
|  |         top: 33px; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     &--active { | ||||||
|  |       .bar { | ||||||
|  |         &:nth-child(1), | ||||||
|  |         &:nth-child(3) { | ||||||
|  |           width: 0; | ||||||
|  |         } | ||||||
|  |         &:nth-child(2) { | ||||||
|  |           transform: rotate(-45deg); | ||||||
|  |         } | ||||||
|  |         &:nth-child(2):after { | ||||||
|  |           transform: rotate(-90deg); | ||||||
|  |           // background: rgba($c-dark, 0.5); | ||||||
|  |           background-color: $text-color-70; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   &__list { | ||||||
|  |     width: 100%; | ||||||
|  |     position: fixed; | ||||||
|  |     left: 0; | ||||||
|  |     top: var(--header-size); | ||||||
|  |     opacity: 0; | ||||||
|  |     transition: opacity 0.4s ease; | ||||||
|  |     visibility: hidden; | ||||||
|  |  | ||||||
|  |     @include mobile-only { | ||||||
|  |       display: flex; | ||||||
|  |       flex-wrap: wrap; | ||||||
|  |       background-color: $background-95; | ||||||
|  |       &--active { | ||||||
|  |         opacity: 1; | ||||||
|  |         visibility: visible; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     @include tablet-min { | ||||||
|  |       display: flex; | ||||||
|  |       position: relative; | ||||||
|  |       display: block; | ||||||
|  |       width: 100%; | ||||||
|  |       border-top: 0; | ||||||
|  |       top: 0; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||
							
								
								
									
										95
									
								
								src/components/NavigationIcons.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								src/components/NavigationIcons.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | |||||||
|  | <template> | ||||||
|  |   <ul class="navigation-icons"> | ||||||
|  |     <router-link | ||||||
|  |       :to="{ path: route.route }" | ||||||
|  |       v-for="route in routes" | ||||||
|  |       :key="route.title" | ||||||
|  |     > | ||||||
|  |       <li | ||||||
|  |         class="navigation-link" | ||||||
|  |         :class="{ active: route.route == activeRoute }" | ||||||
|  |       > | ||||||
|  |         <component class="navigation-icon" :is="route.icon"></component> | ||||||
|  |         <span>{{ route.title }}</span> | ||||||
|  |       </li> | ||||||
|  |     </router-link> | ||||||
|  |  | ||||||
|  |     <slot></slot> | ||||||
|  |   </ul> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  | import IconRequest from "../icons/IconRequest"; | ||||||
|  | import IconNowPlaying from "../icons/IconNowPlaying"; | ||||||
|  | import IconPopular from "../icons/IconPopular"; | ||||||
|  | import IconUpcoming from "../icons/IconUpcoming"; | ||||||
|  |  | ||||||
|  | export default { | ||||||
|  |   name: "NavigationIcons", | ||||||
|  |   components: { IconRequest, IconPopular, IconNowPlaying, IconUpcoming }, | ||||||
|  |   data() { | ||||||
|  |     return { | ||||||
|  |       routes: [], | ||||||
|  |       activeRoute: null | ||||||
|  |     }; | ||||||
|  |   }, | ||||||
|  |   watch: { | ||||||
|  |     $route() { | ||||||
|  |       this.activeRoute = window.location.pathname; | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   created() { | ||||||
|  |     this.activeRoute = window.location.pathname; | ||||||
|  |     this.routes = this.getAvailableRoutes(); | ||||||
|  |   }, | ||||||
|  |   methods: { | ||||||
|  |     getAvailableRoutes() { | ||||||
|  |       return [ | ||||||
|  |         { | ||||||
|  |           title: "Requests", | ||||||
|  |           route: "/requests", | ||||||
|  |           apiPath: "/v2/requests", | ||||||
|  |           icon: IconRequest | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           title: "Now Playing", | ||||||
|  |           route: "/list/now_playing", | ||||||
|  |           apiPath: "/v2/movie/now_playing", | ||||||
|  |           icon: IconNowPlaying | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           title: "Popular", | ||||||
|  |           route: "/list/popular", | ||||||
|  |           apiPath: "/v2/movie/popular", | ||||||
|  |           icon: IconPopular | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           title: "Upcoming", | ||||||
|  |           route: "/list/upcoming", | ||||||
|  |           apiPath: "/v2/movie/upcoming", | ||||||
|  |           icon: IconUpcoming | ||||||
|  |         } | ||||||
|  |       ]; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style lang="scss" scoped> | ||||||
|  | @import "./src/scss/media-queries"; | ||||||
|  |  | ||||||
|  | .navigation-icons { | ||||||
|  |   display: inline-flex; | ||||||
|  |   flex-direction: column; | ||||||
|  |   margin: 0; | ||||||
|  |   padding-left: 0; | ||||||
|  |   height: 100%; | ||||||
|  |   background-color: var(--background-color-secondary); | ||||||
|  |   z-index: 15; | ||||||
|  |  | ||||||
|  |   @include mobile { | ||||||
|  |     flex-wrap: wrap; | ||||||
|  |     flex-direction: row; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||
| @@ -1,12 +1,15 @@ | |||||||
| <template> | <template> | ||||||
|   <ul class="results" :class="{'shortList': shortList}"> |   <ul class="results" :class="{ shortList: shortList }"> | ||||||
|     <movies-list-item v-for='movie in results' :movie="movie" /> |     <movies-list-item | ||||||
|  |       v-for="movie in results" | ||||||
|  |       :movie="movie" | ||||||
|  |       :key="movie.title" | ||||||
|  |     /> | ||||||
|   </ul> |   </ul> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
|  |  | ||||||
| <script> | <script> | ||||||
| import MoviesListItem from '@/components/MoviesListItem' | import MoviesListItem from "@/components/MoviesListItem"; | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   components: { MoviesListItem }, |   components: { MoviesListItem }, | ||||||
|   | |||||||
| @@ -15,9 +15,12 @@ | |||||||
|         @keydown.escape="handleEscape" |         @keydown.escape="handleEscape" | ||||||
|         @keyup.enter="handleSubmit" |         @keyup.enter="handleSubmit" | ||||||
|         @keydown.up="navigateUp" |         @keydown.up="navigateUp" | ||||||
|         @keydown.down="navigateDown" /> |         @keydown.down="navigateDown" | ||||||
|  |       /> | ||||||
|  |  | ||||||
|       <svg class="search-icon" fill="currentColor" @click="handleSubmit"><use xlink:href="#iconSearch"></use></svg> |       <svg class="search-icon" fill="currentColor" @click="handleSubmit"> | ||||||
|  |         <use xlink:href="#iconSearch"></use> | ||||||
|  |       </svg> | ||||||
|     </div> |     </div> | ||||||
|  |  | ||||||
|     <transition name="fade"> |     <transition name="fade"> | ||||||
| @@ -26,10 +29,14 @@ | |||||||
|           <h2>Filter your search:</h2> |           <h2>Filter your search:</h2> | ||||||
|  |  | ||||||
|           <div class="filter-items"> |           <div class="filter-items"> | ||||||
|             <toggle-button :options="searchTypes" :selected.sync="selectedSearchType" /> |             <toggle-button | ||||||
|  |               :options="searchTypes" | ||||||
|  |               :selected.sync="selectedSearchType" | ||||||
|  |             /> | ||||||
|  |  | ||||||
|             <label>Adult |             <label | ||||||
|               <input type="checkbox" value="adult" v-model="adult"> |               >Adult | ||||||
|  |               <input type="checkbox" value="adult" v-model="adult" /> | ||||||
|             </label> |             </label> | ||||||
|           </div> |           </div> | ||||||
|         </div> |         </div> | ||||||
| @@ -37,49 +44,57 @@ | |||||||
|         <hr /> |         <hr /> | ||||||
|  |  | ||||||
|         <div class="dropdown-results" v-if="elasticSearchResults.length"> |         <div class="dropdown-results" v-if="elasticSearchResults.length"> | ||||||
|           <ul v-for="(item, index) in elasticSearchResults" |           <ul | ||||||
|  |             v-for="(item, index) in elasticSearchResults" | ||||||
|             @click="openResult(item, index + 1)" |             @click="openResult(item, index + 1)" | ||||||
|               :class="{ active: index + 1 === selectedResult}"> |             :class="{ active: index + 1 === selectedResult }" | ||||||
|                  |           > | ||||||
|               {{ item.name }} |             {{ | ||||||
|  |               item.name | ||||||
|  |             }} | ||||||
|           </ul> |           </ul> | ||||||
|         </div> |         </div> | ||||||
|  |  | ||||||
|         <div v-else class="dropdown"> |         <div v-else class="dropdown"> | ||||||
|           <div class="dropdown-results"> |           <div class="dropdown-results"> | ||||||
|             <h2 class="not-found">No results for query: <b>{{ query }}</b></h2> |             <h2 class="not-found"> | ||||||
|  |               No results for query: <b>{{ query }}</b> | ||||||
|  |             </h2> | ||||||
|           </div> |           </div> | ||||||
|         </div> |         </div> | ||||||
|  |  | ||||||
|         <seasoned-button class="end-section" fullWidth="true"  |         <seasoned-button | ||||||
|           @click="focus = false" :active="elasticSearchResults.length + 1 === selectedResult"> |           class="end-section" | ||||||
|  |           fullWidth="true" | ||||||
|  |           @click="focus = false" | ||||||
|  |           :active="elasticSearchResults.length + 1 === selectedResult" | ||||||
|  |         > | ||||||
|           close |           close | ||||||
|         </seasoned-button> |         </seasoned-button> | ||||||
|       </div> |       </div> | ||||||
|  |  | ||||||
|     </transition> |     </transition> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script> | <script> | ||||||
| import SeasonedButton from '@/components/ui/SeasonedButton' | import SeasonedButton from "@/components/ui/SeasonedButton"; | ||||||
| import ToggleButton from '@/components/ui/ToggleButton'; | import ToggleButton from "@/components/ui/ToggleButton"; | ||||||
|  |  | ||||||
| import { elasticSearchMoviesAndShows } from '@/api' | import { elasticSearchMoviesAndShows } from "@/api"; | ||||||
| import config from '@/config.json' | import config from "@/config.json"; | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   name: 'SearchInput', |   name: "SearchInput", | ||||||
|   components: { |   components: { | ||||||
|     SeasonedButton, |     SeasonedButton, | ||||||
|     ToggleButton |     ToggleButton | ||||||
|   }, |   }, | ||||||
|   props: ['value'], |   props: ["value"], | ||||||
|   data() { |   data() { | ||||||
|     return { |     return { | ||||||
|       adult: true, |       adult: true, | ||||||
|       searchTypes: ['all', 'movie', 'show', 'person'], |       searchTypes: ["all", "movie", "show", "person"], | ||||||
|       selectedSearchType: 'all', |       selectedSearchType: "all", | ||||||
|  |  | ||||||
|       query: this.value, |       query: this.value, | ||||||
|       focus: false, |       focus: false, | ||||||
| @@ -87,144 +102,150 @@ export default { | |||||||
|       scrollListener: undefined, |       scrollListener: undefined, | ||||||
|       scrollDistance: 0, |       scrollDistance: 0, | ||||||
|       elasticSearchResults: [], |       elasticSearchResults: [], | ||||||
|       selectedResult: 0, |       selectedResult: 0 | ||||||
|     } |     }; | ||||||
|   }, |   }, | ||||||
|   watch: { |   watch: { | ||||||
|     focus: function(val) { |     focus: function (val) { | ||||||
|       if (val === true) { |       if (val === true) { | ||||||
|         window.addEventListener('scroll', this.disableFocus) |         window.addEventListener("scroll", this.disableFocus); | ||||||
|       } else { |       } else { | ||||||
|         window.removeEventListener('scroll', this.disableFocus) |         window.removeEventListener("scroll", this.disableFocus); | ||||||
|         this.scrollDistance = 0 |         this.scrollDistance = 0; | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     adult: function(value) { |     adult: function (value) { | ||||||
|       this.handleInput() |       this.handleInput(); | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   beforeMount() { |   beforeMount() { | ||||||
|     const elasticUrl = config.ELASTIC_URL |     const elasticUrl = config.ELASTIC_URL; | ||||||
|     if (elasticUrl === undefined || elasticUrl === false || elasticUrl === '') { |     if (elasticUrl === undefined || elasticUrl === false || elasticUrl === "") { | ||||||
|       this.disabled = true |       this.disabled = true; | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   beforeDestroy() { |   beforeDestroy() { | ||||||
|     console.log('scroll eventlistener not removed, destroying!') |     console.log("scroll eventlistener not removed, destroying!"); | ||||||
|     window.removeEventListener('scroll', this.disableFocus) |     window.removeEventListener("scroll", this.disableFocus); | ||||||
|   }, |   }, | ||||||
|   methods: { |   methods: { | ||||||
|     navigateDown() { |     navigateDown() { | ||||||
|       this.focus = true |       this.focus = true; | ||||||
|       this.selectedResult++ |       this.selectedResult++; | ||||||
|     }, |     }, | ||||||
|     navigateUp() { |     navigateUp() { | ||||||
|       this.focus = true |       this.focus = true; | ||||||
|       this.selectedResult-- |       this.selectedResult--; | ||||||
|       const input = this.$refs.input; |       const input = this.$refs.input; | ||||||
|       const textLength = input.value.length |       const textLength = input.value.length; | ||||||
|  |  | ||||||
|       setTimeout(() => { |       setTimeout(() => { | ||||||
|         input.focus() |         input.focus(); | ||||||
|         input.setSelectionRange(textLength, textLength + 1) |         input.setSelectionRange(textLength, textLength + 1); | ||||||
|       }, 1) |       }, 1); | ||||||
|     }, |     }, | ||||||
|     openResult(item, index) { |     openResult(item, index) { | ||||||
|       this.selectedResult = index; |       this.selectedResult = index; | ||||||
|       this.$popup.open(item.id, item.type) |       this.$popup.open(item.id, item.type); | ||||||
|     }, |     }, | ||||||
|     handleInput(e){ |     handleInput(e) { | ||||||
|       this.selectedResult = 0 |       this.selectedResult = 0; | ||||||
|       this.$emit('input', this.query); |       this.$emit("input", this.query); | ||||||
|  |  | ||||||
|       if (! this.focus) { |       if (!this.focus) { | ||||||
|         this.focus = true; |         this.focus = true; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       elasticSearchMoviesAndShows(this.query) |       elasticSearchMoviesAndShows(this.query).then(resp => { | ||||||
|       .then(resp => { |         const data = resp.hits.hits; | ||||||
|         const data = resp.hits.hits |  | ||||||
|  |  | ||||||
|         let results = data.map(item => { |         let results = data.map(item => { | ||||||
|           const index = item._index.slice(0, -1) |           const index = item._index.slice(0, -1); | ||||||
|           if (index === 'movie' || item._source.original_title) { |           if (index === "movie" || item._source.original_title) { | ||||||
|             return { |             return { | ||||||
|               name: item._source.original_title, |               name: item._source.original_title, | ||||||
|               id: item._source.id, |               id: item._source.id, | ||||||
|               adult: item._source.adult, |               adult: item._source.adult, | ||||||
|               type: 'movie' |               type: "movie" | ||||||
|             } |             }; | ||||||
|           } else if (index === 'show' || item._source.original_name) { |           } else if (index === "show" || item._source.original_name) { | ||||||
|             return { |             return { | ||||||
|               name: item._source.original_name, |               name: item._source.original_name, | ||||||
|               id: item._source.id, |               id: item._source.id, | ||||||
|               adult: item._source.adult, |               adult: item._source.adult, | ||||||
|               type: 'show' |               type: "show" | ||||||
|  |             }; | ||||||
|           } |           } | ||||||
|           } |         }); | ||||||
|         }) |         results = this.removeDuplicates(results); | ||||||
|         results = this.removeDuplicates(results) |         this.elasticSearchResults = results; | ||||||
|         this.elasticSearchResults = results |       }); | ||||||
|       }) |  | ||||||
|     }, |     }, | ||||||
|     removeDuplicates(searchResults) { |     removeDuplicates(searchResults) { | ||||||
|       let filteredResults = [] |       let filteredResults = []; | ||||||
|       searchResults.map(result => { |       searchResults.map(result => { | ||||||
|         const numberOfDuplicates = filteredResults.filter(filterItem => filterItem.id == result.id) |         const numberOfDuplicates = filteredResults.filter( | ||||||
|  |           filterItem => filterItem.id == result.id | ||||||
|  |         ); | ||||||
|         if (numberOfDuplicates.length >= 1) { |         if (numberOfDuplicates.length >= 1) { | ||||||
|           return null |           return null; | ||||||
|         } |         } | ||||||
|         filteredResults.push(result) |         filteredResults.push(result); | ||||||
|       }) |       }); | ||||||
|  |  | ||||||
|       if (this.adult == false) { |       if (this.adult == false) { | ||||||
|         filteredResults = filteredResults.filter(result => result.adult == false) |         filteredResults = filteredResults.filter( | ||||||
|  |           result => result.adult == false | ||||||
|  |         ); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       return filteredResults |       return filteredResults; | ||||||
|     }, |     }, | ||||||
|     handleSubmit() { |     handleSubmit() { | ||||||
|       let searchResults = this.elasticSearchResults |       let searchResults = this.elasticSearchResults; | ||||||
|  |  | ||||||
|       if (this.selectedResult > searchResults.length) { |       if (this.selectedResult > searchResults.length) { | ||||||
|         this.focus = false |         this.focus = false; | ||||||
|         this.selectedResult = 0 |         this.selectedResult = 0; | ||||||
|       } else if (this.selectedResult > 0) { |       } else if (this.selectedResult > 0) { | ||||||
|         const resultItem = searchResults[this.selectedResult - 1] |         const resultItem = searchResults[this.selectedResult - 1]; | ||||||
|         this.$popup.open(resultItem.id, resultItem.type) |         this.$popup.open(resultItem.id, resultItem.type); | ||||||
|       } else { |       } else { | ||||||
|         const encodedQuery = encodeURI(this.query.replace('/ /g, "+"')) |         const encodedQuery = encodeURI(this.query.replace('/ /g, "+"')); | ||||||
|         const media_type = this.selectedSearchType !== 'all' ? this.selectedSearchType : null |         const media_type = | ||||||
|         this.$router.push({ name: 'search', query: { query: encodedQuery, adult: this.adult, media_type }}); |           this.selectedSearchType !== "all" ? this.selectedSearchType : null; | ||||||
|         this.focus = false |         this.$router.push({ | ||||||
|         this.selectedResult = 0 |           name: "search", | ||||||
|  |           query: { query: encodedQuery, adult: this.adult, media_type } | ||||||
|  |         }); | ||||||
|  |         this.focus = false; | ||||||
|  |         this.selectedResult = 0; | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     handleEscape() { |     handleEscape() { | ||||||
|       if (this.$popup.isOpen) { |       if (this.$popup.isOpen) { | ||||||
|         console.log('THIS WAS FUCKOING OPEN!') |         console.log("THIS WAS FUCKOING OPEN!"); | ||||||
|       } else { |       } else { | ||||||
|         this.focus = false |         this.focus = false; | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     disableFocus(_) { |     disableFocus(_) { | ||||||
|       this.focus = false |       this.focus = false; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | }; | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="scss" scoped> | <style lang="scss" scoped> | ||||||
| @import "./src/scss/variables"; | @import "./src/scss/variables"; | ||||||
| @import "./src/scss/media-queries"; | @import "./src/scss/media-queries"; | ||||||
| @import './src/scss/main'; | @import "./src/scss/main"; | ||||||
|  |  | ||||||
|  |  | ||||||
| .fade-enter-active { | .fade-enter-active { | ||||||
|   transition: opacity .2s; |   transition: opacity 0.2s; | ||||||
| } | } | ||||||
| .fade-leave-active { | .fade-leave-active { | ||||||
|   transition: opacity .2s; |   transition: opacity 0.2s; | ||||||
| } | } | ||||||
| .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ { | .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ { | ||||||
|   opacity: 0; |   opacity: 0; | ||||||
| @@ -311,7 +332,9 @@ hr { | |||||||
|       overflow: hidden; |       overflow: hidden; | ||||||
|       color: $text-color-50; |       color: $text-color-50; | ||||||
|  |  | ||||||
|       &.active, &:hover, &:active { |       &.active, | ||||||
|  |       &:hover, | ||||||
|  |       &:active { | ||||||
|         color: $text-color; |         color: $text-color; | ||||||
|         border-bottom: 2px solid $text-color; |         border-bottom: 2px solid $text-color; | ||||||
|       } |       } | ||||||
| @@ -333,7 +356,7 @@ hr { | |||||||
|   top: 0; |   top: 0; | ||||||
|   right: 55px; |   right: 55px; | ||||||
|  |  | ||||||
|   @include tablet-min{ |   @include tablet-min { | ||||||
|     position: relative; |     position: relative; | ||||||
|     width: 100%; |     width: 100%; | ||||||
|     right: 0px; |     right: 0px; | ||||||
| @@ -348,16 +371,16 @@ hr { | |||||||
|     border: 0; |     border: 0; | ||||||
|     background-color: $background-color-secondary; |     background-color: $background-color-secondary; | ||||||
|     font-weight: 300; |     font-weight: 300; | ||||||
|     font-size: 19px; |     font-size: 18px; | ||||||
|     color: $text-color; |     color: $text-color; | ||||||
|     transition: background-color .5s ease, color .5s ease; |  | ||||||
|  |  | ||||||
|     @include tablet-min { |     @include tablet-min { | ||||||
|  |       font-size: 24px; | ||||||
|       padding: 13px 30px 13px 60px; |       padding: 13px 30px 13px 60px; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   &-icon{ |   &-icon { | ||||||
|     width: 20px; |     width: 20px; | ||||||
|     height: 20px; |     height: 20px; | ||||||
|     fill: $text-color-50; |     fill: $text-color-50; | ||||||
| @@ -365,11 +388,13 @@ hr { | |||||||
|     pointer-events: none; |     pointer-events: none; | ||||||
|     position: absolute; |     position: absolute; | ||||||
|     left: 15px; |     left: 15px; | ||||||
|     top: 15px; |     top: calc(50% - 10px); | ||||||
|  |  | ||||||
|     @include tablet-min{ |     @include tablet-min { | ||||||
|       top: 27px; |       width: 24px; | ||||||
|       left: 25px; |       height: 24px; | ||||||
|  |       top: calc(50% - 12px); | ||||||
|  |       left: 22px; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -21,59 +21,59 @@ $mobile-width: 768px; | |||||||
|  |  | ||||||
| .desktop-only { | .desktop-only { | ||||||
| 	@include mobile { | 	@include mobile { | ||||||
| 		display: none; | 		display: none !important; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| .mobile-only { | .mobile-only { | ||||||
| 	@include desktop { | 	@include desktop { | ||||||
| 		display: none; | 		display: none !important; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // Media | // Media | ||||||
| @mixin mobile-only{ | @mixin mobile-only { | ||||||
| 	@media (max-width: #{$tablet-p-width - 1px}){ | 	@media (max-width: #{$tablet-p-width - 1px}) { | ||||||
| 		@content; | 		@content; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @mixin mobile-ls-min{ | @mixin mobile-ls-min { | ||||||
|   @media (min-width: #{$phone-xs-width}){ | 	@media (min-width: #{$phone-xs-width}) { | ||||||
| 		@content; | 		@content; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @mixin tablet-only{ | @mixin tablet-only { | ||||||
| 	@media (min-width: #{$tablet-p-width}) and (max-width: #{$desktop-width - 1px}){ | 	@media (min-width: #{$tablet-p-width}) and (max-width: #{$desktop-width - 1px}) { | ||||||
| 		@content; | 		@content; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @mixin tablet-min{ | @mixin tablet-min { | ||||||
| 	@media (min-width: #{$tablet-p-width}){ | 	@media (min-width: #{$tablet-p-width}) { | ||||||
| 		@content; | 		@content; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @mixin tablet-portrait-only{ | @mixin tablet-portrait-only { | ||||||
| 	@media (min-width: #{$tablet-p-width}) and (max-width: #{$tablet-l-width - 1px}){ | 	@media (min-width: #{$tablet-p-width}) and (max-width: #{$tablet-l-width - 1px}) { | ||||||
| 		@content; | 		@content; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @mixin tablet-landscape-min{ | @mixin tablet-landscape-min { | ||||||
| 	@media (min-width: #{$tablet-l-width}){ | 	@media (min-width: #{$tablet-l-width}) { | ||||||
| 		@content; | 		@content; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @mixin desktop-min{ | @mixin desktop-min { | ||||||
| 	@media (min-width: #{$desktop-width}){ | 	@media (min-width: #{$desktop-width}) { | ||||||
| 		@content; | 		@content; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @mixin desktop-lg-min{ | @mixin desktop-lg-min { | ||||||
| 	@media (min-width: #{$desktop-l-width}){ | 	@media (min-width: #{$desktop-l-width}) { | ||||||
| 		@content; | 		@content; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @mixin retina{ | @mixin retina { | ||||||
|   @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi){ | 	@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { | ||||||
| 		@content; | 		@content; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -18,12 +18,12 @@ | |||||||
|  |  | ||||||
|   --background-nav-logo: #081c24; |   --background-nav-logo: #081c24; | ||||||
|   --color-green: #01d277; |   --color-green: #01d277; | ||||||
|   --color-green-90: rgba(1, 210, 119, .9); |   --color-green-90: rgba(1, 210, 119, 0.9); | ||||||
|   --color-green-70: rgba(1, 210, 119, .73); |   --color-green-70: rgba(1, 210, 119, 0.73); | ||||||
|   --color-teal: #091c24; |   --color-teal: #091c24; | ||||||
|   --color-black: #081c24; |   --color-black: #081c24; | ||||||
|   --white: #fff; |   --white: #fff; | ||||||
|   --white-70: rgba(255,255,255,0.7); |   --white-70: rgba(255, 255, 255, 0.7); | ||||||
|  |  | ||||||
|   --color-warning: rgba(241, 188, 53, 0.7); |   --color-warning: rgba(241, 188, 53, 0.7); | ||||||
|   --color-warning-highlight: #f1bc35; |   --color-warning-highlight: #f1bc35; | ||||||
| @@ -31,9 +31,9 @@ | |||||||
|   --color-success-text: #fff; |   --color-success-text: #fff; | ||||||
|   --color-success-highlight: rgb(0, 100, 66); |   --color-success-highlight: rgb(0, 100, 66); | ||||||
|   --color-error: rgba(220, 48, 35, 0.8); |   --color-error: rgba(220, 48, 35, 0.8); | ||||||
|   --color-error-highlight: #DC3023; |   --color-error-highlight: #dc3023; | ||||||
|  |  | ||||||
|   --header-size: 75px; |   --header-size: 90px; | ||||||
| } | } | ||||||
|  |  | ||||||
| @media (prefers-color-scheme: dark) { | @media (prefers-color-scheme: dark) { | ||||||
| @@ -55,7 +55,7 @@ | |||||||
|  |  | ||||||
| @include mobile-only { | @include mobile-only { | ||||||
|   :root { |   :root { | ||||||
|     --header-size: 50px; |     --header-size: 55px; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -67,9 +67,9 @@ $green-90: var(--color-green-90); | |||||||
| $green-70: var(--color-green-70); | $green-70: var(--color-green-70); | ||||||
| $teal: #091c24; | $teal: #091c24; | ||||||
| $black: #081c24; | $black: #081c24; | ||||||
| $black-80: rgba(0,0,0,0.8); | $black-80: rgba(0, 0, 0, 0.8); | ||||||
| $white: #fff; | $white: #fff; | ||||||
| $white-80: rgba(255,255,255,0.8); | $white-80: rgba(255, 255, 255, 0.8); | ||||||
|  |  | ||||||
| $text-color: var(--text-color) !default; | $text-color: var(--text-color) !default; | ||||||
| $text-color-70: var(--text-color-70) !default; | $text-color-70: var(--text-color-70) !default; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user