2023-09-26 14:27:38 +08:00
|
|
|
---
|
|
|
|
interface Props {
|
|
|
|
keyword: string;
|
|
|
|
tags: string[];
|
|
|
|
categories: string[];
|
|
|
|
}
|
|
|
|
const { keyword, tags, categories} = Astro.props;
|
|
|
|
|
|
|
|
import Button from "./control/Button.astro";
|
2023-10-11 22:29:23 +08:00
|
|
|
import {getSortedPosts} from "../utils/content-utils";
|
|
|
|
import {getPostUrlBySlug} from "../utils/url-utils";
|
2024-01-21 20:19:34 +08:00
|
|
|
import {i18n} from "../i18n/translation";
|
|
|
|
import I18nKey from "../i18n/i18nKey";
|
2024-01-22 02:06:24 +08:00
|
|
|
import {UNCATEGORIZED} from "@constants/constants";
|
2023-09-26 14:27:38 +08:00
|
|
|
|
|
|
|
let posts = await getSortedPosts()
|
|
|
|
|
|
|
|
if (Array.isArray(tags) && tags.length > 0) {
|
|
|
|
posts = posts.filter(post =>
|
|
|
|
Array.isArray(post.data.tags) && post.data.tags.some(tag => tags.includes(tag))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Array.isArray(categories) && categories.length > 0) {
|
|
|
|
posts = posts.filter(post =>
|
2024-01-21 20:19:34 +08:00
|
|
|
(post.data.category && categories.includes(post.data.category)) ||
|
|
|
|
(!post.data.category && categories.includes(UNCATEGORIZED))
|
2023-09-26 14:27:38 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
const groups = function () {
|
|
|
|
const groupedPosts = posts.reduce((grouped, post) => {
|
2023-10-18 17:31:11 +08:00
|
|
|
const year = post.data.published.getFullYear()
|
2023-09-26 14:27:38 +08:00
|
|
|
if (!grouped[year]) {
|
|
|
|
grouped[year] = []
|
|
|
|
}
|
|
|
|
grouped[year].push(post)
|
|
|
|
return grouped
|
|
|
|
}, {})
|
|
|
|
|
|
|
|
// convert the object to an array
|
|
|
|
const groupedPostsArray = Object.keys(groupedPosts).map(key => ({
|
|
|
|
year: key,
|
|
|
|
posts: groupedPosts[key]
|
|
|
|
}))
|
|
|
|
|
|
|
|
// sort years by latest first
|
|
|
|
groupedPostsArray.sort((a, b) => b.year - a.year)
|
|
|
|
return groupedPostsArray;
|
|
|
|
}();
|
|
|
|
|
|
|
|
function formatDate(date: Date) {
|
|
|
|
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
|
|
|
const day = date.getDate().toString().padStart(2, '0');
|
|
|
|
return `${month}-${day}`;
|
|
|
|
}
|
|
|
|
|
2023-10-18 21:24:51 +08:00
|
|
|
function formatTag(tag: string[]) {
|
|
|
|
return tag.map(t => `#${t}`).join(' ');
|
|
|
|
}
|
2023-09-26 14:27:38 +08:00
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
<div class="card-base px-8 py-6">
|
|
|
|
{
|
|
|
|
groups.map(group => (
|
|
|
|
<div>
|
2024-01-22 11:25:56 +08:00
|
|
|
<div class="flex flex-row w-full items-center h-[3.75rem]">
|
2024-01-22 02:06:24 +08:00
|
|
|
<div class="w-[15%] md:w-[10%] transition text-2xl font-bold text-right text-black/75 dark:text-white/75">{group.year}</div>
|
|
|
|
<div class="w-[15%] md:w-[10%]">
|
2023-09-26 14:27:38 +08:00
|
|
|
<div class="h-3 w-3 bg-none rounded-full outline outline-[var(--primary)] mx-auto -outline-offset-[2px] z-50 outline-3"></div>
|
|
|
|
</div>
|
2024-01-22 02:06:24 +08:00
|
|
|
<div class="w-[70%] md:w-[80%] transition text-left text-black/50 dark:text-white/50">{group.posts.length} {i18n(I18nKey.postsCount)}</div>
|
2023-09-26 14:27:38 +08:00
|
|
|
</div>
|
|
|
|
{group.posts.map(post => (
|
2023-10-20 11:36:55 +08:00
|
|
|
<a href={getPostUrlBySlug(post.slug)} aria-label={post.data.title} class="group">
|
2023-10-02 01:52:08 +08:00
|
|
|
<Button light height="40px" class="w-full rounded-lg hover:text-[initial]">
|
2023-09-26 14:27:38 +08:00
|
|
|
<div class="flex flex-row justify-start items-center h-full">
|
|
|
|
<!-- date -->
|
2024-01-22 02:06:24 +08:00
|
|
|
<div class="w-[15%] md:w-[10%] transition text-sm text-right text-black/50 dark:text-white/50">{formatDate(post.data.published)}</div>
|
2023-09-26 14:27:38 +08:00
|
|
|
<!-- dot and line -->
|
2024-01-22 02:06:24 +08:00
|
|
|
<div class="w-[15%] md:w-[10%] relative dash-line h-full flex items-center">
|
2023-09-26 14:27:38 +08:00
|
|
|
<div class="transition-all mx-auto w-1 h-1 rounded group-hover:h-5
|
|
|
|
bg-[oklch(0.5_0.05_var(--hue))] group-hover:bg-[var(--primary)]
|
|
|
|
outline outline-4 z-50
|
|
|
|
outline-[var(--card-bg)]
|
|
|
|
group-hover:outline-[var(--btn-plain-bg-hover)]
|
|
|
|
group-active:outline-[var(--btn-plain-bg-active)]
|
|
|
|
"
|
|
|
|
></div>
|
|
|
|
</div>
|
|
|
|
<!-- post title -->
|
2024-01-22 02:06:24 +08:00
|
|
|
<div class="w-[70%] md:max-w-[65%] md:w-[65%] text-left font-bold
|
2023-09-29 11:58:14 +08:00
|
|
|
group-hover:translate-x-1 transition-all group-hover:text-[var(--primary)]
|
|
|
|
text-black/80 dark:text-white/80 pr-8 whitespace-nowrap overflow-ellipsis overflow-hidden"
|
|
|
|
>
|
2023-09-26 14:27:38 +08:00
|
|
|
{post.data.title}
|
|
|
|
</div>
|
|
|
|
<!-- tag list -->
|
2024-01-22 02:06:24 +08:00
|
|
|
<div class="hidden md:block md:w-[15%] text-left text-sm transition
|
2023-09-26 14:27:38 +08:00
|
|
|
whitespace-nowrap overflow-ellipsis overflow-hidden
|
|
|
|
text-black/30 dark:text-white/30"
|
2023-10-18 21:24:51 +08:00
|
|
|
>{formatTag(post.data.tags)}</div>
|
2023-09-26 14:27:38 +08:00
|
|
|
</div>
|
|
|
|
</Button>
|
|
|
|
</a>
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
))
|
|
|
|
}
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<style>
|
|
|
|
@tailwind components;
|
|
|
|
@tailwind utilities;
|
|
|
|
|
|
|
|
@layer components {
|
|
|
|
.dash-line {
|
|
|
|
}
|
|
|
|
.dash-line::before {
|
|
|
|
content: "";
|
|
|
|
@apply w-[10%] h-full absolute -top-1/2 left-[calc(50%_-_1px)] -top-[50%] border-l-[2px]
|
|
|
|
border-dashed pointer-events-none border-[var(--line-color)] transition
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|