diff --git a/src/components/blog/PostItem.astro b/src/components/blog/PostItem.astro
index fe3d36c..37043c0 100644
--- a/src/components/blog/PostItem.astro
+++ b/src/components/blog/PostItem.astro
@@ -1,6 +1,7 @@
---
import Tags from "@/components/ui/Tags.astro";
import Categories from "@/components/ui/Categories.astro";
+import Destinations from "@/components/ui/Destinations.astro";
import { type CollectionEntry, render } from "astro:content";
import { toR2Url } from "@/utils/r2";
import Picture from "@/components/ui/Picture.astro";
@@ -89,5 +90,12 @@ const readingTime = remarkPluginFrontmatter?.minutesRead
)
}
+ {
+ post.data.destination && post.data.destination.length > 0 && (
+
+
+
+ )
+ }
diff --git a/src/components/ui/Destinations.astro b/src/components/ui/Destinations.astro
new file mode 100644
index 0000000..4ab9c09
--- /dev/null
+++ b/src/components/ui/Destinations.astro
@@ -0,0 +1,39 @@
+---
+export interface Props {
+ destinations: string[];
+ class?: string;
+}
+
+const { destinations, class: className = "text-sm" } = Astro.props;
+---
+
+{
+ destinations && Array.isArray(destinations) && (
+
+ )
+}
diff --git a/src/content.config.ts b/src/content.config.ts
index 364bed4..d0c2772 100644
--- a/src/content.config.ts
+++ b/src/content.config.ts
@@ -11,6 +11,7 @@ const blog = defineCollection({
image: z.string().optional(),
tags: z.array(z.string()).optional(),
categories: z.array(z.string()).optional(),
+ destination: z.array(z.string()).optional(),
}),
});
diff --git a/src/pages/[...slug].astro b/src/pages/[...slug].astro
index e3d042d..4a38141 100644
--- a/src/pages/[...slug].astro
+++ b/src/pages/[...slug].astro
@@ -3,6 +3,7 @@ import BaseLayout from "@/layouts/BaseLayout.astro";
import Schema from "@/components/seo/Schema.astro";
import Tags from "@/components/ui/Tags.astro";
import Categories from "@/components/ui/Categories.astro";
+import Destinations from "@/components/ui/Destinations.astro";
import { toR2Url } from "@/utils/r2";
import Picture from "@/components/ui/Picture.astro";
@@ -18,8 +19,16 @@ export async function getStaticPaths() {
const { post } = Astro.props;
const { Content, remarkPluginFrontmatter } = await render(post);
-const { title, description, pubDate, author, image, categories, tags } =
- post.data;
+const {
+ title,
+ description,
+ pubDate,
+ author,
+ image,
+ categories,
+ tags,
+ destination,
+} = post.data;
const coverImage = toR2Url(image);
const formattedDate = pubDate.toLocaleDateString("vi-VN", {
@@ -70,6 +79,13 @@ const metadata = {
>
{title}
+ {
+ destination && destination.length > 0 && (
+
+
+
+ )
+ }
{
diff --git a/src/pages/destination/[destination]/[...page].astro b/src/pages/destination/[destination]/[...page].astro
new file mode 100644
index 0000000..bc948cf
--- /dev/null
+++ b/src/pages/destination/[destination]/[...page].astro
@@ -0,0 +1,64 @@
+---
+import BaseLayout from "@/layouts/BaseLayout.astro";
+import { getCollection } from "astro:content";
+import Headline from "@/components/ui/Headline.astro";
+import PostItem from "@/components/blog/PostItem.astro";
+import Pagination from "@/components/ui/Pagination.astro";
+import type { GetStaticPathsOptions } from "astro";
+
+export async function getStaticPaths({ paginate }: GetStaticPathsOptions) {
+ const allPosts = await getCollection("blog");
+ const posts = allPosts.filter((post) => post.data && post.data.pubDate);
+
+ const destinations = new Set();
+ posts.forEach((post) => {
+ post.data.destination?.forEach((d) => destinations.add(d));
+ });
+
+ return Array.from(destinations).flatMap((destination) => {
+ const destinationPosts = posts
+ .filter((post) => post.data.destination?.includes(destination))
+ .sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());
+
+ return paginate(destinationPosts, {
+ params: { destination },
+ pageSize: 6,
+ });
+ });
+}
+
+const { page } = Astro.props;
+const { destination } = Astro.params;
+
+const metadata = {
+ title: `Destination: ${destination}`,
+ description: `Travel articles about ${destination}.`,
+};
+---
+
+
+
+
+
+
+
+
+
+ {page.data.map((post) =>
)}
+
+
+
+
+