This repository has been archived by the owner on Nov 4, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature/COR-1516-404-page-improvements-multiple-pages (#4736)
* feat(404-pages): Remove hardcoded article redirects * feat(404-pages): Enable configuration of 404 pages in Sanity. * feat(404-pages): Adjust schemas. * feat(404-pages): Wrap breadcrumbs with a guard. * feat(404-pages): Middleware redirect logic with parameters for each 404 page. * feat(404-pages): Add new icons. Adjust KpiIconInput component so that it closes upon selecting an icon. * feat(404-pages): Extract query to its own file and adjust not found schema. * feat(404-pages): Update SVG fill * feat(404-pages): Adjust query and schema. Delete old 404 page * feat(404-pages): WIP new 404 pages. * feat(404-pages): Finalize 404 pages. * feat(404-pages): Fine tune implementation. * feat(404-pages): PR Feedback, first round. * feat(404-pages): PR Feedback, second round. * feat(404-pages): Non middleware solution. * feat(404-pages): Refactor. * feat(404-pages): PR feedback and a few tweaks. * feat(404 pages): Refactor not found page for general, landelijk, and articles. * feat(404 pages): Change fallback back to blocking so that EN locale pages are built at runtime. * feat(404 pages): Create dedicated GM 404 page with new rewrites. * feat(404 pages): Formatting. * feat(404 pages): Finalize rewrites for all Gemeente scenarios. * feat(404 pages): Refactor and update utils typing. * feat(404-pages): PR feedback - round 1 * feat(404-pages): PR feedback - round 2. --------- Co-authored-by: VWSCoronaDashboard28 <[email protected]>
- Loading branch information
Showing
10 changed files
with
349 additions
and
231 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { getClient } from '~/lib/sanity'; | ||
import { getNotFoundPageQuery } from '~/queries/get-not-found-page-query'; | ||
import { NotFoundPageConfiguration } from './types'; | ||
|
||
const determinePageTypeFromUrl = (url: string) => { | ||
const levelsToPageTypeMapping: { [key: string]: string } = { landelijk: 'nl', gemeente: 'gm', artikelen: 'article', general: 'general' }; | ||
const pageType = levelsToPageTypeMapping[Object.keys(levelsToPageTypeMapping).find((key) => url.includes(`/${key}`)) ?? 'general']; | ||
|
||
return pageType; | ||
}; | ||
|
||
/** | ||
* @function getNotFoundPageData | ||
* @description Fetches the data for a given page type from Sanity and adds additional properties to the page configuration. | ||
* @param url - The current request URL. | ||
* @param locale - The selected locale. | ||
* @returns {Promise<NotFoundPageConfiguration> | null} - Returns the page configuration if found, otherwise null. | ||
*/ | ||
export const getNotFoundPageData = async (url: string, locale: string) => { | ||
const pageType = url ? determinePageTypeFromUrl(url) : 'general'; | ||
const query = getNotFoundPageQuery(locale, pageType); | ||
const client = await getClient(); | ||
const notFoundPageConfiguration: NotFoundPageConfiguration = await client.fetch(query); | ||
|
||
if (!notFoundPageConfiguration) return null; | ||
|
||
notFoundPageConfiguration.isGmPage = pageType === 'gm'; | ||
notFoundPageConfiguration.isGeneralPage = pageType === 'general'; | ||
|
||
return notFoundPageConfiguration; | ||
}; |
39 changes: 39 additions & 0 deletions
39
packages/app/src/components/not-found-pages/not-found-link.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { colors } from '@corona-dashboard/common'; | ||
import { ChevronRight } from '@corona-dashboard/icons'; | ||
import styled from 'styled-components'; | ||
import { space } from '~/style/theme'; | ||
import { getFilenameToIconName } from '~/utils/get-filename-to-icon-name'; | ||
import { Box } from '../base/box'; | ||
import DynamicIcon, { IconName } from '../get-icon-by-name'; | ||
import { Anchor } from '../typography'; | ||
import { NotFoundLinkProps } from './types'; | ||
|
||
export const NotFoundLink = ({ link: { linkUrl, linkLabel, linkIcon }, hasChevron, isCTA, ...restProps }: NotFoundLinkProps) => { | ||
const iconNameFromFileName = linkIcon ? (getFilenameToIconName(linkIcon) as IconName) : null; | ||
const icon = iconNameFromFileName ? <DynamicIcon color={colors.blue8} name={iconNameFromFileName} height="30px" width="30px" /> : undefined; | ||
|
||
return ( | ||
<Box {...restProps}> | ||
{icon} | ||
|
||
<StyledAnchor hasIcon={!!icon} href={linkUrl} isCTA={isCTA} underline={!isCTA}> | ||
{linkLabel} | ||
</StyledAnchor> | ||
|
||
{hasChevron && <ChevronRight color={colors.blue8} height="10px" />} | ||
</Box> | ||
); | ||
}; | ||
|
||
interface StyledAnchorProps { | ||
hasIcon: boolean; | ||
isCTA: boolean | undefined; | ||
} | ||
|
||
const StyledAnchor = styled(Anchor)<StyledAnchorProps>` | ||
margin-inline: ${({ hasIcon, isCTA }) => (hasIcon || isCTA ? space[2] : !hasIcon ? `0 ${space[2]}` : 0)}; | ||
&:hover { | ||
text-decoration: none; | ||
} | ||
`; |
17 changes: 17 additions & 0 deletions
17
packages/app/src/components/not-found-pages/not-found-page-fallback.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { Content } from '~/domain/layout/content'; | ||
import { Layout } from '~/domain/layout/layout'; | ||
import { useIntl } from '~/intl'; | ||
import { Heading, Text } from '../typography'; | ||
|
||
export const NotFoundFallback = ({ lastGenerated }: { lastGenerated: string }) => { | ||
const { commonTexts } = useIntl(); | ||
|
||
return ( | ||
<Layout {...commonTexts.notfound_metadata} lastGenerated={lastGenerated}> | ||
<Content> | ||
<Heading level={1}>{commonTexts.notfound_titel.text}</Heading> | ||
<Text>{commonTexts.notfound_beschrijving.text}</Text> | ||
</Content> | ||
</Layout> | ||
); | ||
}; |
108 changes: 108 additions & 0 deletions
108
packages/app/src/components/not-found-pages/not-found-page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import { colors } from '@corona-dashboard/common'; | ||
import styled from 'styled-components'; | ||
import { GmComboBox } from '~/domain/layout/components/gm-combo-box'; | ||
import { Layout } from '~/domain/layout/layout'; | ||
import { useIntl } from '~/intl'; | ||
import { getImageProps } from '~/lib/sanity'; | ||
import { mediaQueries, radii, sizes, space } from '~/style/theme'; | ||
import { Box } from '../base/box'; | ||
import { RichContent } from '../cms/rich-content'; | ||
import { SanityImage } from '../cms/sanity-image'; | ||
import { Heading } from '../typography'; | ||
import { NotFoundLink } from './not-found-link'; | ||
import { NotFoundProps } from './types'; | ||
|
||
export const NotFoundPage = ({ lastGenerated, notFoundPageConfiguration }: NotFoundProps) => { | ||
const { | ||
commonTexts: { notfound_metadata }, | ||
} = useIntl(); | ||
const { title, description, isGmPage = true, isGeneralPage = false, image, links = undefined, cta = undefined } = notFoundPageConfiguration; | ||
|
||
return ( | ||
<Layout {...notfound_metadata} lastGenerated={lastGenerated}> | ||
<NotFoundLayout> | ||
<Box minWidth="50%" display="flex" flexDirection="column"> | ||
<Box spacing={4} marginBottom={space[4]} maxWidth="400px" order={1}> | ||
<Heading level={1}>{title}</Heading> | ||
<RichContent blocks={description} elementAlignment="start" /> | ||
</Box> | ||
|
||
{isGmPage && ( | ||
// Compensating for padding on the combo-box element using negative margins. | ||
<Box margin={`-${space[4]} -${space[3]} 0`} maxWidth="400px" order={2}> | ||
<GmComboBox selectedGmCode="" shouldFocusInput={false} /> | ||
</Box> | ||
)} | ||
|
||
{links && ( | ||
<Box order={isGeneralPage ? 3 : 4}> | ||
{links.map((link, index) => ( | ||
<NotFoundLink | ||
alignItems="center" | ||
display="flex" | ||
hasChevron | ||
key={link.id} | ||
link={link} | ||
marginBottom={isGeneralPage ? (index === links.length - 1 ? space[4] : space[2]) : undefined} | ||
/> | ||
))} | ||
</Box> | ||
)} | ||
|
||
{cta && Object.values(cta).some((item) => item !== null) && ( | ||
<NotFoundCTA | ||
alignItems="center" | ||
border={`1px solid ${colors.blue8}`} | ||
borderRadius={`${radii[1]}px`} | ||
className="not-found-content-cta" | ||
display="inline-flex" | ||
isCTA | ||
link={{ linkUrl: cta.ctaLink, linkLabel: cta.ctaLabel, linkIcon: cta.ctaIcon || '' }} | ||
marginBottom={isGeneralPage ? undefined : space[4]} | ||
maxWidth="fit-content" | ||
order={isGeneralPage ? 4 : 3} | ||
padding={`${space[1]} ${space[2]}`} | ||
/> | ||
)} | ||
</Box> | ||
|
||
<Box display="flex" justifyContent={{ _: 'center', sm: 'flex-start' }} maxHeight="520px"> | ||
<SanityImage {...getImageProps(image, {})} /> | ||
</Box> | ||
</NotFoundLayout> | ||
</Layout> | ||
); | ||
}; | ||
|
||
const NotFoundCTA = NotFoundLink; // Renaming for the sake of readability. | ||
|
||
const NotFoundLayout = styled.div` | ||
display: flex; | ||
flex-direction: column; | ||
gap: ${space[4]}; | ||
justify-content: space-between; | ||
margin: ${space[5]} auto; | ||
max-width: ${sizes.maxWidth}px; | ||
padding: 0 ${space[3]}; | ||
@media ${mediaQueries.sm} { | ||
flex-direction: row; | ||
padding: 0 ${space[4]}; | ||
} | ||
@media ${mediaQueries.md} { | ||
align-items: flex-start; | ||
} | ||
.not-found-content-cta { | ||
transition: all 0.2s ease-in-out; | ||
svg rect { | ||
fill: ${colors.transparent}; | ||
} | ||
&:hover { | ||
background-color: ${colors.gray1}; | ||
} | ||
} | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { PortableTextEntry } from '@sanity/block-content-to-react'; | ||
import { ImageBlock } from '~/types/cms'; | ||
|
||
type Link = { | ||
id?: string; | ||
linkIcon?: string; | ||
linkLabel: string; | ||
linkUrl: string; | ||
}; | ||
|
||
export type NotFoundPageConfiguration = { | ||
description: PortableTextEntry[]; | ||
image: ImageBlock; | ||
isGeneralPage: boolean; | ||
isGmPage: boolean; | ||
title: string; | ||
cta?: { | ||
ctaIcon?: string; | ||
ctaLabel: string; | ||
ctaLink: string; | ||
}; | ||
links?: Link[]; | ||
}; | ||
|
||
export interface NotFoundProps { | ||
lastGenerated: string; | ||
notFoundPageConfiguration: NotFoundPageConfiguration; | ||
} | ||
|
||
export interface NotFoundLinkProps { | ||
alignItems: string; | ||
display: string; | ||
link: Link; | ||
border?: string; | ||
borderRadius?: string; | ||
className?: string; | ||
hasChevron?: boolean; | ||
isCTA?: boolean; | ||
marginBottom?: string; | ||
maxWidth?: string; | ||
order?: number; | ||
padding?: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.