Skip to content

Commit

Permalink
feat(pdc-frontend): improve the image component & enable figcaption
Browse files Browse the repository at this point in the history
- [x] fix the broken image
- [x] improve the image component implementation
- [x] enable figcaption
  • Loading branch information
AliKdhim87 committed Sep 27, 2023
1 parent d19262e commit 943b9c3
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 99 deletions.
2 changes: 1 addition & 1 deletion apps/pdc-frontend/src/app/[locale]/[...not-found]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const NotFoundPage = async ({ params: { locale } }: { params: { locale: string }
]}
/>
<PageTitle>{data?.notFoundPage?.data?.attributes?.title}</PageTitle>
<Markdown strapiBackendURL={process.env.STRAPI_PUBLIC_URL}>{data?.notFoundPage?.data?.attributes?.body}</Markdown>
<Markdown>{data?.notFoundPage?.data?.attributes?.body}</Markdown>
</div>
);
};
Expand Down
2 changes: 1 addition & 1 deletion apps/pdc-frontend/src/app/[locale]/not-found.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const NotFoundPage = async () => {
]}
/>
<PageTitle>{data?.notFoundPage?.data?.attributes?.title}</PageTitle>
<Markdown strapiBackendURL={process.env.STRAPI_PUBLIC_URL}>{data?.notFoundPage?.data?.attributes?.body}</Markdown>
<Markdown>{data?.notFoundPage?.data?.attributes?.body}</Markdown>
</div>
);
};
Expand Down
47 changes: 16 additions & 31 deletions apps/pdc-frontend/src/app/[locale]/products/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Metadata } from 'next';
import { cookies, draftMode } from 'next/headers';
import Image from 'next/image';
import { notFound } from 'next/navigation';
import React from 'react';
import { useTranslation } from '@/app/i18n';
Expand All @@ -22,11 +21,13 @@ import {
import { BottomBar, BottomBarItem } from '@/components/BottomBar';
import { Breadcrumbs } from '@/components/Breadcrumb';
import { FAQSection } from '@/components/FAQSection';
import { Img } from '@/components/Img';
import { Markdown } from '@/components/Markdown';
import { PreviewAlert } from '@/components/PreviewAlert';
import { ReactionLink } from '@/components/ReactionLink';
import { ScrollToTopButton } from '@/components/ScrollToTopButton';
import { GET_PRODUCT_BY_SLUG_FETCH } from '@/query';
import { buildImgURL } from '@/util/buildImgURL';
import { createStrapiURL } from '@/util/createStrapiURL';
import { fetchData } from '@/util/fetchData';

Expand Down Expand Up @@ -135,15 +136,15 @@ const Product = async ({ params: { locale, slug }, searchParams }: ProductProps)
const { product } = await getAllProducts(locale, slug);

const priceData = product?.attributes.price && product?.attributes.price?.data?.attributes.price;
const strapiImageURL = process.env.STRAPI_PUBLIC_URL;

const { t } = await useTranslation(locale, 'common');
const Sections = () =>
product?.attributes && product?.attributes.sections.length > 0
? product?.attributes.sections.map((component: any, index: number) => {
switch (component.__typename) {
case 'ComponentComponentsBlockContent':
return component.content ? (
<Markdown strapiBackendURL={strapiImageURL} locale={locale} key={index} priceData={priceData}>
<Markdown locale={locale} key={index} priceData={priceData}>
{component.content}
</Markdown>
) : null;
Expand All @@ -170,7 +171,6 @@ const Product = async ({ params: { locale, slug }, searchParams }: ProductProps)
accordion={component.faq.data.attributes.faq.accordion}
sectionTitle={component.faq.data.attributes.title}
priceData={priceData}
strapiBackendURL={strapiImageURL}
/>
);
}
Expand All @@ -183,43 +183,28 @@ const Product = async ({ params: { locale, slug }, searchParams }: ProductProps)
label: title,
headingLevel: 3, // TODO add this property from CMS
body: (
<Markdown priceData={priceData} locale={locale} strapiBackendURL={strapiImageURL}>
<Markdown priceData={priceData} locale={locale}>
{body}
</Markdown>
),
}))}
/>
);
case 'ComponentComponentsImage':
if (
component.imageData &&
component.imageData.data.attributes &&
component.imageData.data.attributes.url
) {
return (
<Image
src={`${strapiImageURL}${component.imageData.data.attributes.url}`}
alt={component.imageData.data.attributes.alternativeText || ''}
sizes="(max-width: 768px) 100vw,
(max-width: 1200px) 50vw,
33vw"
width={component.imageData.data.attributes.width}
height={component.imageData.data.attributes.height}
style={{
maxWidth: '100%',
height: 'auto',
}}
/>
);
} else {
return null;
}
return (
<Img
src={buildImgURL(component?.imageData?.data?.attributes?.url)}
width={component?.imageData?.data?.attributes?.width}
height={component?.imageData?.data?.attributes?.height}
alt={component?.imageData?.data?.attributes?.alternativeText}
data-figcaption={component?.imageData?.data?.attributes?.caption}
/>
);

case 'ComponentComponentsSpotlight':
return component.content ? (
<SpotlightSection type={component.type} aside={component?.aside}>
<Markdown strapiBackendURL={strapiImageURL} priceData={priceData}>
{component.content}
</Markdown>
<Markdown priceData={priceData}>{component.content}</Markdown>
</SpotlightSection>
) : null;
case 'ComponentComponentsButtonLink':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const SearchTips = async ({ params: { locale, query } }: any) => {
]}
/>
<PageTitle>{`${title} "${query}"`}</PageTitle>
<Markdown strapiBackendURL={process.env.STRAPI_PUBLIC_URL}>{body}</Markdown>
<Markdown>{body}</Markdown>
</>
);
};
Expand Down
11 changes: 2 additions & 9 deletions apps/pdc-frontend/src/components/FAQSection/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,9 @@ export interface FAQSectionProps {
accordion?: AccordionType[];
locale?: string;
priceData?: any;
strapiBackendURL?: any;
}

export const FAQSection: React.FC<FAQSectionProps> = ({
sectionTitle,
accordion,
locale,
priceData,
strapiBackendURL,
}) => (
export const FAQSection: React.FC<FAQSectionProps> = ({ sectionTitle, accordion, locale, priceData }) => (
<section>
<Heading2>{sectionTitle}</Heading2>
{accordion && accordion.length > 0 && (
Expand All @@ -32,7 +25,7 @@ export const FAQSection: React.FC<FAQSectionProps> = ({
label: title,
headingLevel: 3, // TODO add this property from CMS
body: (
<Markdown priceData={priceData} locale={locale} strapiBackendURL={strapiBackendURL}>
<Markdown priceData={priceData} locale={locale}>
{body}
</Markdown>
),
Expand Down
22 changes: 22 additions & 0 deletions apps/pdc-frontend/src/components/Img/index.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.utrecht-img {
block-size: auto;
max-inline-size: 100%;
}

.utrecht-figure {
--utrecht-figure-margin-inline-start: 0;
--utrecht-figure-margin-inline-end: 0;
--utrecht-figure-margin-block-start: var(--utrecht-space-block-md);
--utrecht-figure-margin-block-end: var(--utrecht-space-block-md);

margin-block-end: var(--utrecht-figure-margin-block-end);
margin-block-start: var(--utrecht-figure-margin-block-start);
margin-inline-end: var(--utrecht-figure-margin-inline-end);
margin-inline-start: var(--utrecht-figure-margin-inline-start);
}

.utrecht-figure__figcaption {
--utrecht-figure--figcaption-color: var(--utrecht-color-grey-40);

color: var(--utrecht-figure--figcaption-color);
}
39 changes: 39 additions & 0 deletions apps/pdc-frontend/src/components/Img/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import classNames from 'classnames/bind';
import Image from 'next/image';
import React from 'react';
import styles from './index.module.scss';

const css = classNames.bind(styles);

export interface ImgProps
extends Omit<React.DetailedHTMLProps<React.ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>, 'ref'> {}
export const Img = (props: ImgProps & { 'data-figcaption'?: null }) => {
const { height, width, src, alt, title } = props;

if (width && height && src) {
const imgElement = (
<Image
className={css('utrecht-img')}
src={src}
alt={alt || ''}
title={title}
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
width={width as number}
height={height as number}
/>
);

if (props['data-figcaption']) {
return (
<figure className={css('utrecht-figure')}>
{imgElement}
<figcaption className={css('utrecht-figure__figcaption')}>{props['data-figcaption']}</figcaption>
</figure>
);
}

return imgElement;
}

return null;
};
76 changes: 20 additions & 56 deletions apps/pdc-frontend/src/components/Markdown/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
'use client';

import isAbsoluteUrl from 'is-absolute-url';
import Image from 'next/image';
import NextLink from 'next/link';
import React from 'react';
import ReactMarkdown, { Components } from 'react-markdown';
Expand All @@ -26,8 +23,10 @@ import {
UnorderedList,
UnorderedListItem,
} from '@/components';
import { useTranslation } from '../../app/i18n/client';
import { buildImgURL } from '@/util/buildImgURL';
import { useTranslation } from '../../app/i18n';
import { fallbackLng } from '../../app/i18n/settings';
import { Img } from '../Img';

type PriceTypes = {
value: string;
Expand All @@ -36,17 +35,7 @@ type PriceTypes = {
id: string;
};

const components = ({
strapiBackendURL,
priceData,
locale,
freeProductLabel,
}: {
strapiBackendURL: string;
priceData: PriceTypes[];
locale: string;
freeProductLabel: string;
}) =>
const components = ({ priceData, locale }: { priceData: PriceTypes[]; locale: string }) =>
({
h1: ({ children, node }) => {
delete node.properties?.style;
Expand Down Expand Up @@ -137,33 +126,15 @@ const components = ({
delete node.properties?.style;
return <TableCaption {...node.properties}>{children}</TableCaption>;
},
img: ({ width, height, src, alt }) => {
if (width && height && src && alt) {
return (
<Image
src={`${strapiBackendURL}${src}`}
alt={alt || ''}
sizes="(max-width: 768px) 100vw,
(max-width: 1200px) 50vw,
33vw"
width={width as number}
height={height as number}
style={{
maxWidth: '100%',
height: 'auto',
}}
/>
);
} else {
return null;
}
},
'react-widget': ({ node }: any) => {
img: (props) => props.src && <Img {...props} src={buildImgURL(props.src)} />,
'react-widget': async ({ node }: any) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const { t } = await useTranslation(locale ?? fallbackLng, 'common');
if (node.properties?.id && priceData && priceData.length > 0) {
const product = priceData.find(({ id }) => id === node.properties?.id);
const price =
Number(product?.value) === 0
? freeProductLabel
? t('text.free-product')
: new Intl.NumberFormat(locale, {
style: 'currency',
currency: product?.currency,
Expand All @@ -180,23 +151,16 @@ interface MarkdownProps {
children: any;
priceData?: any;
locale?: string;
strapiBackendURL?: string;
}

export const Markdown: React.FC<MarkdownProps> = ({ children, priceData, locale, strapiBackendURL }) => {
const url = strapiBackendURL ? new URL(strapiBackendURL) : null;
const { t } = useTranslation(locale ?? fallbackLng, 'common');
return (
<ReactMarkdown
components={components({
priceData,
locale: locale ?? fallbackLng,
strapiBackendURL: url?.origin ?? '',
freeProductLabel: t('text.free-product'),
})}
rehypePlugins={[rehypeRaw]}
>
{children}
</ReactMarkdown>
);
};
export const Markdown: React.FC<MarkdownProps> = ({ children, priceData, locale }) => (
<ReactMarkdown
components={components({
priceData,
locale: locale ?? fallbackLng,
})}
rehypePlugins={[rehypeRaw]}
>
{children}
</ReactMarkdown>
);
12 changes: 12 additions & 0 deletions apps/pdc-frontend/src/util/buildImgURL.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export const buildImgURL = (src: string) => {
if (!process.env.STRAPI_PUBLIC_URL) {
throw new Error('`STRAPI_PUBLIC_URL` is required to construct the image URL in the Markdown component.');
}
const url = new URL(process.env.STRAPI_PUBLIC_URL);
// if we need to support a different image-provider-upload, we can use the following approach
// just rename env variable
// if (process.env.DEPLOY_TO_VERCEL && Boolean(process.env.DEPLOY_TO_VERCEL)) {
// return src;
// }
return `${url?.origin}${src}`;
};

0 comments on commit 943b9c3

Please sign in to comment.