2023-09-26 10:12:55 +02:00
|
|
|
// Dependencies
|
|
|
|
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
|
|
|
import { pages as posts } from 'site/prebuild/blog.mjs'
|
|
|
|
import { meta } from 'site/prebuild/blog-meta.mjs'
|
|
|
|
import { cloudflareImageUrl } from 'shared/utils.mjs'
|
|
|
|
import { nsMerge } from 'shared/utils.mjs'
|
|
|
|
// Hooks
|
|
|
|
import { useTranslation } from 'next-i18next'
|
|
|
|
// Components
|
|
|
|
import Link from 'next/link'
|
|
|
|
import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs'
|
|
|
|
|
|
|
|
// Translation namespaces used on this page
|
2023-09-26 11:06:26 +02:00
|
|
|
const namespaces = nsMerge('designs', 'sections', pageNs)
|
2023-09-26 10:12:55 +02:00
|
|
|
|
|
|
|
// Helper object to order posts
|
|
|
|
const order = {}
|
2023-11-03 19:41:21 +01:00
|
|
|
let i = 0 // Avoid posts with same date not showing up
|
|
|
|
for (const [slug, props] of Object.entries(meta)) {
|
|
|
|
i++
|
|
|
|
order[props.d + i] = slug
|
|
|
|
}
|
2023-09-26 10:12:55 +02:00
|
|
|
|
2023-09-26 10:38:51 +02:00
|
|
|
export const recentBlogPosts = Object.keys(order)
|
|
|
|
.sort()
|
|
|
|
.reverse()
|
|
|
|
.slice(0, 2)
|
|
|
|
.map((d) => order[d])
|
|
|
|
|
2023-09-26 10:12:55 +02:00
|
|
|
const textShadow = {
|
|
|
|
style: {
|
|
|
|
textShadow:
|
|
|
|
'1px 1px 1px #000000, -1px -1px 1px #000000, 1px -1px 1px #000000, -1px 1px 1px #000000, 2px 2px 1px #000000',
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2023-10-22 15:06:27 +02:00
|
|
|
/* eslint-disable @next/next/no-img-element */
|
2023-09-26 11:13:36 +02:00
|
|
|
export const BlogPreview = ({ post }) => (
|
2023-09-26 10:12:55 +02:00
|
|
|
<Link href={`/${post.s}`} className="aspect-video relative">
|
|
|
|
<img
|
2023-10-22 15:06:27 +02:00
|
|
|
alt={post.caption}
|
2023-09-26 10:12:55 +02:00
|
|
|
src={cloudflareImageUrl({ id: post.s.replace('/', '-'), variant: 'w1000' })}
|
|
|
|
loading="lazy"
|
2023-09-26 10:38:51 +02:00
|
|
|
className="rounded md:rounded-lg top-0 left-0"
|
2023-09-26 10:12:55 +02:00
|
|
|
/>
|
|
|
|
<div
|
|
|
|
className={`absolute bottom-4 md:bottom-8 right-0 ml-8 md:ml-12
|
|
|
|
rounded-l md:rounded-l-lg bg-neutral bg-opacity-70 p-2 px-4 font-medium leading-7
|
|
|
|
text-neutral-content text-right text-xl md:text-2xl
|
|
|
|
|
|
|
|
`}
|
|
|
|
{...textShadow}
|
|
|
|
>
|
|
|
|
{post.t}
|
|
|
|
</div>
|
|
|
|
</Link>
|
|
|
|
)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Each page MUST be wrapped in the PageWrapper component.
|
|
|
|
* You also MUST spread props.page into this wrapper component
|
|
|
|
* when path and locale come from static props (as here)
|
|
|
|
* or set them manually.
|
|
|
|
*/
|
|
|
|
const BlogIndexPage = ({ page }) => {
|
|
|
|
const { t } = useTranslation()
|
|
|
|
|
|
|
|
return (
|
|
|
|
<PageWrapper {...page} t={t('sections:blog')}>
|
|
|
|
<div className="grid grid-cols-1 gap-2 lg:grid-cols-2 lg:gap-4 max-w-7xl">
|
|
|
|
{Object.keys(order)
|
|
|
|
.sort()
|
|
|
|
.reverse()
|
|
|
|
.map((date) => (
|
2023-09-26 10:38:51 +02:00
|
|
|
<BlogPreview
|
2023-09-26 10:12:55 +02:00
|
|
|
post={{
|
|
|
|
s: order[date],
|
|
|
|
...posts[page.locale][order[date]],
|
|
|
|
}}
|
|
|
|
key={order[date]}
|
|
|
|
/>
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
</PageWrapper>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
export default BlogIndexPage
|
|
|
|
|
|
|
|
/*
|
|
|
|
* getStaticProps() is used to fetch data at build-time.
|
|
|
|
*
|
|
|
|
* On this page, it fetches data for the blogs to be linked to on this page
|
|
|
|
*
|
|
|
|
* This, in combination with getStaticPaths() below means this
|
|
|
|
* page will be used to link to all blogs.
|
|
|
|
*
|
|
|
|
* To learn more, see: https://nextjs.org/docs/basic-features/data-fetching
|
|
|
|
*/
|
|
|
|
export async function getStaticProps({ locale }) {
|
|
|
|
return {
|
|
|
|
props: {
|
|
|
|
...(await serverSideTranslations(locale, namespaces)),
|
|
|
|
page: {
|
|
|
|
locale,
|
|
|
|
path: ['blog'],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|