1
1
<script setup lang="ts">
2
- import { NFlex , NSkeleton } from ' naive-ui' ;
3
- import { computed , onActivated , onDeactivated , ref , toRefs } from ' vue' ;
2
+ import { NFlex , NH2 , NH4 , NSkeleton } from ' naive-ui' ;
3
+ import { computed , onMounted , onUnmounted , ref , toRefs , Transition , watch } from ' vue' ;
4
4
5
- import { useRoute } from ' vue-router' ;
6
-
7
- import type { PosterItem } from ' ~/models/poster.model' ;
8
5
import type { TraktEpisodeExtended } from ' ~/models/trakt/trakt-episode.model' ;
9
6
import type { TraktShowExtended } from ' ~/models/trakt/trakt-show.model' ;
10
7
11
- import type { ImageQuery } from ' ~/stores/data/image.store' ;
12
-
13
- import PosterComponent from ' ~/components/common/poster/PosterComponent.vue' ;
8
+ import ShowPanelPicker from ' ~/components/views/panel/ShowPanelPicker.vue' ;
9
+ import ShowPanelPoster from ' ~/components/views/panel/ShowPanelPoster.vue' ;
14
10
import { type ShowSeasons , useShowStore } from ' ~/stores/data/show.store' ;
11
+ import { deCapitalise } from ' ~/utils/string.utils' ;
15
12
16
13
const props = defineProps ({
17
14
showId: {
@@ -37,91 +34,141 @@ const episode = ref<TraktEpisodeExtended>();
37
34
const { showId, seasonNumber, episodeNumber } = toRefs (props );
38
35
39
36
const seasonNb = computed (() => {
40
- if (! seasonNumber ?.value ) return ;
37
+ if (seasonNumber ?.value === undefined ) return ;
41
38
const _seasonNumber = Number (seasonNumber .value );
42
39
if (Number .isNaN (_seasonNumber )) return ;
43
40
return _seasonNumber ;
44
41
});
45
42
46
43
const episodeNb = computed (() => {
47
- if (! episodeNumber ?.value ) return ;
44
+ if (episodeNumber ?.value === undefined ) return ;
48
45
const _episodeNumber = Number (episodeNumber .value );
49
46
if (Number .isNaN (_episodeNumber )) return ;
50
47
return _episodeNumber ;
51
48
});
52
49
53
- const size = computed (() => window ?.innerWidth ?? 800 / 2 );
54
-
55
- const { query } = useRoute ();
56
- const posterItem = computed <PosterItem | undefined >(() => {
57
- const poster = query .poster ?.toString ();
58
- if (poster ) return { poster } satisfies PosterItem ;
59
-
60
- const tmdb = query .tmdb ?.toString ();
61
- if (! tmdb ) return ;
62
- const imageQuery: ImageQuery = {
63
- id: tmdb ,
64
- season: seasonNb .value ,
65
- episode: episodeNb .value ,
66
- type: ' show' ,
67
- };
68
- if (episodeNb .value ) imageQuery .type = ' episode' ;
69
- else if (seasonNb .value ) imageQuery .type = ' season' ;
70
-
71
- return {
72
- posterRef: ref (),
73
- getPosterQuery : () => imageQuery ,
74
- };
50
+ const showTitle = computed (() => {
51
+ if (! show .value ?.title ) return ;
52
+ return deCapitalise (show .value .title );
53
+ });
54
+
55
+ const episodeTitle = computed (() => {
56
+ if (! episode .value ?.title ) return ;
57
+ return deCapitalise (episode .value ?.title );
75
58
});
76
59
77
60
const subscriptions = new Set <() => void >();
78
61
79
- onActivated (() => {
80
- if (showId ?.value ) subscriptions .add (getShowRef (showId .value , show ).unsub );
81
- if (showId ?.value ) subscriptions .add (getShowSeasonsRef (showId .value , seasons ).unsub );
82
- if (showId ?.value && seasonNb ?.value && episodeNb ?.value ) {
83
- subscriptions .add (
84
- getShowEpisodeRef (
85
- {
86
- id: showId .value ,
87
- season: seasonNb .value ,
88
- episode: episodeNb .value ,
89
- },
90
- episode ,
91
- ).unsub ,
92
- );
93
- }
62
+ const watchData = () =>
63
+ watch (
64
+ props ,
65
+ (next , prev ) => {
66
+ if (next .showId !== prev ?.showId ) {
67
+ show .value = undefined ;
68
+ seasons .value = undefined ;
69
+ episode .value = undefined ;
70
+ } else if (next .episodeNumber !== prev ?.episodeNumber ) {
71
+ episode .value = undefined ;
72
+ } else if (next .seasonNumber !== prev ?.seasonNumber ) {
73
+ episode .value = undefined ;
74
+ }
75
+
76
+ if (showId ?.value ) subscriptions .add (getShowRef (showId .value , show ).unsub );
77
+ if (showId ?.value )
78
+ subscriptions .add (getShowSeasonsRef (showId .value , seasons ).unsub );
79
+ if (
80
+ showId ?.value &&
81
+ seasonNb ?.value !== undefined &&
82
+ episodeNb ?.value !== undefined
83
+ ) {
84
+ subscriptions .add (
85
+ getShowEpisodeRef (
86
+ {
87
+ id: showId .value ,
88
+ season: seasonNb .value ,
89
+ episode: episodeNb .value ,
90
+ },
91
+ episode ,
92
+ ).unsub ,
93
+ );
94
+ }
95
+ },
96
+ { immediate: true },
97
+ );
98
+
99
+ onMounted (() => {
100
+ subscriptions .add (watchData ());
94
101
});
95
102
96
- onDeactivated (() => {
103
+ onUnmounted (() => {
97
104
subscriptions .forEach (unsub => unsub ());
98
105
subscriptions .clear ();
99
- show .value = undefined ;
100
- seasons .value = undefined ;
101
- episode .value = undefined ;
102
106
});
103
107
</script >
104
108
105
109
<template >
106
110
<NFlex justify =" center" align =" center" vertical >
107
- <NFlex v-if =" posterItem" class =" poster-container" >
108
- <PosterComponent :item =" posterItem" :episode =" !!episodeNumber" :size =" size" />
109
- </NFlex >
110
- <div >show {{ showId }}</div >
111
- <div v-if =" show" >show : {{ show?.title }}</div >
111
+ <NH2 v-if =" showTitle" class =" show-title" >{{ showTitle }}</NH2 >
112
112
<NSkeleton v-else />
113
- <div >season {{ seasonNumber }}</div >
114
- <div v-if =" seasons" >season {{ Object.keys(seasons) }}</div >
115
- <NSkeleton v-else />
116
- <div >episode {{ episodeNumber }}</div >
117
- <div v-if =" episode" >episode {{ episode?.title }}</div >
118
- <NSkeleton v-else
119
- /></NFlex >
113
+
114
+ <ShowPanelPicker :seasons =" seasons" :season-number =" seasonNb" />
115
+
116
+ <ShowPanelPoster
117
+ :show-id =" show?.ids.tmdb"
118
+ :season-number =" seasonNb"
119
+ :episode-number =" episodeNb"
120
+ />
121
+
122
+ <Transition name =" scale" mode =" out-in" >
123
+ <NFlex
124
+ v-if =" episodeNumber !== undefined"
125
+ :key =" `season-${seasonNb}-episode-${episodeNb}`"
126
+ justify =" center"
127
+ align =" center"
128
+ vertical
129
+ class =" episode-container"
130
+ >
131
+ <NH4 v-if =" episodeTitle" class =" episode-title" >{{ episodeTitle }}</NH4 >
132
+ <NSkeleton v-else />
133
+
134
+ <div v-if =" episode" >{{ episode?.overview }}</div >
135
+ <NSkeleton v-else />
136
+ </NFlex >
137
+ </Transition >
138
+ </NFlex >
120
139
</template >
121
140
122
141
<style lang="scss" scoped>
142
+ @use ' ~/styles/transition' as transition ;
143
+ @include transition .scale ;
144
+
123
145
.poster-container {
124
- --poster-width : 50 dvw;
125
- --poster-height : calc (var (--poster-width ) * (9 / 16 ));
146
+ --poster-height : calc (50 dvw * (9 / 16 ));
147
+ --poster-width : calc (var (--poster-height ) * (2 / 3 ));
148
+
149
+ & .landscape {
150
+ --poster-width : 50 dvw;
151
+ --poster-height : calc (var (--poster-width ) * (9 / 16 ));
152
+ }
153
+
154
+ position : relative ;
155
+ border : 1px solid var (--border-white );
156
+ box-shadow : var (--image-box-shadow );
157
+ }
158
+
159
+ .show-title {
160
+ margin-bottom : 0.5rem ;
161
+ }
162
+
163
+ .episode {
164
+ & -container {
165
+ width : 100% ;
166
+ }
167
+
168
+ & -title {
169
+ margin-top : 1rem ;
170
+ margin-bottom : 1rem ;
171
+ font-weight : bold ;
172
+ }
126
173
}
127
174
</style >
0 commit comments