diff --git a/src/app/page.tsx b/src/app/page.tsx
index 50f34ed..231f2e3 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,8 +1,16 @@
-import { getNotionPages } from "@/lib/notion/notion";
+import { getArticles } from "@/lib/notion/notion";
import Link from "next/link";
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from "@/components/ui/card";
export default async function Home() {
- const posts = await getNotionPages({ pageSize: 10 });
+ const articles = await getArticles({ pageSize: 10 });
return (
@@ -11,19 +19,24 @@ export default async function Home() {
Франция | Гайд по иммиграции и интеграции
-
- {posts.map((post) => (
+
+ {articles.map((article) => (
-
- {post.properties.Page.title[0].plain_text}
-
-
- {new Date(post.created_time).toLocaleDateString()}
-
+
+
+ {article.title}
+
+
+ {article.description}
+
+
+ {new Date(article.publishedAt).toLocaleDateString()}
+
+
))}
diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx
new file mode 100644
index 0000000..cabfbfc
--- /dev/null
+++ b/src/components/ui/card.tsx
@@ -0,0 +1,76 @@
+import * as React from "react"
+
+import { cn } from "@/lib/utils"
+
+const Card = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+Card.displayName = "Card"
+
+const CardHeader = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardHeader.displayName = "CardHeader"
+
+const CardTitle = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardTitle.displayName = "CardTitle"
+
+const CardDescription = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardDescription.displayName = "CardDescription"
+
+const CardContent = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardContent.displayName = "CardContent"
+
+const CardFooter = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardFooter.displayName = "CardFooter"
+
+export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
diff --git a/src/lib/notion/mapper.ts b/src/lib/notion/mapper.ts
new file mode 100644
index 0000000..a17a866
--- /dev/null
+++ b/src/lib/notion/mapper.ts
@@ -0,0 +1,11 @@
+import { NotionPage } from "./schemas";
+
+export function mapNotionPageToArticle(page: NotionPage): Article {
+ return {
+ id: page.id,
+ title: page.properties.Page.title[0]?.plain_text || "",
+ description: page.properties.Description.rich_text[0]?.plain_text || "",
+ slug: page.properties.URL.url,
+ publishedAt: new Date(page.properties["Publish date"]?.date?.start || ""),
+ };
+}
diff --git a/src/lib/notion/notion.ts b/src/lib/notion/notion.ts
index 091811f..6815b3e 100644
--- a/src/lib/notion/notion.ts
+++ b/src/lib/notion/notion.ts
@@ -1,21 +1,22 @@
import { Client } from "@notionhq/client";
import { validateEnv } from "../env";
-import { NotionPages, pagesSchema } from "./schemas";
+import { pagesSchema } from "./schemas";
import { withNotionErrorHandling } from "./errorHandlers";
+import { mapNotionPageToArticle } from "./mapper";
const env = validateEnv();
const notion = new Client({
auth: env.NOTION_TOKEN,
});
-export const getNotionPages = async ({
+export const getArticles = async ({
pageSize,
startCursor,
}: {
pageSize: number;
startCursor?: string;
}) => {
- return withNotionErrorHandling(async () => {
+ return withNotionErrorHandling(async () => {
const response = await notion.databases.query({
database_id: env.NOTION_DATABASE_ID,
filter: {
@@ -33,7 +34,8 @@ export const getNotionPages = async ({
page_size: pageSize,
start_cursor: startCursor,
});
- console.log(JSON.stringify(response.results));
- return pagesSchema.parse(response.results);
+ const parsedNotionPages = pagesSchema.parse(response.results);
+
+ return parsedNotionPages.map(mapNotionPageToArticle);
}, "Failed to fetch pages");
};
diff --git a/src/lib/notion/schemas.ts b/src/lib/notion/schemas.ts
index 8c8d6eb..14f6e97 100644
--- a/src/lib/notion/schemas.ts
+++ b/src/lib/notion/schemas.ts
@@ -16,7 +16,7 @@ const multiSelectOptionSchema = z.object({
color: z.string(),
});
-const titleTextSchema = z.object({
+const textSchema = z.object({
type: z.string(),
text: z
.object({
@@ -78,7 +78,12 @@ const pagePropertiesSchema = z.object({
Page: z.object({
id: z.literal("title"),
type: z.literal("title"),
- title: z.array(titleTextSchema),
+ title: z.array(textSchema),
+ }),
+ Description: z.object({
+ id: z.string(),
+ type: z.literal("rich_text"),
+ rich_text: z.array(textSchema),
}),
Owner: z.object({
id: z.string(),
diff --git a/src/lib/notion/types.ts b/src/lib/notion/types.ts
new file mode 100644
index 0000000..c941e86
--- /dev/null
+++ b/src/lib/notion/types.ts
@@ -0,0 +1,7 @@
+type Article = {
+ id: string;
+ title: string;
+ description: string;
+ slug: string;
+ publishedAt: Date;
+};