feat: pagination
This commit is contained in:
parent
95f59c3faf
commit
19f86d5b89
4 changed files with 95 additions and 79 deletions
|
@ -3,65 +3,47 @@
|
|||
class="border-t border-gray-200 flex items-center justify-between max-w-2xl mx-auto p-4 sm:px-6 lg:max-w-7xl"
|
||||
>
|
||||
<div class="-mt-px w-0 flex-1 flex">
|
||||
<a
|
||||
<NuxtLink
|
||||
v-if="prevPageToken"
|
||||
:to="{ name: 'index', query: { pageToken: prevPageToken } }"
|
||||
href="#"
|
||||
class="border-t-2 border-transparent pt-4 pr-1 inline-flex items-center text-sm font-medium text-gray-500 hover:text-gray-700 hover:border-gray-300"
|
||||
>
|
||||
Previous
|
||||
</a>
|
||||
</div>
|
||||
<div class="hidden md:-mt-px md:flex">
|
||||
<a
|
||||
href="#"
|
||||
class="border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 border-t-2 pt-4 px-4 inline-flex items-center text-sm font-medium"
|
||||
>
|
||||
1
|
||||
</a>
|
||||
<!-- Current: "border-pink-500 text-pink-600", Default: "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300" -->
|
||||
<a
|
||||
href="#"
|
||||
class="border-brandlight text-brandlight border-t-2 pt-4 px-4 inline-flex items-center text-sm font-medium"
|
||||
aria-current="page"
|
||||
>
|
||||
2
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
class="border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 border-t-2 pt-4 px-4 inline-flex items-center text-sm font-medium"
|
||||
>
|
||||
3
|
||||
</a>
|
||||
<span
|
||||
class="border-transparent text-gray-500 border-t-2 pt-4 px-4 inline-flex items-center text-sm font-medium"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
<a
|
||||
href="#"
|
||||
class="border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 border-t-2 pt-4 px-4 inline-flex items-center text-sm font-medium"
|
||||
>
|
||||
8
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
class="border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 border-t-2 pt-4 px-4 inline-flex items-center text-sm font-medium"
|
||||
>
|
||||
9
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
class="border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 border-t-2 pt-4 px-4 inline-flex items-center text-sm font-medium"
|
||||
>
|
||||
10
|
||||
</a>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
<div class="-mt-px w-0 flex-1 flex justify-end">
|
||||
<a
|
||||
<NuxtLink
|
||||
v-if="nextPageToken"
|
||||
:to="{ name: 'index', query: { pageToken: nextPageToken } }"
|
||||
href="#"
|
||||
class="border-t-2 border-transparent pt-4 pl-1 inline-flex items-center text-sm font-medium text-gray-500 hover:text-gray-700 hover:border-gray-300"
|
||||
>
|
||||
Next
|
||||
</a>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'SimplePagination',
|
||||
|
||||
props: {
|
||||
nextPageToken: {
|
||||
type: String,
|
||||
default: () => {
|
||||
return ''
|
||||
},
|
||||
},
|
||||
prevPageToken: {
|
||||
type: String,
|
||||
default: () => {
|
||||
return ''
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
<template>
|
||||
<div
|
||||
id="videolist"
|
||||
class="max-w-2xl mx-auto py-8 px-4 sm:px-6 lg:max-w-7xl lg:px-8"
|
||||
>
|
||||
<div>
|
||||
<h2 class="sr-only">Videos</h2>
|
||||
|
||||
<div
|
||||
|
@ -17,34 +14,18 @@
|
|||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
const maxResults: number = 2
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'VideoList',
|
||||
|
||||
data(): {
|
||||
hasError: boolean
|
||||
videos: []
|
||||
} {
|
||||
return {
|
||||
hasError: false,
|
||||
videos: [],
|
||||
}
|
||||
props: {
|
||||
videos: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return []
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
|
||||
async fetch() {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`https://www.googleapis.com/youtube/v3/playlistItems?part=snippet%2CcontentDetails&maxResults=${maxResults}&playlistId=${process.env.YOUTUBE_UPLOADS_PLAYLIST_ID}&key=${process.env.YOUTUBE_API_KEY}`
|
||||
)
|
||||
const json = await response.json()
|
||||
this.videos = json.items
|
||||
} catch (error: any) {
|
||||
this.hasError = true
|
||||
throw new Error(error)
|
||||
}
|
||||
},
|
||||
|
||||
fetchOnServer: true,
|
||||
})
|
||||
</script>
|
||||
|
|
|
@ -112,6 +112,10 @@ export default {
|
|||
],
|
||||
},
|
||||
|
||||
router: {
|
||||
routes: [{ path: '/:pageToken', props: true }],
|
||||
},
|
||||
|
||||
// Global CSS: https://go.nuxtjs.dev/config-css
|
||||
css: [],
|
||||
|
||||
|
|
|
@ -6,8 +6,17 @@
|
|||
<main>
|
||||
<IndexHero />
|
||||
<div class="bg-gray-200 pb-12">
|
||||
<VideosList />
|
||||
<SimplePagination />
|
||||
<div class="max-w-2xl mx-auto py-8 px-4 sm:px-6 lg:max-w-7xl lg:px-8">
|
||||
<p v-if="$fetchState.pending">Fetching videos...</p>
|
||||
<p v-else-if="$fetchState.error">An error occurred :(</p>
|
||||
<div v-else id="videolist">
|
||||
<VideosList :videos="videos" />
|
||||
<SimplePagination
|
||||
:prev-page-token="prevPageToken"
|
||||
:next-page-token="nextPageToken"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
@ -15,8 +24,48 @@
|
|||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
const maxResults: number = 12
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'IndexPage',
|
||||
|
||||
data(): {
|
||||
videos: []
|
||||
prevPageToken: string
|
||||
nextPageToken: string
|
||||
} {
|
||||
return {
|
||||
videos: [],
|
||||
prevPageToken: '',
|
||||
nextPageToken: '',
|
||||
}
|
||||
},
|
||||
|
||||
async fetch() {
|
||||
try {
|
||||
let requestUrl =
|
||||
'https://www.googleapis.com/youtube/v3/playlistItems?part=snippet%2CcontentDetails'
|
||||
requestUrl += `&maxResults=${maxResults}`
|
||||
requestUrl += `&playlistId=${process.env.NUXT_ENV_YOUTUBE_UPLOADS_PLAYLIST_ID}`
|
||||
requestUrl += `&key=${process.env.NUXT_ENV_YOUTUBE_API_KEY}`
|
||||
if (this.$route.query.pageToken)
|
||||
requestUrl += `&pageToken=${this.$route.query.pageToken}`
|
||||
|
||||
const response = await fetch(requestUrl)
|
||||
const json = await response.json()
|
||||
|
||||
this.prevPageToken = json.prevPageToken
|
||||
this.nextPageToken = json.nextPageToken
|
||||
this.videos = json.items
|
||||
} catch (error: any) {
|
||||
throw new Error(error)
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
'$route.query': '$fetch',
|
||||
},
|
||||
|
||||
fetchOnServer: true,
|
||||
})
|
||||
</script>
|
||||
|
|
Loading…
Add table
Reference in a new issue