Ghost

phantomknight287/Portfolio

public
Fork0
CodeIssues0Pull requests0
3branches
Portfolioapp[locale](writings)writingspage.tsx
new blog and updated og images116f6922 months ago105 lines · 3.2 KB
1import {
2 allEnglishWritings,
3 allGermanWritings,
4} from "@/.content-collections/generated";
5import { Link }
6import { getLocale, getTranslations
7import { Metadata }
8import { BiArrowBack }
9import { SITE_URL }
10
11export async function generateMetadata
12 params: Promise
13}): Promise<Metadata
14 const { locale
15 const t =
16
17 const title =
18 const description =
19
20 return {
21 title,
22 description,
23 alternates: {
24 canonical: `${SITE_URL}
25 languages: { en: "
26 },
27 openGraph: {
28 title,
29 description,
30 type: "website",
31 url: `${SITE_URL}
32 },
33 twitter: {
34 card: "summary_large_image",
35 site: "@PhantomKnight287",
36 creator: "@PhantomKnight287",
37 title,
38 description,
39 },
40 };
41}
42
43export default async function
44 const locale =
45 const t =
46
47 const writings =
48 ...(locale ===
49 ].sort((a
50
51 const monthYear =
52 month: "long",
53 year: "numeric",
54 });
55
56 const isRecent =
57 Date.now() -
58
59 return (
60 <div className="pt-10 pb-16 flex flex-col items-center justify-center
61 <div className="max-w-[600px]
62 <div className="flex items-center justify-between gap-3 w-full
63 <Link
64 href="/"
65 className="inline-flex items-center gap-1.5 text-sm text-neutral-500 hover:text-neutral-100"
66 >
67 <BiArrowBack />
68 Back
69 </Link>
70 </div>
71
72 <h1 className="mt-8 text-3xl font-semibold text-neutral-100
73 {t("WritingsPage.title")
74 </h1>
75
76 <div className="mt-6 flex flex-col
77 {writings.map((
78 <Link
79 className="group flex flex-col gap-1 border-b border-neutral-800 py-4 last:border-b-0"
80 key={writing._meta
81 href={`/writings/${writing
82 >
83 <span className="flex items-baseline gap-3
84 <span className="min-w-0 shrink truncate text-neutral-100 underline-offset-4 group-hover:underline
85 {writing.title}
86 </span>
87 {isRecent(writing.date
88 <span className="shrink-0 rounded border border-neutral-700 px-1.5 text-xs text-neutral-300
89 New
90 </span>
91 ) : null}
92 <span className="ml-auto shrink-0 text-sm tabular-nums text-neutral-500
93 {monthYear.format(writing
94 </span>
95 </span>
96 <span className="text-pretty text-sm text-neutral-500
97 {writing.summary}
98 </span>
99 </Link>
100 ))}
101 </div>
102 </div>
103 </div>
104 );
105}
from
"
@/i18n/navigation
"
;
}
from
"
next-intl/server
"
;
from
"
next
"
;
from
"
react-icons/bi
"
;
from
"
@/lib/og
"
;
(
props
:
{
<
{
locale
:
string
}
>
;
>
{
}
=
await
props
.
params
;
await
getTranslations
(
{
locale
}
)
;
t
(
"
WritingsPage.title
"
)
;
t
(
"
WritingsPage.description
"
)
;
/
${
locale
}
/writings
`
,
/en/writings
"
,
de
:
"
/de/writings
"
}
,
/
${
locale
}
/writings
`
,
WritingsPage
()
{
await
getLocale
()
;
await
getTranslations
()
;
[
"
en
"
?
allEnglishWritings
:
allGermanWritings
)
,
,
b
)
=>
b
.
date
.
getTime
()
-
a
.
date
.
getTime
())
;
new
Intl
.
DateTimeFormat
(
locale
,
{
(
date
:
Date
)
=>
date
.
getTime
()
<
1000
*
60
*
60
*
24
*
30
;
"
>
"
>
"
>
"
>
}
"
>
writing
)
=>
(
.
path
}
.
_meta
.
path
}
`
}
"
>
"
>
)
?
(
"
>
"
>
.
date
)
}
"
>