diff --git a/packages/app/src/domain/variants/static-props/get-variant-order-colors.ts b/packages/app/src/domain/variants/static-props/get-variant-order-colors.ts
index f37edb5821..d899e624a9 100644
--- a/packages/app/src/domain/variants/static-props/get-variant-order-colors.ts
+++ b/packages/app/src/domain/variants/static-props/get-variant-order-colors.ts
@@ -1,6 +1,6 @@
import { NlVariants, colors } from '@corona-dashboard/common';
import { isDefined } from 'ts-is-present';
-import { VariantCode } from './'
+import { VariantCode } from './';
export type ColorMatch = {
variant: VariantCode;
@@ -12,29 +12,23 @@ const getColorForVariant = (variantCode: VariantCode, index: number): string =>
if (variantCode === 'other_graph') return colors.gray5;
return colors.variants.colorList[index];
-}
+};
-export function getVariantOrderColors(
- variants: NlVariants | undefined
-): ColorMatch[] {
+export const getVariantOrderColors = (variants: NlVariants | undefined): ColorMatch[] => {
if (!isDefined(variants) || !isDefined(variants.values)) {
return [];
}
const colorOrder = variants.values
- .filter(
- (variant) =>
- variant.last_value.is_variant_of_concern ||
- variant.last_value.has_historical_significance
- )
- .sort((a, b) => a.last_value.order - b.last_value.order)
+ .filter((variant) => variant.last_value.is_variant_of_concern || variant.last_value.has_historical_significance)
+ .sort((a, b) => (a.variant_code.includes('other') || b.variant_code.includes('other') ? -1 : a.last_value.order - b.last_value.order))
.map((variant, index) => {
- const variantColor = getColorForVariant(variant.variant_code, index)
+ const variantColor = getColorForVariant(variant.variant_code, index);
return {
variant: variant.variant_code,
- color: variantColor
+ color: variantColor,
};
- });
+ });
return colorOrder;
-}
+};
diff --git a/packages/app/src/domain/variants/variants-stacked-area-tile/variants-stacked-area-tile.tsx b/packages/app/src/domain/variants/variants-stacked-area-tile/variants-stacked-area-tile.tsx
index 6eff3614c0..b95a3f1680 100644
--- a/packages/app/src/domain/variants/variants-stacked-area-tile/variants-stacked-area-tile.tsx
+++ b/packages/app/src/domain/variants/variants-stacked-area-tile/variants-stacked-area-tile.tsx
@@ -1,11 +1,5 @@
-import {
- colors,
- TimeframeOption,
- TimeframeOptionsList,
-} from '@corona-dashboard/common';
-import css from '@styled-system/css';
-import { ReactNode, useMemo, useState } from 'react';
-import styled from 'styled-components';
+import { colors, TimeframeOption, TimeframeOptionsList } from '@corona-dashboard/common';
+import { useMemo, useState } from 'react';
import { isDefined, isPresent } from 'ts-is-present';
import { Spacer } from '~/components/base';
import { ChartTile } from '~/components/chart-tile';
@@ -20,95 +14,34 @@ import { SiteText } from '~/locale';
import { useList } from '~/utils/use-list';
import { ColorMatch, VariantCode } from '~/domain/variants/static-props';
import { useUnreliableDataAnnotations } from './logic/use-unreliable-data-annotations';
+import { space } from '~/style/theme';
type VariantsStackedAreaTileText = {
variantCodes: SiteText['common']['variant_codes'];
} & SiteText['pages']['variants_page']['nl']['varianten_over_tijd_grafiek'];
-type VariantsStackedAreaTileProps = {
- text: VariantsStackedAreaTileText;
- values?: VariantChartValue[] | null;
- variantColors: ColorMatch[];
- metadata: MetadataProps;
- children?: ReactNode;
- noDataMessage?: ReactNode;
-};
-
-export function VariantsStackedAreaTile({
- values,
- variantColors,
- metadata,
- children = null,
- noDataMessage = '',
- text,
-}: VariantsStackedAreaTileProps) {
- if (!isPresent(values)) {
- return (
-
- {children}
- {noDataMessage}
-
- );
- }
- return (
-
- {children}
-
- );
-}
-
const alwaysEnabled: (keyof VariantChartValue)[] = [];
-type VariantStackedAreaTileWithDataProps = {
+interface VariantsStackedAreaTileProps {
text: VariantsStackedAreaTileText;
values: VariantChartValue[];
metadata: MetadataProps;
variantColors: ColorMatch[];
- children?: ReactNode;
-};
+}
-function VariantStackedAreaTileWithData({
- text,
- values,
- variantColors,
- metadata,
- children = null,
-}: VariantStackedAreaTileWithDataProps) {
- const [variantTimeframe, setVariantTimeframe] = useState(
- TimeframeOption.ALL
- );
+export const VariantsStackedAreaTile = ({ text, values, variantColors, metadata }: VariantsStackedAreaTileProps) => {
+ const [variantTimeframe, setVariantTimeframe] = useState(TimeframeOption.THREE_MONTHS);
- const { list, toggle, clear } =
- useList(alwaysEnabled);
+ const { list, toggle, clear } = useList(alwaysEnabled);
- const [seriesConfig, otherConfig, selectOptions] = useSeriesConfig(
- text,
- values,
- variantColors
- );
+ const [seriesConfig, otherConfig, selectOptions] = useSeriesConfig(text, values, variantColors);
- const filteredConfig = useFilteredSeriesConfig(
- seriesConfig,
- otherConfig,
- list
- );
+ const filteredConfig = useFilteredSeriesConfig(seriesConfig, otherConfig, list);
/* Static legend contains only the inaccurate item */
const staticLegendItems: LegendItem[] = [];
- const timespanAnnotations = useUnreliableDataAnnotations(
- values,
- text.lagere_betrouwbaarheid
- );
+ const timespanAnnotations = useUnreliableDataAnnotations(values, text.lagere_betrouwbaarheid);
if (timespanAnnotations.length) {
staticLegendItems.push({
@@ -124,149 +57,104 @@ function VariantStackedAreaTileWithData({
description={text.toelichting}
metadata={metadata}
timeframeOptions={TimeframeOptionsList}
- timeframeInitialValue={TimeframeOption.SIX_MONTHS}
+ timeframeInitialValue={TimeframeOption.THREE_MONTHS}
onSelectTimeframe={setVariantTimeframe}
>
- <>
- {children}
- {children && }
-
-
- {
- /**
- * Filter out zero values in value object, so it will be invisible in the tooltip.
- * When a selection has been made, the zero values will be shown in the tooltip.
- */
- const metricAmount = context.config.length;
- const totalMetricAmount = seriesConfig.length;
- const hasSelectedMetrics = metricAmount !== totalMetricAmount;
-
- const filteredValues = Object.fromEntries(
- Object.entries(context.value).filter(([key, value]) =>
- key.includes('percentage')
- ? value !== 0 && isPresent(value) && !isNaN(Number(value))
- : value
- )
- ) as VariantChartValue;
-
- const reorderContext = {
- ...context,
- config: [
- ...context.config.filter(
- (value) =>
- !hasMetricProperty(value) ||
- filteredValues[value.metricProperty] ||
- hasSelectedMetrics
- ),
- context.config.find(
- (value) =>
- hasMetricProperty(value) &&
- value.metricProperty === 'other_graph_percentage'
- ),
- ].filter(isDefined),
- value: !hasSelectedMetrics ? filteredValues : context.value,
- };
-
- const percentageValuesAmount = Object.keys(
- reorderContext.value
- ).filter((key) => key.includes('percentage')).length;
-
- const hasTwoColumns = !hasSelectedMetrics
- ? percentageValuesAmount > 4
- : metricAmount > 4;
-
- return (
-
- );
- }}
- numGridLines={0}
- tickValues={[0, 25, 50, 75, 100]}
- />
-
- >
+
+
+ {
+ /**
+ * Filter out zero values in value object, so it will be invisible in the tooltip.
+ * When a selection has been made, the zero values will be shown in the tooltip.
+ */
+ const metricAmount = context.config.length;
+ const totalMetricAmount = seriesConfig.length;
+ const hasSelectedMetrics = metricAmount !== totalMetricAmount;
+
+ const filteredValues = Object.fromEntries(
+ Object.entries(context.value).filter(([key, value]) => (key.includes('percentage') ? value !== 0 && isPresent(value) && !isNaN(Number(value)) : value))
+ ) as VariantChartValue;
+
+ const reorderContext = {
+ ...context,
+ config: [
+ ...context.config.filter((value) => !hasMetricProperty(value) || filteredValues[value.metricProperty] || hasSelectedMetrics),
+ context.config.find((value) => hasMetricProperty(value) && value.metricProperty === 'other_graph_percentage'),
+ ].filter(isDefined),
+ value: !hasSelectedMetrics ? filteredValues : context.value,
+ };
+
+ const percentageValuesAmount = Object.keys(reorderContext.value).filter((key) => key.includes('percentage')).length;
+
+ const hasTwoColumns = !hasSelectedMetrics ? percentageValuesAmount > 4 : metricAmount > 4;
+
+ return ;
+ }}
+ numGridLines={0}
+ tickValues={[0, 25, 50, 75, 100]}
+ />
+
);
-}
+};
-function hasMetricProperty(config: any): config is { metricProperty: string } {
+const hasMetricProperty = (config: any): config is { metricProperty: string } => {
return 'metricProperty' in config;
-}
+};
-function useFilteredSeriesConfig(
+const useFilteredSeriesConfig = (
seriesConfig: GappedAreaSeriesDefinition[],
otherConfig: GappedAreaSeriesDefinition,
compareList: (keyof VariantChartValue)[]
-) {
+) => {
return useMemo(() => {
return [otherConfig, ...seriesConfig].filter(
- (item) =>
- item.metricProperty !== 'other_graph_percentage' &&
- (compareList.includes(item.metricProperty) ||
- compareList.length === alwaysEnabled.length)
+ (item) => item.metricProperty !== 'other_graph_percentage' && (compareList.includes(item.metricProperty) || compareList.length === alwaysEnabled.length)
);
}, [seriesConfig, otherConfig, compareList]);
-}
+};
-function useSeriesConfig(
- text: VariantsStackedAreaTileText,
- values: VariantChartValue[],
- variantColors: ColorMatch[]
-) {
+const useSeriesConfig = (text: VariantsStackedAreaTileText, values: VariantChartValue[], variantColors: ColorMatch[]) => {
return useMemo(() => {
const baseVariantsFiltered = values
.flatMap((x) => Object.keys(x))
.filter((x, index, array) => array.indexOf(x) === index) // de-dupe
- .filter(
- (x) => x.endsWith('_percentage') && x !== 'other_graph_percentage'
- )
+ .filter((x) => x.endsWith('_percentage') && x !== 'other_graph_percentage')
.reverse(); // Reverse to be in an alphabetical order
/* Enrich config with dynamic data / locale */
- const seriesConfig: GappedAreaSeriesDefinition[] =
- baseVariantsFiltered.map((variantKey) => {
- const variantCodeFragments = variantKey.split('_');
- variantCodeFragments.pop();
- const variantCode = variantCodeFragments.join('_') as VariantCode;
-
- const color =
- variantColors.find(
- (variantColors) => variantColors.variant === variantCode
- )?.color || colors.gray5;
-
- return {
- type: 'gapped-area',
- metricProperty: variantKey as keyof VariantChartValue,
- color,
- label: text.variantCodes[variantCode],
- shape: 'gapped-area',
- strokeWidth: 2,
- fillOpacity: 0.2,
- mixBlendMode: 'multiply',
- };
- });
+ const seriesConfig: GappedAreaSeriesDefinition[] = baseVariantsFiltered.map((variantKey) => {
+ const variantCodeFragments = variantKey.split('_');
+ variantCodeFragments.pop();
+ const variantCode = variantCodeFragments.join('_') as VariantCode;
+
+ const color = variantColors.find((variantColors) => variantColors.variant === variantCode)?.color || colors.gray5;
+
+ return {
+ type: 'gapped-area',
+ metricProperty: variantKey as keyof VariantChartValue,
+ color,
+ label: text.variantCodes[variantCode],
+ shape: 'gapped-area',
+ strokeWidth: 2,
+ fillOpacity: 0.2,
+ mixBlendMode: 'multiply',
+ };
+ });
const otherConfig = {
type: 'gapped-area',
@@ -282,21 +170,5 @@ function useSeriesConfig(
const selectOptions = [...seriesConfig];
return [seriesConfig, otherConfig, selectOptions] as const;
- }, [
- values,
- text.tooltip_labels.other_percentage,
- text.variantCodes,
- variantColors,
- ]);
-}
-
-const NoDataBox = styled.div(
- css({
- width: '100%',
- display: 'flex',
- height: '8em',
- color: 'gray5',
- justifyContent: 'center',
- alignItems: 'center',
- })
-);
+ }, [values, text.tooltip_labels.other_percentage, text.variantCodes, variantColors]);
+};
diff --git a/packages/app/src/pages/landelijk/varianten.tsx b/packages/app/src/pages/landelijk/varianten.tsx
index 498544b8fd..8ebced13cd 100644
--- a/packages/app/src/pages/landelijk/varianten.tsx
+++ b/packages/app/src/pages/landelijk/varianten.tsx
@@ -4,30 +4,14 @@ import { PageInformationBlock } from '~/components/page-information-block';
import { TileList } from '~/components/tile-list';
import { Layout } from '~/domain/layout/layout';
import { NlLayout } from '~/domain/layout/nl-layout';
-import {
- getVariantChartData,
- getVariantOrderColors,
- getVariantTableData,
-} from '~/domain/variants/static-props';
+import { getVariantChartData, getVariantOrderColors, getVariantTableData } from '~/domain/variants/static-props';
import { VariantsStackedAreaTile } from '~/domain/variants/variants-stacked-area-tile';
import { VariantsTableTile } from '~/domain/variants/variants-table-tile';
import { useIntl } from '~/intl';
import { Languages, SiteText } from '~/locale';
-import {
- getArticleParts,
- getLinkParts,
- getPagePartsQuery,
-} from '~/queries/get-page-parts-query';
-import {
- createGetStaticProps,
- StaticProps,
-} from '~/static-props/create-get-static-props';
-import {
- createGetContent,
- getLastGeneratedDate,
- selectNlData,
- getLokalizeTexts,
-} from '~/static-props/get-data';
+import { getArticleParts, getLinkParts, getPagePartsQuery } from '~/queries/get-page-parts-query';
+import { createGetStaticProps, StaticProps } from '~/static-props/create-get-static-props';
+import { createGetContent, getLastGeneratedDate, selectNlData, getLokalizeTexts } from '~/static-props/get-data';
import { ArticleParts, LinkParts, PagePartQueryResult } from '~/types/cms';
import { getLastInsertionDateOfPage } from '~/utils/get-last-insertion-date-of-page';
import { useDynamicLokalizeTexts } from '~/utils/cms/use-dynamic-lokalize-texts';
@@ -43,8 +27,7 @@ const selectLokalizeTexts = (siteText: SiteText) => ({
type LokalizeTexts = ReturnType;
export const getStaticProps = createGetStaticProps(
- ({ locale }: { locale: keyof Languages }) =>
- getLokalizeTexts(selectLokalizeTexts, locale),
+ ({ locale }: { locale: keyof Languages }) => getLokalizeTexts(selectLokalizeTexts, locale),
selectNlData('variants', 'named_difference'),
getLastGeneratedDate,
() => {
@@ -57,19 +40,13 @@ export const getStaticProps = createGetStaticProps(
const variantColors = getVariantOrderColors(variants);
return {
- ...getVariantTableData(
- variants,
- data.selectedNlData.named_difference,
- variantColors
- ),
+ ...getVariantTableData(variants, data.selectedNlData.named_difference, variantColors),
...getVariantChartData(variants),
variantColors,
};
},
async (context: GetStaticPropsContext) => {
- const { content } = await createGetContent<
- PagePartQueryResult
- >(() => getPagePartsQuery('variants_page'))(context);
+ const { content } = await createGetContent>(() => getPagePartsQuery('variants_page'))(context);
return {
content: {
@@ -80,23 +57,11 @@ export const getStaticProps = createGetStaticProps(
}
);
-export default function CovidVariantenPage(
- props: StaticProps
-) {
- const {
- pageText,
- selectedNlData: data,
- lastGenerated,
- content,
- variantTable,
- variantChart,
- variantColors,
- dates,
- } = props;
+export default function CovidVariantenPage(props: StaticProps) {
+ const { pageText, selectedNlData: data, lastGenerated, content, variantTable, variantChart, variantColors, dates } = props;
const { commonTexts } = useIntl();
- const { metadataTexts, textNl, textShared } =
- useDynamicLokalizeTexts(pageText, selectLokalizeTexts);
+ const { metadataTexts, textNl, textShared } = useDynamicLokalizeTexts(pageText, selectLokalizeTexts);
const metadata = {
...metadataTexts,
@@ -111,9 +76,7 @@ export default function CovidVariantenPage(
}
@@ -132,19 +95,21 @@ export default function CovidVariantenPage(
articles={content.articles}
/>
-
+ {variantChart && (
+
+ )}