Skip to content

Commit

Permalink
Merge pull request #165 from nr2f1/publications
Browse files Browse the repository at this point in the history
publications page
  • Loading branch information
pataruco authored Jan 22, 2025
2 parents 94dc40d + 8756b3a commit a683b2d
Show file tree
Hide file tree
Showing 15 changed files with 830 additions and 150 deletions.
11 changes: 11 additions & 0 deletions website/src/app/[lang]/publications/page-body.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.publications {
ul {
margin: 0;
padding: 0;
padding-inline-start: var(--spacing-8);
}

&__by-year:not(:last-of-type) {
margin-block-end: var(--spacing-6);
}
}
163 changes: 163 additions & 0 deletions website/src/app/[lang]/publications/page-body.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import styles from './page-body.module.scss';

import PageBody from '@components/page-body';
import { documentToReactComponents } from '@contentful/rich-text-react-renderer';
import { getClient } from '@graphql/client';
import {
GetPublicationsPageDocument,
type GetPublicationsPageQuery,
} from '@graphql/queries/publications-page/index.generated';
import type { AvailableLocale } from '@i18n/locales';
import {
geneResearchHeadingId,
patientResearchHeadingId,
} from '@models/headings';
import {
geneResearchContentId,
patientResearchContentId,
} from '@models/paragraphs';
import { createHashLink } from '@shared/utils/hash-links';

interface RegisterPageBodyProps {
lang: AvailableLocale;
}

const { query } = getClient();

interface CleanedPublication {
__typename: 'Publication';
title: string;
dateOfPublication: string;
link: string | null;
asset: {
__typename: 'Asset';
url: string;
} | null;
}

interface PublicationWithLink {
title: string;
year: number;
link: string;
}

interface PublicationsByYear {
year: number;
publications: PublicationWithLink[];
}

const getPublicationWithLink = (
publication: CleanedPublication,
): PublicationWithLink => {
const { title, dateOfPublication, link, asset } = publication;
return {
title: title,
year: new Date(dateOfPublication).getFullYear(),
link: link ?? asset?.url ?? '',
};
};

const getPublicationsByYear = (
acc: PublicationsByYear[],
{ title, year, link }: PublicationWithLink,
) => {
const existingYear = acc.find((publication) => publication.year === year);

if (existingYear) {
existingYear.publications.push({ title, link, year });
} else {
acc.push({ year, publications: [{ title, link, year }] });
}

return acc;
};

const sortByYear = (
{ year: yearA }: PublicationsByYear,
{ year: yearB }: PublicationsByYear,
) => {
return yearB - yearA;
};

interface PublicationsByYearProps {
publications: CleanedPublication[];
}

const PublicationsByYear: React.FC<PublicationsByYearProps> = ({
publications,
}) => {
const publicationsByYear = publications
.map(getPublicationWithLink)
.reduce(getPublicationsByYear, [] as PublicationsByYear[])
.sort(sortByYear);

return publicationsByYear.map(({ year, publications }) => (
<div className={styles['publications__by-year']} key={crypto.randomUUID()}>
<h3>{year}</h3>
<ul>
{publications.map(({ title, link }) => (
<li key={crypto.randomUUID()}>
<a href={link}>{title}</a>
</li>
))}
</ul>
</div>
));
};

const RegisterPageBody: React.FC<RegisterPageBodyProps> = async ({ lang }) => {
const {
data: {
patientResearchHeading,
patientResearchContent,
patientPublications,
geneResearchHeading,
geneResearchContent,
genePublications,
},
error,
} = await query<GetPublicationsPageQuery>({
query: GetPublicationsPageDocument,
variables: {
locale: lang,
patientResearchHeadingId,
patientResearchContentId,
geneResearchHeadingId,
geneResearchContentId,
},
});

if (error) {
return null;
}

const headings = [
patientResearchHeading?.content ?? '',
geneResearchHeading?.content ?? '',
];

return (
<PageBody lang={lang} headings={headings} className={styles.publications}>
<section>
<h2 id={createHashLink(patientResearchHeading?.content ?? '')}>
{patientResearchHeading?.content}
</h2>
{documentToReactComponents(patientResearchContent?.content?.json)}
<PublicationsByYear
publications={patientPublications?.items as CleanedPublication[]}
/>
</section>
<section>
<h2 id={createHashLink(geneResearchHeading?.content ?? '')}>
{geneResearchHeading?.content}
</h2>
{documentToReactComponents(geneResearchContent?.content?.json)}
<PublicationsByYear
publications={genePublications?.items as CleanedPublication[]}
/>
</section>
</PageBody>
);
};

export default RegisterPageBody;
57 changes: 57 additions & 0 deletions website/src/app/[lang]/publications/page-header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import PageHeader from '@components/page-header';
import { getClient } from '@graphql/client';
import {
GetPageHeaderDocument,
type GetPageHeaderQuery,
} from '@graphql/queries/page-header/index.generated';
import type { AvailableLocale } from '@i18n/locales';
import { publicationsPageHeaderId } from '@models/page-header';

interface RegisterPageHeaderProps {
lang: AvailableLocale;
}

const PublicationsPageHeader: React.FC<RegisterPageHeaderProps> = async ({
lang,
}) => {
const { query } = getClient();

// TODO: Change query
const { data, error } = await query<GetPageHeaderQuery>({
query: GetPageHeaderDocument,
variables: {
locale: lang,
id: publicationsPageHeaderId,
},
});

if (
error ||
!data.pageHeader ||
!data.pageHeader.title ||
!data.pageHeader.sectionTitle ||
!data.pageHeader.lastUpdated ||
!data.pageHeader.image
) {
return null;
}

const {
title,
sectionTitle,
lastUpdated,
image: { url },
} = data.pageHeader;

return (
<PageHeader
lang={lang}
pageTitle={title}
sectionTitle={sectionTitle}
lastUpdated={lastUpdated}
imageUrl={url ?? ''}
/>
);
};

export default PublicationsPageHeader;
102 changes: 102 additions & 0 deletions website/src/app/[lang]/publications/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import SupportBanner from '@components/support-banner';
import { getClient } from '@graphql/client';
import {
GetMetadataDocument,
type GetMetadataQuery,
} from '@graphql/queries/metadata/index.generated';
import { registerPatientPageMetadataId } from '@models/metadata';
import type { PagePropsWithLocale } from '@shared/types/page-with-locale-params';
import type { Metadata, NextPage } from 'next';
import type { Graph, MedicalStudy, WebPage, WithContext } from 'schema-dts';
import RegisterPageBody from './page-body';
import PublicationsPageHeader from './page-header';

const { query } = getClient();

const Page: NextPage<PagePropsWithLocale> = async ({ params }) => {
const { lang } = await params;

// TODO: Change query
const {
data: {
// @ts-ignore
htmlHeadMetadata: { title, description },
},
} = await query<GetMetadataQuery>({
query: GetMetadataDocument,
variables: {
locale: lang,
id: registerPatientPageMetadataId,
},
});

const medicalStudy: WithContext<MedicalStudy> = {
'@context': 'https://schema.org',
'@type': 'MedicalStudy',
name: title,
description,
potentialAction: [
{
'@type': 'RegisterAction',
target: `https://nr2f1.org/${lang}/register-patient`,
name: title,
},
],
};

// TODO: Change schema
const webPage: WithContext<WebPage> = {
'@context': 'https://schema.org',
'@type': 'WebPage',
url: `https://nr2f1.org/${lang}/register-a-patient`,
name: title,
inLanguage: lang,
};

const jsonLd: Graph = {
'@context': 'https://schema.org',
'@graph': [medicalStudy, webPage],
};

return (
<>
<script
type="application/ld+json"
// biome-ignore lint/security/noDangerouslySetInnerHtml: this is a safe usage
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<PublicationsPageHeader lang={lang} />
<RegisterPageBody lang={lang} />
<SupportBanner lang={lang} />
</>
);
};

export default Page;

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

// TODO: Change query
const {
data: {
// @ts-ignore
htmlHeadMetadata: { title, description, keywords },
},
error,
} = await query<GetMetadataQuery>({
query: GetMetadataDocument,
variables: {
locale: lang,
id: registerPatientPageMetadataId,
},
});

return {
title: `NR2F1 Foundation | ${title}`,
description,
keywords,
};
}
Loading

0 comments on commit a683b2d

Please sign in to comment.