1
1
<script setup lang="ts">
2
- import {Series , Video } from " .prisma/client" ;
2
+ import { Series , Video } from " .prisma/client" ;
3
3
import getParam from " ~/composables/getParam" ;
4
4
5
+ definePageMeta ({
6
+ layout: false ,
7
+ });
8
+
9
+ const setColorTheme = (newTheme : Theme ) => {
10
+ useColorMode ().preference = newTheme
11
+ }
12
+
13
+
5
14
const route = useRoute ()
6
- const videoElements = ref ([])
7
15
8
16
type topicData = {
9
17
series: Series []
10
18
videos: Video []
11
19
}
12
20
13
21
const topicName = getParam (' name' ) as string
14
- const {data, pending} = await useFetch <topicData >(` /api/topic/${topicName } ` , {key: route .fullPath })
22
+ const { data, pending } = await useFetch <topicData >(` /api/topic/${topicName } ` , { key: route .fullPath })
23
+ const videoPlaceholderElement = ref (null )
24
+ const videoWrapper = ref (null )
25
+
26
+ const activeVideo = ref (data .value .videos [0 ])
15
27
16
- function createIframe(vidId , index ) {
28
+ function setActive(video : Video ) {
29
+ activeVideo .value = video
17
30
18
- const youtubePlaceholder = videoElements .value [index ]
31
+ const htmlString = ` <div class="video__youtube" :id="${activeVideo .value .host_id }">
32
+ <img src="https://i.ytimg.com/vi/${activeVideo .value .host_id }/maxresdefault.jpg"
33
+ class="block object-cover object-center lg:rounded-lg w-full min-w-200 aspect-video mb-10 p-0"
34
+ alt="video thumbnail" />
35
+ </div>
36
+ `
37
+ videoWrapper .value .innerHTML = htmlString ;
38
+ }
39
+
40
+ function createIframe(vidId : string ) {
19
41
const url = ' https://www.youtube.com/embed/' + vidId + ' ?autoplay=1'
20
42
const htmlString = ` <iframe class="mt-5 block object-cover object-center lg:rounded-lg w-full min-w-200 aspect-video mb-10 p-0" src="${url }" allowfullscreen allow="autoplay"></iframe> `
21
43
22
- youtubePlaceholder .style .display = ' none' ;
23
- youtubePlaceholder .insertAdjacentHTML (' beforebegin' , htmlString );
24
- youtubePlaceholder .parentNode .removeChild (youtubePlaceholder );
44
+ videoWrapper .value .innerHTML = htmlString ;
25
45
}
26
46
27
47
</script >
28
48
29
49
<template >
30
- <div class =" dark:bg-slate-800 min-h-screen" v-if =" !pending && data" >
31
- <div >
32
- <section class =" overflow-hidden text-gray-700 p-0" >
33
- <div class =" container px-0 py-2 mx-auto lg:pt-12 lg:px-32" >
34
- <div class =" flex flex-wrap -m-1 md:-m-2" >
35
- <div class =" mt-5" @click =" createIframe(video?.host_id, i)" :ref =" (el) => videoElements[i] = el"
36
- v-for =" (video, i) in data.videos" >
37
- <div class =" video__youtube" :id =" video?.host_id" >
38
- <img :src =" 'https://i.ytimg.com/vi/'+video?.host_id+'/maxresdefault.jpg'"
39
- class =" block object-cover object-center lg:rounded-lg w-full min-w-200 aspect-video mb-10 p-0" alt =" video thumbnail" />
40
- <img src =" /img/youtube_social_icon_red.png" class =" absolute text-5xl text-white top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2" alt =" youtube play button" >
50
+
51
+ <div class =" md:flex" >
52
+ <aside class =" hidden lg:block h-screen pl-10 pr-10 text-left w-1/4 dark:bg-slate-900" >
53
+ <div class =" text-gray-800 dark:text-gray-100 text-xl" >
54
+ <div class =" p-2.5 mt-1 flex items-center" >
55
+
56
+ <NuxtLink to =" /" >
57
+ <img class =" h-20" src =" /img/logo_clear_fsj.png" alt =" full stack jack logo" >
58
+ <h1 class =" font-bold text-gray-800 dark:text-gray-200 text-[15px] ml-3" >Full Stack Jack</h1 >
59
+ </NuxtLink >
60
+
61
+
62
+ </div >
63
+ <div >
64
+
65
+ <span class =" hidden md:block " @click =" setColorTheme($colorMode.preference == 'dark' ? 'light' : 'dark')" >
66
+ <svg v-if =" $colorMode.value == 'dark'" xmlns =" http://www.w3.org/2000/svg"
67
+ class =" h-6 w-6 text-gray-50 hidden lg:block" viewBox =" 0 0 20 20" fill =" currentColor" >
68
+ <path d =" M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" />
69
+ </svg >
70
+ <svg v-if =" $colorMode.value == 'light'" xmlns =" http://www.w3.org/2000/svg" class =" h-6 w-6 hidden lg:block"
71
+ viewBox =" 0 0 20 20" fill =" currentColor" >
72
+ <path fill-rule =" evenodd"
73
+ d =" M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
74
+ clip-rule =" evenodd" />
75
+ </svg >
76
+ </span >
77
+
78
+ </div >
79
+ <div class =" my-2 bg-gray-600 h-[1px]" ></div >
80
+ </div >
81
+ <div >
82
+ <img src =" /img/nuxt3.svg" alt =" " >
83
+ </div >
84
+ <div class =" p-2.5 mt-3 flex items-center rounded-md px-4 duration-300 cursor-pointer hover:bg-green-600 text-white"
85
+ onclick =" dropdown()" >
86
+ <i class =" bi bi-chat-left-text-fill" ></i >
87
+ <div class =" flex justify-between w-full items-center" >
88
+ <span class =" text-sm rotate-180" id =" arrow" >
89
+ <i class =" bi bi-chevron-down" ></i >
90
+ </span >
91
+ </div >
92
+ </div >
93
+ <ul class =" text-left mx-auto text-gray-800 dark:text-gray-200 font-bold" >
94
+ <li class =" cursor-pointer p-2 hover:bg-green-600 rounded-md mt-1" @click =" setActive(video)"
95
+ v-for =" video in data.videos" >
96
+ {{ video.title }}
97
+ </li >
98
+ </ul >
99
+ </aside >
100
+ <div class =" w-screen" v-if =" !pending && data" >
101
+
102
+ <section class =" overflow-hidden text-gray-700 p-0" >
103
+ <div class =" container px-0 py-2 mx-auto lg:pt-12 lg:px-32" >
104
+ <div class =" flex flex-wrap -m-1 md:-m-2 clickable" @click =" createIframe(activeVideo?.host_id)"
105
+ ref =" videoWrapper" >
106
+ <div class =" mt-5" ref =" videoPlaceholderElement align-center justify-center" >
107
+ <div class =" video__youtube container flex" :id =" activeVideo?.host_id" >
108
+ <img :src =" 'https://i.ytimg.com/vi/' + activeVideo?.host_id + '/maxresdefault.jpg'"
109
+ class =" "
110
+ alt =" video thumbnail" />
111
+ <!-- <img src="/img/youtube_social_icon_red.png"
112
+ class="center"
113
+ alt="youtube play button"> -->
114
+ </div >
41
115
</div >
42
116
</div >
43
117
</div >
44
- </div >
45
- </section >
118
+ </section >
119
+
120
+ </div >
121
+ <div class =" md:hidden" >
122
+ <div >
123
+ <img class =" pr-5 pl-5" src =" /img/nuxt3.svg" alt =" " >
124
+ </div >
125
+ <div class =" p-5 flex align-center justify-between" >
126
+ <NuxtLink to =" /" >
127
+ <img class =" h-20" src =" /img/logo_clear_fsj.png" alt =" full stack jack logo" >
128
+ </NuxtLink >
129
+ <span class =" " @click =" setColorTheme($colorMode.preference == 'dark' ? 'light' : 'dark')" >
130
+ <svg v-if =" $colorMode.value == 'dark'" xmlns =" http://www.w3.org/2000/svg"
131
+ class =" h-6 w-6 text-gray-50" viewBox =" 0 0 20 20" fill =" currentColor" >
132
+ <path d =" M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" />
133
+ </svg >
134
+ <svg v-if =" $colorMode.value == 'light'" xmlns =" http://www.w3.org/2000/svg" class =" h-6"
135
+ viewBox =" 0 0 20 20" fill =" currentColor" >
136
+ <path fill-rule =" evenodd"
137
+ d =" M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
138
+ clip-rule =" evenodd" />
139
+ </svg >
140
+ </span >
141
+ </div >
142
+
143
+
144
+ <ul class =" mx-auto text-left mx-auto text-gray-800 dark:text-gray-200 font-bold" >
145
+ <li class =" cursor-pointer p-2 hover:bg-green-600 rounded-md mt-1" @click =" setActive(video)"
146
+ v-for =" video in data.videos" >
147
+ {{ video.title }}
148
+ </li >
149
+ </ul >
46
150
</div >
47
151
</div >
48
- </template >
49
152
50
- <style scoped >
153
+ </ template >
51
154
52
- .video__youtube {
53
- padding-bottom : 56.23% ;
54
- width : 100% ;
55
- height : 0 ;
56
- overflow : hidden ;
57
- position : relative ;
58
- object-fit : cover ;
59
- background-color : black ;
155
+ <style >
156
+ .clickable {
157
+ cursor : pointer ;
60
158
}
61
-
62
159
</style >
0 commit comments