Skip to content

Commit

Permalink
Merge pull request #185 from nr2f1/news
Browse files Browse the repository at this point in the history
News
  • Loading branch information
pataruco authored Feb 1, 2025
2 parents 10c79c4 + d3421c0 commit a9e0369
Show file tree
Hide file tree
Showing 23 changed files with 486 additions and 179 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
GetPostDocument,
type GetPostQuery,
} from '@graphql/queries/post/index.generated';
import type { BlogPagePropsWithLocale } from '@shared/types/page-with-locale-params';
import type { NewsPagePropsWithLocale } from '@shared/types/page-with-locale-params';
import { getIntlDateStrings } from '@shared/utils/intl-date';
import { renderNode } from '@shared/utils/rich-text';
import type { Metadata, NextPage } from 'next';
Expand All @@ -16,7 +16,7 @@ const { query } = getClient();

export async function generateMetadata({
params,
}: BlogPagePropsWithLocale): Promise<Metadata> {
}: NewsPagePropsWithLocale): Promise<Metadata> {
const { lang, slug } = await params;

const { data } = await query<GetPostQuery>({
Expand All @@ -35,7 +35,7 @@ export async function generateMetadata({
title,
description,
type: 'article',
url: `https://nr2f1.org/${lang}/blog/${slug}`,
url: `https://nr2f1.org/${lang}/news/${slug}`,
locale: lang,
images: {
url: imgUrl,
Expand All @@ -44,7 +44,7 @@ export async function generateMetadata({
};
}

const Page: NextPage<BlogPagePropsWithLocale> = async ({ params }) => {
const Page: NextPage<NewsPagePropsWithLocale> = async ({ params }) => {
const { lang, slug } = await params;

const { data } = await query<GetPostQuery>({
Expand Down Expand Up @@ -72,7 +72,7 @@ const Page: NextPage<BlogPagePropsWithLocale> = async ({ params }) => {
'@type': 'Blog',
headline: post?.title ?? '',
datePublished: publishedString,
url: `https://nr2f1.org/blog/${slug}`,
url: `https://nr2f1.org/news/${slug}`,
abstract: post?.excerpt ?? '',
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@use '@styles/text-styles';
@use '@styles/breakpoints';

.blog {
.news {
padding: var(--spacing-6) var(--spacing-16) var(--spacing-24);

ul {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import NewsCard from '@components/news-card';
import styles from './page-body.module.scss';

import NewsCard from '@components/news-card';
import Pagination from '@components/pagination';
import { getClient } from '@graphql/client';
import {
GetPostsDocument,
type GetPostsQuery,
} from '@graphql/queries/posts/index.generated';
GetNewsDocument,
type GetNewsQuery,
} from '@graphql/queries/news/index.generated';
import type { BlogPageCollection, NewsletterCollection } from '@graphql/types';
import type { AvailableLocale } from '@i18n/locales';
import { News } from '@shared/types/news';
import { fromBlogNewsletterToNews } from '@shared/utils/from-blog-newsletter-to-news';
import type { CollectionPage, WithContext } from 'schema-dts';

interface BlogPageBodyProps {
interface NewsPageBodyProps {
lang: AvailableLocale;
page?: string | string[] | undefined;
}
const { query } = getClient();

const getSkipPagination = (page: BlogPageBodyProps['page'], limit: number) => {
const getSkipPagination = (page: NewsPageBodyProps['page'], limit: number) => {
if (!page) {
return 0;
}
Expand All @@ -30,65 +33,74 @@ const getSkipPagination = (page: BlogPageBodyProps['page'], limit: number) => {
return pageNumber * limit;
};

const BlogPageBody: React.FC<BlogPageBodyProps> = async ({ lang, page }) => {
const NewsPageBody: React.FC<NewsPageBodyProps> = async ({ lang, page }) => {
const LIMIT = 12;

const {
data: { blogPageCollection },
data: { entryCollection },
error,
} = await query<GetPostsQuery>({
query: GetPostsDocument,
} = await query<GetNewsQuery>({
query: GetNewsDocument,
variables: {
locale: lang,
skip: page ? getSkipPagination(page, LIMIT) : 0,
limit: LIMIT,
},
});

if (error || !blogPageCollection || !blogPageCollection?.items) {
if (error || !entryCollection?.items) {
return null;
}

const { total } = blogPageCollection;
const { total, items } = entryCollection;

const rawPosts = items.filter((item) => item?.__typename === 'BlogPage');

const rawNewsletter = items.filter(
(item) => item?.__typename === 'Newsletter',
);

const allNews = fromBlogNewsletterToNews({
posts: rawPosts as BlogPageCollection['items'],
newsletters: rawNewsletter as NewsletterCollection['items'],
limit: total,
});

const start = getSkipPagination(page, LIMIT);
const end = start + LIMIT;

const news = allNews.slice(start, end);

const posts = blogPageCollection.items.map((item) => ({
title: item?.title ?? '',
slug: item?.slug ?? '',
date: item?.date ?? '',
excerpt: item?.excerpt ?? '',
imageUrl: item?.image?.url ?? '',
}));
const newsPosts = news.filter((item) => item.type === News.BLOG);

const jsonLd: WithContext<CollectionPage> = {
'@context': 'https://schema.org',
'@type': 'CollectionPage',
mainEntity: posts.map(({ title, slug, excerpt, imageUrl }) => ({
mainEntity: newsPosts.map(({ title, url, imageUrl }) => ({
'@type': 'BlogPosting',
headline: title,
url: `https://nr2f1.org/${lang}/blog/${slug}`,
abstract: excerpt,
image: imageUrl,
url: `https://nr2f1.org/${lang}/news/${url}`,
image: imageUrl ?? undefined,
})),
};

return (
<section className={styles.blog}>
<section className={styles.news}>
<script
type="application/ld+json"
// biome-ignore lint/security/noDangerouslySetInnerHtml: this is a safe usage
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<div className="content-wrapper">
<nav>
<ul className={styles.blog__articles}>
{posts.map(({ title, slug, date, imageUrl }) => (
<ul className={styles.news__articles}>
{news.map(({ title, url, date, imageUrl, type }) => (
<NewsCard
date={date}
imageUrl={imageUrl}
key={crypto.randomUUID()}
lang={lang}
slug={slug}
url={url}
title={title}
type={type}
/>
))}
</ul>
Expand All @@ -106,4 +118,4 @@ const BlogPageBody: React.FC<BlogPageBodyProps> = async ({ lang, page }) => {
);
};

export default BlogPageBody;
export default NewsPageBody;
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import {
import type { AvailableLocale } from '@i18n/locales';
import { blogsPageHeaderId } from '@models/page-header';

interface BlogPageHeaderProps {
interface NewsPageHeaderProps {
lang: AvailableLocale;
}

const { query } = getClient();

const BlogPageHeader: React.FC<BlogPageHeaderProps> = async ({ lang }) => {
const NewsPageHeader: React.FC<NewsPageHeaderProps> = async ({ lang }) => {
const { data, error } = await query<GetBlogPageHeaderQuery>({
query: GetBlogPageHeaderDocument,
variables: {
Expand Down Expand Up @@ -43,4 +43,4 @@ const BlogPageHeader: React.FC<BlogPageHeaderProps> = async ({ lang }) => {
);
};

export default BlogPageHeader;
export default NewsPageHeader;
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
import type { PagePropsWithLocale } from '@shared/types/page-with-locale-params';
import type { Metadata, NextPage } from 'next';
import BlogPageBody from './page-body';
import BlogPageHeader from './page-header';
import NewsPageBody from './page-body';
import NewsPageHeader from './page-header';

export const metadata: Metadata = {
title: 'NR2F1 Foundation | Blog',
description: 'Blog',
// Todo: update i18n title and description
title: 'NR2F1 Foundation | News',
description: 'News',
};

interface BlogPageProps extends PagePropsWithLocale {
interface NewsPageProps extends PagePropsWithLocale {
searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
}

// todo: create getStaticProps

const Page: NextPage<BlogPageProps> = async ({ params, searchParams }) => {
const Page: NextPage<NewsPageProps> = async ({ params, searchParams }) => {
const { lang } = await params;
const { page } = await searchParams;

return (
<>
<BlogPageHeader lang={lang} />
<BlogPageBody lang={lang} page={page} />
<NewsPageHeader lang={lang} />
<NewsPageBody lang={lang} page={page} />
</>
);
};
Expand Down
26 changes: 17 additions & 9 deletions website/src/components/latest-news/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import NewsCard from '@components/news-card';
import styles from './index.module.scss';

import NewsCard from '@components/news-card';
import { getClient } from '@graphql/client';
import {
GetLatestNewsDocument,
type GetLatestNewsQuery,
} from '@graphql/queries/latest-news/index.generated';
import type { BlogPageCollection, NewsletterCollection } from '@graphql/types';
import type { AvailableLocale } from '@i18n/locales';
import { latestNewsTitleId } from '@models/headings';
import { latestNewsCtaId } from '@models/links';
import { fromBlogNewsletterToNews } from '@shared/utils/from-blog-newsletter-to-news';
import Link from 'next/link';

interface LatestNewsProps {
Expand All @@ -31,26 +33,32 @@ const LatestNews: React.FC<LatestNewsProps> = async ({ lang }) => {
return null;
}

const { title, cta, posts } = data;
const { title, cta, posts, newsletters } = data;

if (!posts.items) {
if (!posts.items || !newsletters?.items) {
return null;
}

const news = fromBlogNewsletterToNews({
posts: posts.items as BlogPageCollection['items'],
newsletters: newsletters.items as NewsletterCollection['items'],
limit: 6,
});

return (
<section className={styles.news}>
<div className="content-wrapper">
<h2>{title.content}</h2>

<ul className={styles.news__articles}>
{posts.items.map((post) => (
{news.map((news) => (
<NewsCard
date={post?.date ?? ''}
imageUrl={post?.image?.url ?? ''}
date={news.date ?? ''}
imageUrl={news.imageUrl}
key={crypto.randomUUID()}
lang={lang}
title={post?.title ?? ''}
slug={post?.slug ?? ''}
title={news?.title}
url={news.url}
type={news.type}
/>
))}
</ul>
Expand Down
13 changes: 13 additions & 0 deletions website/src/components/news-card/index.module.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@use '@styles/breakpoints';
@use '@styles/buttons';
@use '@styles/text-styles';
@use '@styles/icons';

.article {
border-radius: var(--border-radius-xl);
Expand Down Expand Up @@ -37,6 +38,18 @@
}
}

&__newsletter_img {
height: var(--spacing-56);
background-size: cover;
background-repeat: no-repeat;
background-position: center;
background-image: url(icons.$newsletter);

@include breakpoints.small-screen {
height: var(--spacing-40);
}
}

& div {
padding: var(--spacing-4);
}
Expand Down
Loading

0 comments on commit a9e0369

Please sign in to comment.