Skip to content
This repository has been archived by the owner on Nov 4, 2024. It is now read-only.

Commit

Permalink
feature/COR-1598-general-page-redesigns (#4802)
Browse files Browse the repository at this point in the history
* feat(page-redesigns): added FAQ and Data Explained schemas for page parts; added and updated components to facilitate new page parts; updated types; left some TODOs to be picked up;

* feat(page-redesigns): cleaned up TODOs; implemented more configuration options through Sanity;

* feat(page-redesigns): applied Sanity json edits;

* feat(page-redesigns): implemented feature on all pages; small styling changes; applied more Sanity JSON edits;

* feat(page-redesigns): fixed broken anchor for FAQ links;

* feat(page-redesigns): PR feedback; added utils; updated FAQ component styles; updated Article component styles; added TODOs related to COR-1601;

* feat(page-redesigns): minor barrel file fixes;

* feat(page-redesign): fixed additional barrel files;

---------

Co-authored-by: VWSCoronaDashboard26 <[email protected]>
  • Loading branch information
VWSCoronaDashboard26 and VWSCoronaDashboard26 authored Jun 30, 2023
1 parent f02b680 commit 25a0666
Show file tree
Hide file tree
Showing 42 changed files with 1,043 additions and 332 deletions.
16 changes: 14 additions & 2 deletions packages/app/src/components/chart-tile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,26 @@ interface ChartTileProps {
title: string;
description?: string;
disableFullscreen?: boolean;
id?: string;
metadata?: MetadataProps;
timeframeInitialValue?: TimeframeOption;
timeframeOptions?: TimeframeOption[];
toggle?: ChartTileToggleProps;
onSelectTimeframe?: (timeframe: TimeframeOption) => void;
}

export const ChartTile = ({ children, title, description, disableFullscreen, metadata, timeframeInitialValue, toggle, timeframeOptions, onSelectTimeframe }: ChartTileProps) => {
export const ChartTile = ({
children,
title,
description,
disableFullscreen,
id,
metadata,
timeframeInitialValue,
toggle,
timeframeOptions,
onSelectTimeframe,
}: ChartTileProps) => {
const [timeframe, setTimeframe] = useState<TimeframeOption>(timeframeInitialValue || TimeframeOption.ALL);

useEffect(() => {
Expand All @@ -33,7 +45,7 @@ export const ChartTile = ({ children, title, description, disableFullscreen, met
}, [timeframe, onSelectTimeframe]);

return (
<FullscreenChartTile metadata={metadata} disabled={disableFullscreen}>
<FullscreenChartTile metadata={metadata} disabled={disableFullscreen} id={id}>
<ChartTileHeader title={title} description={description} toggle={toggle}>
{timeframeOptions && timeframe && (
<Box width={{ sm: '100%', lg: '50%', xl: '25%' }}>
Expand Down
23 changes: 9 additions & 14 deletions packages/app/src/components/cms/rich-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { ChevronRight, Download, External as ExternalLinkIcon } from '@corona-da
import { space } from '~/style/theme';
import { replaceVariablesInText } from '~/utils';
import React from 'react';
import { InlineText } from '../typography';

type ElementAlignment = 'start' | 'center' | 'end' | 'stretch';

Expand All @@ -34,22 +35,14 @@ export function RichContent({ contentWrapper, blocks, imageSizes, elementAlignme
const serializers = {
types: {
inlineBlock: (props: unknown) => {
assert(
PortableText.defaultSerializers.types?.inlineBlock,
`[${RichContent.name}] PortableText needs to provide a serializer for inlineBlock content`
);
assert(PortableText.defaultSerializers.types?.inlineBlock, `[${RichContent.name}] PortableText needs to provide a serializer for inlineBlock content`);
return <ContentWrapper>{PortableText.defaultSerializers.types.inlineBlock(props)}</ContentWrapper>;
},
block: (props: unknown) => {
assert(
PortableText.defaultSerializers.types?.block,
`[${RichContent.name}] PortableText needs to provide a serializer for block content`
);
assert(PortableText.defaultSerializers.types?.block, `[${RichContent.name}] PortableText needs to provide a serializer for block content`);
return <ContentWrapper>{PortableText.defaultSerializers.types.block(props)}</ContentWrapper>;
},
image: (props: { node: ImageBlock | RichContentImageBlock }) => (
<ContentImage contentWrapper={contentWrapper} sizes={imageSizes} {...props} />
),
image: (props: { node: ImageBlock | RichContentImageBlock }) => <ContentImage contentWrapper={contentWrapper} sizes={imageSizes} {...props} />,
inlineCollapsible: (props: { node: InlineCollapsibleList }) => {
if (!props.node.content.inlineBlockContent) return null;

Expand Down Expand Up @@ -86,13 +79,15 @@ export function RichContent({ contentWrapper, blocks, imageSizes, elementAlignme
return (
<>
{children.map((child, index) => (
<React.Fragment key={index}>
{child.includes('{{kpiValue}}') && variableValue ? replaceVariablesInText(child, { kpiValue: variableValue }) : child}
</React.Fragment>
<React.Fragment key={index}>{child.includes('{{kpiValue}}') && variableValue ? replaceVariablesInText(child, { kpiValue: variableValue }) : child}</React.Fragment>
))}
</>
);
},
u: (props: { children: string[] }) => {
const { children } = props;
return <InlineText className="underline">{children}</InlineText>;
},
},
};

Expand Down
24 changes: 14 additions & 10 deletions packages/app/src/components/collapsible/collapsible-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,21 @@ interface CollapsibleSectionProps extends BoxProps {
className?: string;
id?: string;
hideBorder?: boolean;
fontSize?: string;
textColor?: string;
borderColor?: string;
}

export const CollapsibleSection = ({ summary, children, id, hideBorder, textColor = colors.blue8, borderColor = colors.gray2, className }: CollapsibleSectionProps) => {
export const CollapsibleSection = ({
summary,
children,
id,
hideBorder,
textColor = colors.blue8,
fontSize = fontSizes[5],
borderColor = colors.gray2,
className,
}: CollapsibleSectionProps) => {
const section = useRef<HTMLElement>(null);

const collapsible = useCollapsible();
Expand Down Expand Up @@ -53,7 +63,7 @@ export const CollapsibleSection = ({ summary, children, id, hideBorder, textColo

return (
<Box as="section" borderTop={hideBorder ? undefined : `1px solid ${borderColor}`} id={id} ref={section} className={`${className} ${collapsible.isOpen ? 'open' : ''}`}>
<StyledSummary textColor={textColor} onClick={() => collapsible.toggle()}>
<Summary color={textColor} onClick={() => collapsible.toggle()} fontSize={fontSize}>
<Box width="100%" position="relative">
{summary}
{id && (
Expand All @@ -63,7 +73,7 @@ export const CollapsibleSection = ({ summary, children, id, hideBorder, textColo
)}
</Box>
{collapsible.button()}
</StyledSummary>
</Summary>
{collapsible.content(<Box paddingX={space[3]}>{children}</Box>)}
</Box>
);
Expand All @@ -85,16 +95,10 @@ const StyledAnchor = styled(Anchor)`
}
`;

interface SummaryProps {
textColor: string;
}

const StyledSummary = styled(Box)<SummaryProps>`
const Summary = styled(Box)`
align-items: center;
color: ${({ textColor }) => textColor};
cursor: pointer;
display: flex;
font-size: ${fontSizes[5]};
font-weight: ${fontWeights.bold};
justify-content: space-between;
padding: ${space[3]};
Expand Down
9 changes: 5 additions & 4 deletions packages/app/src/components/fullscreen-chart-tile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ import { Modal } from './modal';

interface FullscreenChartTileProps {
children: React.ReactNode;
metadata?: MetadataProps;
disabled?: boolean;
id?: string;
metadata?: MetadataProps;
}

export function FullscreenChartTile({ children, metadata, disabled }: FullscreenChartTileProps) {
export const FullscreenChartTile = ({ children, disabled, id, metadata }: FullscreenChartTileProps) => {
const [isFullscreen, setIsFullscreen] = useState(false);
const wasFullscreen = usePrevious(isFullscreen);
const breakpoints = useBreakpoints();
Expand All @@ -36,7 +37,7 @@ export function FullscreenChartTile({ children, metadata, disabled }: Fullscreen
const label = replaceVariablesInText(isFullscreen ? commonTexts.common.modal_close : commonTexts.common.modal_open, { subject: commonTexts.common.grafiek_singular });

const tile = (
<Tile hasNoBorder={isFullscreen} height="100%">
<Tile hasNoBorder={isFullscreen} height="100%" id={id}>
<Box
paddingX={isFullscreen ? { _: space[3], sm: space[4] } : undefined}
paddingY={isFullscreen ? { _: space[2], sm: space[3] } : undefined}
Expand Down Expand Up @@ -73,7 +74,7 @@ export function FullscreenChartTile({ children, metadata, disabled }: Fullscreen
}

return <div>{tile}</div>;
}
};

interface StyledModalCloseButtonWrapperProps {
isFullscreen: boolean;
Expand Down
119 changes: 119 additions & 0 deletions packages/app/src/components/page-articles-tile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { colors } from '@corona-dashboard/common';
import { getImageProps } from '~/lib/sanity';
import { fontWeights, mediaQueries, radii, space } from '~/style/theme';
import { Box } from './base';
import { ChartTile } from './chart-tile';
import { SanityImage } from './cms/sanity-image';
import { Anchor, BoldText, Text } from './typography';
import { Link } from '~/utils/link';
import styled, { css } from 'styled-components';
import { PublicationDate } from './publication-date';
import { ChevronRight } from '@corona-dashboard/icons';
import { Article } from '~/types/cms';
import { useIntl } from '~/intl';

interface PageArticlesTileProps {
articles: Article[];
title: string;
}

// TODO: this should be moved to the /articles/ directory, as picked up in COR-1601
export const PageArticlesTile = ({ articles, title }: PageArticlesTileProps) => {
const { commonTexts } = useIntl();

return (
<ChartTile title={title ?? commonTexts.article_list.title} disableFullscreen>
<Grid>
{articles.map((article, index) => (
<Link passHref href={`/artikelen/${article.slug.current}`} key={index}>
<ArticleCard>
<ArticleCardHeader>
<ArticleImage {...getImageProps(article.cover, {})} />

<Box display="grid">
<BoldText color={colors.black}>{article.title}</BoldText>
<Text color={colors.gray8}>
{/* TODO: this should be updated after COR-1601 implements publicationDate vs updateDate logic */}
{article.mainCategory && `${commonTexts.article_teaser.categories[article.mainCategory]} · `}
<PublicationDate date={article.publicationDate} />
</Text>
</Box>
</ArticleCardHeader>

<Box color={colors.black}>{article.summary}</Box>

<ArticleLink>
{commonTexts.article_teaser.read_more}
<ChevronRight />
</ArticleLink>
</ArticleCard>
</Link>
))}
</Grid>

<Link passHref href="/artikelen/">
<ArticlesLink>
{commonTexts.article_list.articles_page_link}
<ChevronRight />
</ArticlesLink>
</Link>
</ChartTile>
);
};

const Grid = styled(Box)`
display: grid;
gap: ${space[4]};
margin-bottom: ${space[3]};
@media ${mediaQueries.sm} {
grid-template-columns: repeat(2, 1fr);
}
`;

const ArticleCard = styled(Anchor)`
border-radius: ${radii[2]}px;
border: 1px solid ${colors.gray3};
display: grid;
gap: ${space[2]};
height: 100%;
padding: ${space[3]};
`;

const ArticleCardHeader = styled(Box)`
align-items: center;
display: flex;
gap: ${space[3]};
`;

const ArticleImage = styled(SanityImage)`
object-fit: cover;
flex-shrink: 0;
img {
border-radius: ${radii[2]}px;
height: 48px;
width: 48px;
}
`;

const linkStyles = css`
color: ${colors.blue8};
cursor: pointer;
svg {
height: 10px;
margin-left: ${space[1]};
width: 10px;
}
`;

const ArticleLink = styled(BoldText)`
${linkStyles}
`;

const ArticlesLink = styled(Anchor)`
${linkStyles}
font-weight: ${fontWeights.bold};
`;
36 changes: 36 additions & 0 deletions packages/app/src/components/page-faq-tile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { colors } from '@corona-dashboard/common';
import { useIntl } from '~/intl';
import { fontSizes, space } from '~/style/theme';
import { FAQuestionAndAnswer } from '~/types/cms';
import { Box } from './base/box';
import { ChartTile } from './chart-tile';
import { RichContent } from './cms/rich-content';
import { CollapsibleSection } from './collapsible';
import styled from 'styled-components';

interface PageFaqTileProps {
questions: FAQuestionAndAnswer[];
title: string;
}

export const PageFaqTile = ({ questions, title }: PageFaqTileProps) => {
const { commonTexts } = useIntl();

return (
<ChartTile title={title ?? commonTexts.faq.title} id="veelgestelde-vragen" disableFullscreen>
{questions.map((question, index) => (
<StyledCollapsibleSection key={index} summary={question.title} textColor={colors.black} fontSize={fontSizes[3]} isLast={index + 1 === questions.length}>
{question.content && (
<Box paddingBottom={space[3]}>
<RichContent blocks={question.content} />
</Box>
)}
</StyledCollapsibleSection>
))}
</ChartTile>
);
};

const StyledCollapsibleSection = styled(CollapsibleSection)<{ isLast: boolean }>`
border-bottom: ${({ isLast }) => (isLast ? `1px solid ${colors.gray2}` : undefined)};
`;
Loading

0 comments on commit 25a0666

Please sign in to comment.