Merge pull request #59 from timlrx/feat/pagination

Feat/pagination
This commit is contained in:
Timothy 2021-05-29 17:04:05 +08:00 committed by GitHub
commit 654589b5cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 185 additions and 108 deletions

36
components/Pagination.js Normal file
View File

@ -0,0 +1,36 @@
import Link from '@/components/Link'
export default function Pagination({ totalPages, currentPage }) {
const prevPage = parseInt(currentPage) - 1 > 0
const nextPage = parseInt(currentPage) + 1 <= parseInt(totalPages)
return (
<div className="pt-6 pb-8 space-y-2 md:space-y-5">
<nav className="flex justify-between">
{!prevPage && (
<button rel="previous" className="cursor-auto disabled:opacity-50" disabled={!prevPage}>
Previous
</button>
)}
{prevPage && (
<Link href={currentPage - 1 === 1 ? `/blog/` : `/blog/page/${currentPage - 1}`}>
<button rel="previous">Previous</button>
</Link>
)}
<span>
{currentPage} of {totalPages}
</span>
{!nextPage && (
<button rel="next" className="cursor-auto disabled:opacity-50" disabled={!nextPage}>
Next
</button>
)}
{nextPage && (
<Link href={`/blog/page/${currentPage + 1}`}>
<button rel="next">Next</button>
</Link>
)}
</nav>
</div>
)
}

View File

@ -2,16 +2,21 @@ import Link from '@/components/Link'
import Tag from '@/components/Tag'
import siteMetadata from '@/data/siteMetadata'
import { useState } from 'react'
import Pagination from '@/components/Pagination'
const postDateTemplate = { year: 'numeric', month: 'long', day: 'numeric' }
export default function ListLayout({ posts, title }) {
export default function ListLayout({ posts, title, initialDisplayPosts = [], pagination }) {
const [searchValue, setSearchValue] = useState('')
const filteredBlogPosts = posts.filter((frontMatter) => {
const searchContent = frontMatter.title + frontMatter.summary + frontMatter.tags.join(' ')
return searchContent.toLowerCase().includes(searchValue.toLowerCase())
})
// If initialDisplayPosts exist, display it if no searchValue is specified
const displayPosts =
initialDisplayPosts.length > 0 && !searchValue ? initialDisplayPosts : filteredBlogPosts
return (
<>
<div className="divide-y">
@ -45,7 +50,7 @@ export default function ListLayout({ posts, title }) {
</div>
<ul>
{!filteredBlogPosts.length && 'No posts found.'}
{filteredBlogPosts.map((frontMatter) => {
{displayPosts.map((frontMatter) => {
const { slug, date, title, summary, tags } = frontMatter
return (
<li key={slug} className="py-4">
@ -81,6 +86,11 @@ export default function ListLayout({ posts, title }) {
})}
</ul>
</div>
{pagination &&
pagination.totalPages > 1 &&
!searchValue(
<Pagination currentPage={pagination.currentPage} totalPages={pagination.totalPages} />
)}
</>
)
}

View File

@ -80,7 +80,6 @@ export async function getFileBySlug(type, slug) {
return {
mdxSource,
frontMatter: {
wordCount: content.split(/\s+/gu).length,
readingTime: readingTime(content),
slug: slug || null,
fileName: fs.existsSync(mdxPath) ? `${slug}.mdx` : `${slug}.md`,

139
package-lock.json generated
View File

@ -1208,9 +1208,9 @@
}
},
"@hapi/accept": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/@hapi/accept/-/accept-5.0.1.tgz",
"integrity": "sha512-fMr4d7zLzsAXo28PRRQPXR1o2Wmu+6z+VY1UzDp0iFo13Twj8WePakwXBiqn3E1aAlTpSNzCXdnnQXFhst8h8Q==",
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/@hapi/accept/-/accept-5.0.2.tgz",
"integrity": "sha512-CmzBx/bXUR8451fnZRuZAJRlzgm0Jgu5dltTX/bszmR2lheb9BpyN47Q1RbaGTsvFzn0PXAEs+lXDKfshccYZw==",
"requires": {
"@hapi/boom": "9.x.x",
"@hapi/hoek": "9.x.x"
@ -1239,16 +1239,6 @@
"unist-util-visit": "^2.0.3"
}
},
"@mdx-js/loader": {
"version": "1.6.22",
"resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-1.6.22.tgz",
"integrity": "sha512-9CjGwy595NaxAYp0hF9B/A0lH6C8Rms97e2JS9d3jVUtILn6pT5i5IV965ra3lIWc7Rs1GG1tBdVF7dCowYe6Q==",
"requires": {
"@mdx-js/mdx": "1.6.22",
"@mdx-js/react": "1.6.22",
"loader-utils": "2.0.0"
}
},
"@mdx-js/mdx": {
"version": "1.6.22",
"resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz",
@ -1329,33 +1319,28 @@
"integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA=="
},
"@next/bundle-analyzer": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-10.2.0.tgz",
"integrity": "sha512-vJI5zer6fp9vtDal/IxwyT3rigu/+nACdKIJHyzls+fz1joyHAKU15Xxz0rsak3cwvE6MozFjoJTrawDV8eQDQ==",
"version": "10.2.3",
"resolved": "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-10.2.3.tgz",
"integrity": "sha512-vEfQhGWgJugZOlSUlj3DZWs/KsK0SO2SPKoHSZ7KkzpruKzc/e45G0oUh0rffzdhasMQZM1TuSBkxO+1UcnDNw==",
"dev": true,
"requires": {
"webpack-bundle-analyzer": "4.3.0"
}
},
"@next/env": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/@next/env/-/env-10.2.0.tgz",
"integrity": "sha512-tsWBsn1Rb6hXRaHc/pWMCpZ4Ipkf3OCbZ54ef5ukgIyEvzzGdGFXQshPP2AF7yb+8yMpunWs7vOMZW3e8oPF6A=="
},
"@next/mdx": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/@next/mdx/-/mdx-10.2.0.tgz",
"integrity": "sha512-2AwN5Q4Av6McSpVKps2dDGdKEEUdme0cjdmo0iNuBFdBPzMBMeMyIMrT9T/QPCDUtqeB747f6Zkf/Xt2uVwzBg=="
"version": "10.2.3",
"resolved": "https://registry.npmjs.org/@next/env/-/env-10.2.3.tgz",
"integrity": "sha512-uBOjRBjsWC4C8X3DfmWWP6ekwLnf2JCCwQX9KVnJtJkqfDsv1yQPakdOEwvJzXQc3JC/v5KKffYPVmV2wHXCgQ=="
},
"@next/polyfill-module": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/@next/polyfill-module/-/polyfill-module-10.2.0.tgz",
"integrity": "sha512-Nl3GexIUXsmuggkUqrRFyE/2k7UI44JaVzSywtXEyHzxpZm2a5bdMaWuC89pgLiFDDOqmbqyLAbtwm5lNxa7Eg=="
"version": "10.2.3",
"resolved": "https://registry.npmjs.org/@next/polyfill-module/-/polyfill-module-10.2.3.tgz",
"integrity": "sha512-OkeY4cLhzfYbXxM4fd+6V4s5pTPuyfKSlavItfNRA6PpS7t1/R6YjO7S7rB8tu1pbTGuDHGIdE1ioDv15bAbDQ=="
},
"@next/react-dev-overlay": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/@next/react-dev-overlay/-/react-dev-overlay-10.2.0.tgz",
"integrity": "sha512-PRIAoWog41hLN4iJ8dChKp4ysOX0Q8yiNQ/cwzyqEd3EjugkDV5OiKl3mumGKaApJaIra1MX6j1wgQRuLhuWMA==",
"version": "10.2.3",
"resolved": "https://registry.npmjs.org/@next/react-dev-overlay/-/react-dev-overlay-10.2.3.tgz",
"integrity": "sha512-E6g2jws4YW94l0lMMopBVKIZK2mEHfSBvM0d9dmzKG9L/A/kEq6LZCB4SiwGJbNsAdlk2y3USDa0oNbpA+m5Kw==",
"requires": {
"@babel/code-frame": "7.12.11",
"anser": "1.4.9",
@ -1432,9 +1417,9 @@
}
},
"@next/react-refresh-utils": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/@next/react-refresh-utils/-/react-refresh-utils-10.2.0.tgz",
"integrity": "sha512-3I31K9B4hEQRl7yQ44Umyz+szHtuMJrNdwsgJGhoEnUCXSBRHp5wv5Zv8eDa2NewSbe53b2C0oOpivrzmdBakw=="
"version": "10.2.3",
"resolved": "https://registry.npmjs.org/@next/react-refresh-utils/-/react-refresh-utils-10.2.3.tgz",
"integrity": "sha512-qtBF56vPC6d6a8p7LYd0iRjW89fhY80kAIzmj+VonvIGjK/nymBjcFUhbKiMFqlhsarCksnhwX+Zmn95Dw9qvA=="
},
"@nodelib/fs.scandir": {
"version": "2.1.4",
@ -1473,9 +1458,9 @@
"integrity": "sha512-sDOAZcYwynHFTbLo6n8kIbLiVF3a3BLkrmehJUyEbT9F+Smbi47kLGS2gG2g0fjBLR/Lr1InPD7kXL7FaTqEkw=="
},
"@polka/url": {
"version": "1.0.0-next.12",
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.12.tgz",
"integrity": "sha512-6RglhutqrGFMO1MNUXp95RBuYIuc8wTnMAV5MUhLmjTOy78ncwOw7RgeQ/HeymkKXRhZd0s2DNrM1rL7unk3MQ==",
"version": "1.0.0-next.15",
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.15.tgz",
"integrity": "sha512-15spi3V28QdevleWBNXE4pIls3nFZmBbUGrW9IVPwiQczuSb9n76TCB4bsk8TSel+I1OkHEdPhu5QKMfY6rQHA==",
"dev": true
},
"@svgr/babel-plugin-add-jsx-attribute": {
@ -1648,9 +1633,9 @@
}
},
"@types/node": {
"version": "15.0.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.2.tgz",
"integrity": "sha512-p68+a+KoxpoB47015IeYZYRrdqMUcpbK8re/zpFB8Ld46LHC1lPEbp3EXgkEhAYEcPvjJF6ZO+869SQ0aH1dcA=="
"version": "15.6.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.6.1.tgz",
"integrity": "sha512-7EIraBEyRHEe7CH+Fm1XvgqU6uwZN8Q7jppJGcqjROMT29qhAuuOxYB1uEY5UMYQKEmA5D+5tBnhdaPXSsLONA=="
},
"@types/parse-json": {
"version": "4.0.0",
@ -1806,11 +1791,6 @@
"@babel/runtime-corejs3": "^7.10.2"
}
},
"array-filter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz",
"integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM="
},
"array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
@ -1913,12 +1893,9 @@
}
},
"available-typed-arrays": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz",
"integrity": "sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==",
"requires": {
"array-filter": "^1.0.0"
}
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.4.tgz",
"integrity": "sha512-SA5mXJWrId1TaQjfxUYghbqQ/hYioKmLJvPJyDuYRtXXenFNMjj4hSSt1Cf1xsuXSXrtxrVC5Ot4eU6cOtBDdA=="
},
"axe-core": {
"version": "4.2.0",
@ -2995,7 +2972,8 @@
"emojis-list": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
"integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q=="
"integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
"dev": true
},
"encodeurl": {
"version": "1.0.2",
@ -4127,9 +4105,9 @@
"dev": true
},
"iconv-lite": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz",
"integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==",
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
}
@ -4719,6 +4697,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
"dev": true,
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
@ -5198,9 +5177,9 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"nanoid": {
"version": "3.1.22",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.22.tgz",
"integrity": "sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ=="
"version": "3.1.23",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz",
"integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw=="
},
"native-url": {
"version": "0.3.4",
@ -5223,23 +5202,23 @@
"dev": true
},
"next": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/next/-/next-10.2.0.tgz",
"integrity": "sha512-PKDKCSF7s82xudu3kQhOEaokxggpbLEWouEUtzP6OqV0YqKYHF+Ff+BFLycEem8ixtTM2M6ElN0VRJcskJfxPQ==",
"version": "10.2.3",
"resolved": "https://registry.npmjs.org/next/-/next-10.2.3.tgz",
"integrity": "sha512-dkM1mIfnORtGyzw/Yme8RdqNxlCMZyi4Lqj56F01/yHbe1ZtOaJ0cyqqRB4RGiPhjGGh0319f8ddjDyO1605Ow==",
"requires": {
"@babel/runtime": "7.12.5",
"@hapi/accept": "5.0.1",
"@next/env": "10.2.0",
"@next/polyfill-module": "10.2.0",
"@next/react-dev-overlay": "10.2.0",
"@next/react-refresh-utils": "10.2.0",
"@hapi/accept": "5.0.2",
"@next/env": "10.2.3",
"@next/polyfill-module": "10.2.3",
"@next/react-dev-overlay": "10.2.3",
"@next/react-refresh-utils": "10.2.3",
"@opentelemetry/api": "0.14.0",
"assert": "2.0.0",
"ast-types": "0.13.2",
"browserify-zlib": "0.2.0",
"browserslist": "4.16.1",
"browserslist": "4.16.6",
"buffer": "5.6.0",
"caniuse-lite": "^1.0.30001179",
"caniuse-lite": "^1.0.30001228",
"chalk": "2.4.2",
"chokidar": "3.5.1",
"constants-browserify": "1.0.0",
@ -5279,18 +5258,6 @@
"watchpack": "2.1.1"
},
"dependencies": {
"browserslist": {
"version": "4.16.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.1.tgz",
"integrity": "sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA==",
"requires": {
"caniuse-lite": "^1.0.30001173",
"colorette": "^1.2.1",
"electron-to-chromium": "^1.3.634",
"escalade": "^3.1.1",
"node-releases": "^1.1.69"
}
},
"postcss": {
"version": "8.2.13",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.13.tgz",
@ -6926,12 +6893,12 @@
}
},
"sirv": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.11.tgz",
"integrity": "sha512-SR36i3/LSWja7AJNRBz4fF/Xjpn7lQFI30tZ434dIy+bitLYSP+ZEenHg36i23V2SGEz+kqjksg0uOGZ5LPiqg==",
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.12.tgz",
"integrity": "sha512-+jQoCxndz7L2tqQL4ZyzfDhky0W/4ZJip3XoOuxyQWnAwMxindLl3Xv1qT4x1YX/re0leShvTm8Uk0kQspGhBg==",
"dev": true,
"requires": {
"@polka/url": "^1.0.0-next.9",
"@polka/url": "^1.0.0-next.15",
"mime": "^2.3.1",
"totalist": "^1.0.0"
}
@ -7988,9 +7955,9 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"ws": {
"version": "7.4.5",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz",
"integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==",
"version": "7.4.6",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
"dev": true
},
"xtend": {

View File

@ -12,15 +12,12 @@
},
"dependencies": {
"@mapbox/rehype-prism": "^0.6.0",
"@mdx-js/loader": "^1.6.22",
"@mdx-js/react": "^1.6.22",
"@next/mdx": "10.2.0",
"@tailwindcss/forms": "^0.3.2",
"@tailwindcss/typography": "^0.4.0",
"autoprefixer": "^10.2.5",
"gray-matter": "^4.0.2",
"image-size": "1.0.0",
"next": "10.2.0",
"next": "10.2.3",
"next-mdx-remote": "^3.0.1",
"next-seo": "4.24.0",
"next-themes": "^0.0.14",
@ -38,7 +35,7 @@
"tailwindcss": "^2.1.1"
},
"devDependencies": {
"@next/bundle-analyzer": "10.2.0",
"@next/bundle-analyzer": "10.2.3",
"@svgr/webpack": "^5.5.0",
"cross-env": "^7.0.3",
"eslint": "^7.17.0",

View File

@ -1,26 +1,22 @@
import '@/css/tailwind.css'
import { MDXProvider } from '@mdx-js/react'
import { ThemeProvider } from 'next-themes'
import { DefaultSeo } from 'next-seo'
import Head from 'next/head'
import { SEO } from '@/components/SEO'
import LayoutWrapper from '@/components/LayoutWrapper'
import MDXComponents from '@/components/MDXComponents'
export default function App({ Component, pageProps }) {
return (
<ThemeProvider attribute="class">
<MDXProvider components={MDXComponents}>
<Head>
<meta content="width=device-width, initial-scale=1" name="viewport" />
</Head>
<DefaultSeo {...SEO} />
<LayoutWrapper>
<Component {...pageProps} />
</LayoutWrapper>
</MDXProvider>
<Head>
<meta content="width=device-width, initial-scale=1" name="viewport" />
</Head>
<DefaultSeo {...SEO} />
<LayoutWrapper>
<Component {...pageProps} />
</LayoutWrapper>
</ThemeProvider>
)
}

View File

@ -3,13 +3,20 @@ import siteMetadata from '@/data/siteMetadata'
import ListLayout from '@/layouts/ListLayout'
import { PageSeo } from '@/components/SEO'
export const POSTS_PER_PAGE = 10
export async function getStaticProps() {
const posts = await getAllFilesFrontMatter('blog')
const initialDisplayPosts = posts.slice(0, POSTS_PER_PAGE)
const pagination = {
currentPage: 1,
totalPages: Math.ceil(posts.length / POSTS_PER_PAGE),
}
return { props: { posts } }
return { props: { initialDisplayPosts, posts, pagination } }
}
export default function Blog({ posts }) {
export default function Blog({ posts, initialDisplayPosts, pagination }) {
return (
<>
<PageSeo
@ -17,7 +24,12 @@ export default function Blog({ posts }) {
description={siteMetadata.description}
url={`${siteMetadata.siteUrl}/blog`}
/>
<ListLayout posts={posts} title="All Posts" />
<ListLayout
posts={posts}
initialDisplayPosts={initialDisplayPosts}
pagination={pagination}
title="All Posts"
/>
</>
)
}

60
pages/blog/page/[page].js Normal file
View File

@ -0,0 +1,60 @@
import { PageSeo } from '@/components/SEO'
import siteMetadata from '@/data/siteMetadata'
import { getAllFilesFrontMatter } from '@/lib/mdx'
import ListLayout from '@/layouts/ListLayout'
import { POSTS_PER_PAGE } from '../../blog'
export async function getStaticPaths() {
const totalPosts = await getAllFilesFrontMatter('blog')
const totalPages = Math.ceil(totalPosts.length / POSTS_PER_PAGE)
const paths = Array.from({ length: totalPages }, (_, i) => ({
params: { page: (i + 1).toString() },
}))
return {
paths,
fallback: false,
}
}
export async function getStaticProps(context) {
const {
params: { page },
} = context
const posts = await getAllFilesFrontMatter('blog')
const pageNumber = parseInt(page)
const initialDisplayPosts = posts.slice(
POSTS_PER_PAGE * (pageNumber - 1),
POSTS_PER_PAGE * pageNumber
)
const pagination = {
currentPage: pageNumber,
totalPages: Math.ceil(posts.length / POSTS_PER_PAGE),
}
return {
props: {
posts,
initialDisplayPosts,
pagination,
},
}
}
export default function PostPage({ posts, initialDisplayPosts, pagination }) {
return (
<>
<PageSeo
title={siteMetadata.title}
description={siteMetadata.description}
url={`${siteMetadata.siteUrl}/blog/${pagination.currentPage}`}
/>
<ListLayout
posts={posts}
initialDisplayPosts={initialDisplayPosts}
pagination={pagination}
title="All Posts"
/>
</>
)
}