1
1
<script setup>
2
+ import { watch } from ' vue'
3
+ import { useRoute , useRouter } from ' vue-router'
4
+
2
5
useHead ({
3
6
title: ' Blog - Python Cheatsheet' ,
4
7
meta: [
@@ -11,6 +14,16 @@ useHead({
11
14
})
12
15
13
16
const router = useRouter ()
17
+ const route = useRoute ()
18
+ const currentPage = ref (parseInt (route .query .page ) || 1 )
19
+ const postsPerPage = 7
20
+
21
+ watch (
22
+ () => route .query .page ,
23
+ (newPage ) => {
24
+ currentPage .value = parseInt (newPage) || 1
25
+ },
26
+ )
14
27
15
28
const articles = computed (() => {
16
29
const routes = router .options .routes
@@ -25,27 +38,62 @@ const articles = computed(() => {
25
38
})
26
39
})
27
40
28
- const latestArticle = computed (() => articles .value [0 ])
29
- const otherArticles = computed (() => articles .value .slice (1 ))
41
+ const totalPages = computed (() => {
42
+ return Math .ceil (articles .value .length / postsPerPage)
43
+ })
44
+
45
+ const postsToShow = computed (() => {
46
+ const start = (currentPage .value - 1 ) * postsPerPage
47
+ const end = start + postsPerPage
48
+ return articles .value .slice (start, end)
49
+ })
50
+
51
+ const featuredArticle = computed (() => {
52
+ return currentPage .value === 1 ? postsToShow .value [0 ] : null
53
+ })
54
+
55
+ const gridArticles = computed (() => {
56
+ if (currentPage .value === 1 ) {
57
+ return postsToShow .value .slice (1 )
58
+ }
59
+ return postsToShow .value
60
+ })
30
61
31
62
const getTags = (article ) => {
32
63
const tags = article .children [0 ]? .meta ? .tags
33
64
if (! tags) return []
34
65
return tags .split (' ,' ).map ((tag ) => tag .trim ())
35
66
}
67
+
68
+ function updatePage (newPage ) {
69
+ currentPage .value = newPage
70
+ router .push ({ query: { page: newPage } })
71
+ }
72
+
73
+ function nextPage () {
74
+ if (currentPage .value < totalPages .value ) {
75
+ updatePage (currentPage .value + 1 )
76
+ }
77
+ }
78
+
79
+ function prevPage () {
80
+ if (currentPage .value > 1 ) {
81
+ updatePage (currentPage .value - 1 )
82
+ }
83
+ }
36
84
< / script>
37
85
38
86
< template>
39
- < div v- if = " latestArticle " class = " mb-12" >
87
+ < div v- if = " featuredArticle " class = " mb-12" >
40
88
< router- link
41
- : to= " latestArticle .path"
89
+ : to= " featuredArticle .path"
42
90
class = " group block overflow-hidden rounded-lg border border-slate-200 bg-white shadow-md transition-all duration-300 hover:shadow-xl dark:border-slate-700 dark:bg-slate-800"
43
91
>
44
92
< div class = " md:flex" >
45
93
< div class = " relative md:w-1/2" >
46
94
< img
47
- v- if = " latestArticle .children[0]?.meta?.socialImage"
48
- : src= " latestArticle .children[0]?.meta?.socialImage"
95
+ v- if = " featuredArticle .children[0]?.meta?.socialImage"
96
+ : src= " featuredArticle .children[0]?.meta?.socialImage"
49
97
alt= " "
50
98
class = " h-full w-full object-cover transition-transform duration-300 group-hover:scale-105"
51
99
/ >
@@ -72,22 +120,25 @@ const getTags = (article) => {
72
120
< div class = " flex flex-col p-6 md:w-1/2" >
73
121
< div class = " flex-1" >
74
122
< div class = " mb-2 flex flex-wrap gap-2" >
75
- < Tag v- for = " tag in getTags(latestArticle).slice(0, 2)" : key= " tag" >
123
+ < Tag
124
+ v- for = " tag in getTags(featuredArticle).slice(0, 2)"
125
+ : key= " tag"
126
+ >
76
127
{{ tag }}
77
128
< / Tag>
78
129
< / div>
79
130
< h2
80
131
class = " text-2xl font-semibold text-slate-800 dark:text-slate-100"
81
132
>
82
- {{ latestArticle .children [0 ]? .meta ? .title }}
133
+ {{ featuredArticle .children [0 ]? .meta ? .title }}
83
134
< / h2>
84
135
< p class = " mt-2 text-slate-600 dark:text-slate-400" >
85
- {{ latestArticle .children [0 ]? .meta ? .description }}
136
+ {{ featuredArticle .children [0 ]? .meta ? .description }}
86
137
< / p>
87
138
< / div>
88
139
< div class = " mt-4 flex items-center justify-between" >
89
140
< time class = " text-sm text-slate-500 dark:text-slate-400" >
90
- {{ latestArticle .children [0 ]? .meta ? .date }}
141
+ {{ featuredArticle .children [0 ]? .meta ? .date }}
91
142
< / time>
92
143
< div class = " flex items-center text-sm font-medium text-sky-500" >
93
144
Read article
@@ -113,7 +164,7 @@ const getTags = (article) => {
113
164
114
165
< div class = " grid gap-8 sm:grid-cols-2 lg:grid-cols-3" >
115
166
< router- link
116
- v- for = " article in otherArticles "
167
+ v- for = " article in gridArticles "
117
168
: key= " article.path"
118
169
: to= " article.path"
119
170
class = " group flex flex-col overflow-hidden rounded-lg border border-slate-200 bg-white shadow-md transition-all duration-300 hover:shadow-xl dark:border-slate-700 dark:bg-slate-800"
@@ -183,6 +234,13 @@ const getTags = (article) => {
183
234
< / div>
184
235
< / router- link>
185
236
< / div>
237
+
238
+ < BlogPagination
239
+ : current- page= " currentPage"
240
+ : total- pages= " totalPages"
241
+ @prev- page= " prevPage"
242
+ @next- page= " nextPage"
243
+ / >
186
244
< / template>
187
245
188
246
< route lang= " yaml" >
0 commit comments