From 3717c3bfb9a00b75a512e3c11bca51d57257bffa Mon Sep 17 00:00:00 2001 From: enes Date: Thu, 31 Oct 2024 20:14:29 +0100 Subject: [PATCH] feat: fetching blog data --- src/layout/header.tsx | 2 +- src/pages/blog.tsx | 1 - src/pages/blog/index.tsx | 227 +++++++++++++++++++++++++++++++++++++++ src/pages/blog/loader.ts | 70 ++++++++++++ src/routes/index.tsx | 8 +- src/types/blog.ts | 14 ++- src/utils/nostr.ts | 16 +++ 7 files changed, 332 insertions(+), 6 deletions(-) delete mode 100644 src/pages/blog.tsx create mode 100644 src/pages/blog/index.tsx create mode 100644 src/pages/blog/loader.ts diff --git a/src/layout/header.tsx b/src/layout/header.tsx index 011b7cf..18d034f 100644 --- a/src/layout/header.tsx +++ b/src/layout/header.tsx @@ -212,7 +212,7 @@ export const Header = () => { About Blog diff --git a/src/pages/blog.tsx b/src/pages/blog.tsx deleted file mode 100644 index 47c67f8..0000000 --- a/src/pages/blog.tsx +++ /dev/null @@ -1 +0,0 @@ -export const BlogPage = () => <>WIP diff --git a/src/pages/blog/index.tsx b/src/pages/blog/index.tsx new file mode 100644 index 0000000..971c453 --- /dev/null +++ b/src/pages/blog/index.tsx @@ -0,0 +1,227 @@ +import { LoadingSpinner } from 'components/LoadingSpinner' +import { ProfileSection } from 'components/ProfileSection' +import { useLoaderData } from 'react-router-dom' +import { BlogDetails } from 'types' + +export const BlogPage = () => { + const data = useLoaderData() as Partial + + if (!data) return + + return ( +
+
+
+
+
+
+ {/* */} +
+
+
+
+

Heading

+
+
+
+
+

NSFW

+
+ Tag 1 + Tag 2 + Tag 3 +
+
+
+ {/*
+
+ +
+
+ +
+

420

+
+
+
+
+ +
+

69k

+
+
+
+
+
+
+ +
+

4.2k

+
+
+
+
+
+
+ +
+

69

+
+
+
+
+
+
+
+
+
+ + +

01/11/2024

+
+
+ + +

24/11/2024

+
+ + +

degmods.com

+
+
+
+
*/} + {/* */} + {/*
+
+

Comments

+
+ +
+
+
+ +
+

Yo this article was insane to read!

+
+
+
+
+ + + +

52

+
+
+
+
+
+ + + +

4

+
+
+
+
+
+ + + +

6

+
+
+
+
+
+ + + +

500K

+
+
+
+
+
+ + + +

12

+

Replies

+
+
+

Reply

+
+
+
+
+
+
+
+
+
*/} +
+
+ {!!data.author && } +
+
+ + + ) +} diff --git a/src/pages/blog/loader.ts b/src/pages/blog/loader.ts new file mode 100644 index 0000000..c241b7e --- /dev/null +++ b/src/pages/blog/loader.ts @@ -0,0 +1,70 @@ +import { filterForEventsTaggingId, NDKEvent } from '@nostr-dev-kit/ndk' +import { NDKContextType } from 'contexts/NDKContext' +import { LoaderFunctionArgs, redirect } from 'react-router-dom' +import { toast } from 'react-toastify' +import { appRoutes } from 'routes' +import { BlogDetails } from 'types' +import { + getFirstTagValue, + getFirstTagValueAsInt, + getTagValue, + log, + LogType +} from 'utils' + +export const blogRouteLoader = + (ndkContext: NDKContextType) => + async ({ params }: LoaderFunctionArgs) => { + const { naddr } = params + if (!naddr) { + log(true, LogType.Error, 'Required naddr.') + return redirect(appRoutes.blogs) + } + + try { + const filter = filterForEventsTaggingId(naddr) + if (!filter) { + log(true, LogType.Error, 'Unable to create filter from blog naddr.') + return redirect(appRoutes.blogs) + } + + const event = await ndkContext.fetchEvent(filter) + console.log(event) + if (event) { + const blogDetails = extractBlogDetails(event) + + console.log(blogDetails) + return blogDetails + } + + return null + } catch (error) { + log( + true, + LogType.Error, + 'An error occurred in fetching blog details from relays', + error + ) + toast.error('An error occurred in fetching mod details from relays') + return redirect(appRoutes.blogs) + } + } + +function extractBlogDetails(event: NDKEvent): Partial { + return { + title: getFirstTagValue(event, 'title'), + content: event.content, + summary: getFirstTagValue(event, 'summary'), + image: getFirstTagValue(event, 'image'), + nsfw: getFirstTagValue(event, 'nsfw') === 'true', + + id: event.id, + author: event.pubkey, + published_at: getFirstTagValueAsInt(event, 'published_at'), + edited_at: event.created_at, + rTag: getFirstTagValue(event, 'r') || 'N/A', + dTag: getFirstTagValue(event, 'd'), + aTag: getFirstTagValue(event, 'a'), + tTags: getTagValue(event, 't') || [] + } +} diff --git a/src/routes/index.tsx b/src/routes/index.tsx index bc14e69..e875d86 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -3,7 +3,6 @@ import { NDKContextType } from 'contexts/NDKContext' import { Layout } from 'layout' import { SearchPage } from '../pages/search' import { AboutPage } from '../pages/about' -import { BlogsPage } from '../pages/blogs' import { GamesPage } from '../pages/games' import { HomePage } from '../pages/home' import { ModPage } from '../pages/mod' @@ -18,7 +17,9 @@ import { FeedPage } from '../pages/feed' import { NotificationsPage } from '../pages/notifications' import { WritePage } from '../pages/write' import { writeRouteAction } from '../pages/write/action' +import { BlogsPage } from 'pages/blogs' import { BlogPage } from 'pages/blog' +import { blogRouteLoader } from 'pages/blog/loader' export const appRoutes = { index: '/', @@ -29,7 +30,7 @@ export const appRoutes = { mod: '/mod/:naddr', about: '/about', blogs: '/blogs', - blog: '/blog/:naddr', + blog: '/blogs/:naddr', submitMod: '/submit-mod', editMod: '/edit-mod/:naddr', write: '/write', @@ -93,7 +94,8 @@ export const routerWithNdkContext = (context: NDKContextType) => }, { path: appRoutes.blog, - element: + element: , + loader: blogRouteLoader(context) }, { path: appRoutes.submitMod, diff --git a/src/types/blog.ts b/src/types/blog.ts index 7a7c956..bedb751 100644 --- a/src/types/blog.ts +++ b/src/types/blog.ts @@ -10,12 +10,24 @@ export interface BlogDetails { author: string published_at: number edited_at: number + rTag: string + dTag: string + aTag: string + tTags: string[] } export interface BlogFormSubmit extends Omit< BlogDetails, - 'nsfw' | 'id' | 'author' | 'published_at' | 'edited_at' + | 'nsfw' + | 'id' + | 'author' + | 'published_at' + | 'edited_at' + | 'rTag' + | 'dTag' + | 'aTag' + | 'tTag' > { nsfw: string } diff --git a/src/utils/nostr.ts b/src/utils/nostr.ts index 130d023..b1fd0e1 100644 --- a/src/utils/nostr.ts +++ b/src/utils/nostr.ts @@ -65,6 +65,22 @@ export const getTagValue = ( return null } +export const getFirstTagValue = ( + event: Event | NDKEvent, + tagIdentifier: string +) => { + const tags = getTagValue(event, tagIdentifier) + return tags && tags.length ? tags[0] : undefined +} + +export const getFirstTagValueAsInt = ( + event: Event | NDKEvent, + tagIdentifier: string +) => { + const value = getFirstTagValue(event, tagIdentifier) + return value ? parseInt(value, 10) : undefined +} + /** * @param hexKey hex private or public key * @returns whether or not is key valid