From a3bec707b0f377509fbb3350f695ad96c699ed99 Mon Sep 17 00:00:00 2001 From: enes Date: Tue, 5 Nov 2024 16:22:08 +0100 Subject: [PATCH] feat(landing): show latest blog posts --- src/constants.ts | 3 +- src/pages/blog/loader.ts | 3 +- src/pages/blogs/loader.ts | 2 - src/pages/home.tsx | 142 ++++++++++++++++++++++++++++++-------- 4 files changed, 118 insertions(+), 32 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index e2838b0..8b91a18 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -20,7 +20,8 @@ export const LANDING_PAGE_DATA = { 'Cyberpunk 2077', 'ELDEN RING', 'The Coffin of Andy and Leyley' - ] + ], + featuredBlogPosts: [] } // we use this object to check if a user has reacted positively or negatively to a post // reactions are kind 7 events and their content is either emoji icon or emoji shortcode diff --git a/src/pages/blog/loader.ts b/src/pages/blog/loader.ts index 4cd0338..f4313c7 100644 --- a/src/pages/blog/loader.ts +++ b/src/pages/blog/loader.ts @@ -17,11 +17,11 @@ export const blogRouteLoader = 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) if (!event) { log(true, LogType.Error, 'Unable to fetch the blog event.') @@ -29,7 +29,6 @@ export const blogRouteLoader = } const blogDetails = extractBlogDetails(event) - return blogDetails } catch (error) { log( diff --git a/src/pages/blogs/loader.ts b/src/pages/blogs/loader.ts index 74066f5..f2ab84d 100644 --- a/src/pages/blogs/loader.ts +++ b/src/pages/blogs/loader.ts @@ -1,7 +1,6 @@ import { NDKFilter } from '@nostr-dev-kit/ndk' import { NDKContextType } from 'contexts/NDKContext' import { kinds } from 'nostr-tools' -import { toast } from 'react-toastify' import { log, LogType, npubToHex } from 'utils' import { extractBlogCardDetails } from 'utils/blog' @@ -31,7 +30,6 @@ export const blogsRouteLoader = (ndkContext: NDKContextType) => async () => { 'An error occurred in fetching blog details from relays', error ) - toast.error('An error occurred in fetching blog details from relays') return null } } diff --git a/src/pages/home.tsx b/src/pages/home.tsx index 903c207..3346d7e 100644 --- a/src/pages/home.tsx +++ b/src/pages/home.tsx @@ -1,6 +1,6 @@ -import { nip19 } from 'nostr-tools' +import { kinds, nip19 } from 'nostr-tools' import { useMemo, useState } from 'react' -import { useNavigate } from 'react-router-dom' +import { Link, useNavigate } from 'react-router-dom' import { A11y, Autoplay, Navigation, Pagination } from 'swiper/modules' import { Swiper, SwiperSlide } from 'swiper/react' import { BlogCard } from '../components/BlogCard' @@ -15,19 +15,25 @@ import { useNSFWList } from '../hooks' import { appRoutes, getModPageRoute } from '../routes' -import { ModDetails } from '../types' -import { extractModData, handleModImageError, log, LogType } from '../utils' +import { BlogCardDetails, ModDetails } from '../types' +import { + extractModData, + handleModImageError, + log, + LogType, + npubToHex +} from '../utils' import '../styles/cardLists.css' import '../styles/SimpleSlider.css' import '../styles/styles.css' // Import Swiper styles -import { NDKFilter } from '@nostr-dev-kit/ndk' +import { filterForEventsTaggingId, NDKFilter } from '@nostr-dev-kit/ndk' import 'swiper/css' import 'swiper/css/navigation' import 'swiper/css/pagination' -import placeholder from '../assets/img/DEGMods Placeholder Img.png' +import { extractBlogCardDetails } from 'utils/blog' export const HomePage = () => { const navigate = useNavigate() @@ -114,27 +120,7 @@ export const HomePage = () => { -
-
-

Blog Posts (WIP)

-
-
- - - - -
- -
- - View All - -
-
+ @@ -327,3 +313,105 @@ const Spinner = () => { ) } + +const DisplayLatestBlogs = () => { + const [blogs, setBlogs] = useState[]>() + const { fetchEvents } = useNDKContext() + + useDidMount(() => { + const fetchBlogs = async () => { + try { + // Show maximum of 4 blog posts + // 2 should be featured and the most recent 2 from blog npubs + + // Populate the filter from known naddr (constants.ts) + const filters: NDKFilter[] = [] + for (let i = 0; i < LANDING_PAGE_DATA.featuredBlogPosts.length; i++) { + try { + const naddr = LANDING_PAGE_DATA.featuredBlogPosts[i] + const filterId = filterForEventsTaggingId(naddr) + if (filterId) { + filters.push(filterId) + } + } catch (error) { + // Silently ignore + } + } + // Create a single filter based on multiple #a's + const filter = filters.reduce( + (filter, id) => { + const a = id['#a'] + if (a) { + filter['#a']?.push(a[0]) + } + return filter + }, + { + '#a': [] + } as NDKFilter + ) + // Fetch featured blogs posts + const featuredBlogPosts = await fetchEvents(filter) + + // Fetch latest blog npubs posts + const blogNpubs = import.meta.env.VITE_BLOG_NPUBS.split(',') + const blogHexkeys = blogNpubs + .map(npubToHex) + .filter((hexkey) => hexkey !== null) + + // We fetch 4 posts in case of duplicates (from featured) + const latestBlogPosts = await fetchEvents({ + authors: blogHexkeys, + kinds: [kinds.LongFormArticle], + limit: 4 + }) + + // Remove duplicates + const unique = Array.from( + [...featuredBlogPosts, ...latestBlogPosts] + .reduce((map, obj) => { + map.set(obj.id, obj) + return map + }, new Map()) + .values() + ) + const latest = unique.slice(0, 4) + + setBlogs(latest.map(extractBlogCardDetails)) + } catch (error) { + log( + true, + LogType.Error, + 'An error occurred in fetching blog details from relays', + error + ) + return null + } + } + + fetchBlogs() + }) + + return ( +
+
+

Blog Posts

+
+
+ {blogs?.map((b) => ( + + ))} +
+ +
+ + View All + +
+
+ ) +}