diff --git a/website/src/app/[lang]/publications/page-body.module.scss b/website/src/app/[lang]/publications/page-body.module.scss new file mode 100644 index 0000000..e054df0 --- /dev/null +++ b/website/src/app/[lang]/publications/page-body.module.scss @@ -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); + } +} diff --git a/website/src/app/[lang]/publications/page-body.tsx b/website/src/app/[lang]/publications/page-body.tsx new file mode 100644 index 0000000..173e7a9 --- /dev/null +++ b/website/src/app/[lang]/publications/page-body.tsx @@ -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 = ({ + publications, +}) => { + const publicationsByYear = publications + .map(getPublicationWithLink) + .reduce(getPublicationsByYear, [] as PublicationsByYear[]) + .sort(sortByYear); + + return publicationsByYear.map(({ year, publications }) => ( +
+

{year}

+ +
+ )); +}; + +const RegisterPageBody: React.FC = async ({ lang }) => { + const { + data: { + patientResearchHeading, + patientResearchContent, + patientPublications, + geneResearchHeading, + geneResearchContent, + genePublications, + }, + error, + } = await query({ + query: GetPublicationsPageDocument, + variables: { + locale: lang, + patientResearchHeadingId, + patientResearchContentId, + geneResearchHeadingId, + geneResearchContentId, + }, + }); + + if (error) { + return null; + } + + const headings = [ + patientResearchHeading?.content ?? '', + geneResearchHeading?.content ?? '', + ]; + + return ( + +
+

+ {patientResearchHeading?.content} +

+ {documentToReactComponents(patientResearchContent?.content?.json)} + +
+
+

+ {geneResearchHeading?.content} +

+ {documentToReactComponents(geneResearchContent?.content?.json)} + +
+
+ ); +}; + +export default RegisterPageBody; diff --git a/website/src/app/[lang]/publications/page-header.tsx b/website/src/app/[lang]/publications/page-header.tsx new file mode 100644 index 0000000..9ad0e70 --- /dev/null +++ b/website/src/app/[lang]/publications/page-header.tsx @@ -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 = async ({ + lang, +}) => { + const { query } = getClient(); + + // TODO: Change query + const { data, error } = await query({ + 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 ( + + ); +}; + +export default PublicationsPageHeader; diff --git a/website/src/app/[lang]/publications/page.tsx b/website/src/app/[lang]/publications/page.tsx new file mode 100644 index 0000000..2232276 --- /dev/null +++ b/website/src/app/[lang]/publications/page.tsx @@ -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 = async ({ params }) => { + const { lang } = await params; + + // TODO: Change query + const { + data: { + // @ts-ignore + htmlHeadMetadata: { title, description }, + }, + } = await query({ + query: GetMetadataDocument, + variables: { + locale: lang, + id: registerPatientPageMetadataId, + }, + }); + + const medicalStudy: WithContext = { + '@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 = { + '@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 ( + <> +