🚸(app-impress) footer legales pages

- Add legales pages.
- Add links to the footer for the new pages.

Legales pages are based from
https://lasuite.numerique.gouv.fr/
This commit is contained in:
Anthony LC
2024-05-14 11:46:13 +02:00
committed by Anthony LC
parent 88d6d8977c
commit c1dd34512b
8 changed files with 426 additions and 8 deletions

View File

@@ -33,10 +33,44 @@ test.describe('Footer', () => {
footer.getByRole('link', { name: 'data.gouv.fr' }),
).toBeVisible();
await expect(
footer.getByRole('link', { name: 'Legal Notice' }),
).toBeVisible();
await expect(
footer.getByRole('link', { name: 'Personal data and cookies' }),
).toBeVisible();
await expect(
footer.getByRole('link', { name: 'Accessibility' }),
).toBeVisible();
await expect(
footer.getByText(
'Unless otherwise stated, all content on this site is under licence',
),
).toBeVisible();
});
const legalPages = [
{ name: 'Legal Notice', url: '/legal-notice/' },
{ name: 'Personal data and cookies', url: '/personal-data-cookies/' },
{ name: 'Accessibility', url: '/accessibility/' },
];
for (const { name, url } of legalPages) {
test(`checks ${name} page`, async ({ page }) => {
const footer = page.locator('footer').first();
await footer.getByRole('link', { name }).click();
await expect(
page
.getByRole('heading', {
name,
})
.first(),
).toBeVisible();
await expect(page).toHaveURL(url);
});
}
});

View File

@@ -37,6 +37,7 @@ export const Footer = () => {
$gap="1.5rem"
$align="center"
$justify="space-between"
$css="flex-wrap: wrap;"
>
<Box>
<Box $align="center" $gap="6rem" $direction="row">
@@ -50,7 +51,6 @@ export const Footer = () => {
</Box>
<Box
$direction="row"
$justify="flex-end"
$css={`
column-gap: 1.5rem;
row-gap: .5rem;
@@ -93,6 +93,56 @@ export const Footer = () => {
))}
</Box>
</Box>
<Box
$direction="row"
$margin={{ top: 'big' }}
$padding={{ top: 'tiny' }}
$css={`
flex-wrap: wrap;
border-top: 1px solid var(--c--theme--colors--greyscale-200);
column-gap: 1rem;
row-gap: .5rem;
`}
>
{[
{
label: t('Legal Notice'),
href: '/legal-notice',
},
{
label: t('Personal data and cookies'),
href: '/personal-data-cookies',
},
{
label: t('Accessibility'),
href: '/accessibility',
},
].map(({ label, href }) => (
<StyledLink
key={label}
href={href}
$css={`
padding-right: 1rem;
&:not(:last-child) {
box-shadow: inset -1px 0px 0px 0px var(--c--theme--colors--greyscale-200);
}
`}
>
<Text
$variation="600"
$size="m"
$transition="box-shadow 0.3s"
$css={`
&:hover {
box-shadow: 0px 2px 0 0 var(--c--theme--colors--greyscale-text);
}
`}
>
{label}
</Text>
</StyledLink>
))}
</Box>
<Text
as="p"
$size="m"

View File

@@ -5,7 +5,7 @@ import styled from 'styled-components';
import { default as IconGouv } from '@/assets/icons/icon-gouv.svg?url';
import { default as IconMarianne } from '@/assets/icons/icon-marianne.svg?url';
import { Box, Text } from '@/components/';
import { Box, StyledLink, Text } from '@/components/';
import { LanguagePicker } from '../language/';
@@ -53,12 +53,14 @@ export const Header = () => {
src={IconGouv}
alt={t('Freedom Equality Fraternity Logo')}
/>
<Box $align="center" $gap="1rem" $direction="row">
<Image priority src={IconImpress} alt={t('Impress Logo')} />
<Text $margin="none" as="h2" $theme="primary">
{t('Impress')}
</Text>
</Box>
<StyledLink href="/">
<Box $align="center" $gap="1rem" $direction="row">
<Image priority src={IconImpress} alt={t('Impress Logo')} />
<Text $margin="none" as="h2" $theme="primary">
{t('Impress')}
</Text>
</Box>
</StyledLink>
</Box>
</Box>
<Box

View File

@@ -0,0 +1,17 @@
import { PropsWithChildren } from 'react';
import { Box } from '@/components';
import { Footer } from '@/features/footer/Footer';
import { Header } from '@/features/header';
export function PageLayout({ children }: PropsWithChildren) {
return (
<Box>
<Header />
<Box as="main" $width="100%">
{children}
</Box>
<Footer />
</Box>
);
}

View File

@@ -1,2 +1,3 @@
export * from './MainLayout';
export * from './PadLayout';
export * from './PageLayout';

View File

@@ -0,0 +1,137 @@
import { ReactElement } from 'react';
import { useTranslation } from 'react-i18next';
import { Box, Text, TextStyled } from '@/components';
import { useCunninghamTheme } from '@/cunningham';
import { PageLayout } from '@/layouts';
import { NextPageWithLayout } from '@/types/next';
const Page: NextPageWithLayout = () => {
const { t } = useTranslation();
const { colorsTokens } = useCunninghamTheme();
return (
<Box>
<Box
as="h1"
$background={colorsTokens()['primary-100']}
$margin="none"
$padding="large"
>
{t('Accessibility')}
</Box>
<Box $padding={{ horizontal: 'large', vertical: 'big' }}>
<Text as="p" $display="inline">
<Text $weight="bold" $display="inline">
La Suite numérique
</Text>{' '}
s&apos;engage à rendre ses services numériques accessibles,
conformément à l&apos;article 47 de la loi n° 2005-102 du 11 février
2005.
</Text>
<Text as="h2" $margin={{ bottom: 'xtiny' }}>
Déclaration d&apos;accessibilité
</Text>
<Text as="p">Établie le 20 décembre 2023.</Text>
<Text as="p" $display="inline">
Cette déclaration d&apos;accessibilité s&apos;applique au site{' '}
<Text $weight="bold" $display="inline">
lasuite.numerique.gouv.fr
</Text>
.
</Text>
<Text as="h2" $margin={{ bottom: 'xtiny' }}>
État de conformité
</Text>
<Text as="p" $display="inline">
<Text $weight="bold" $display="inline">
lasuite.numerique.gouv.fr
</Text>{' '}
est non conforme avec le RGAA 4.1. Le site n&apos;a{' '}
<Text $weight="bold" $display="inline">
pas encore é audité.
</Text>
</Text>
<Text as="h2" $margin={{ bottom: 'xtiny' }}>
Amélioration et contact
</Text>
<Text as="p" $display="inline">
Si vous n&apos;arrivez pas à accéder à un contenu ou à un service,
vous pouvez contacter le responsable de lasuite.numerique.gouv.fr pour
être orienté vers une alternative accessible ou obtenir le contenu
sous une autre forme.
</Text>
<Text as="p" $display="inline">
<li>
E-mail :{' '}
<TextStyled
as="a"
href="mailto:lasuite@modernisation.gouv.fr"
$display="inline"
>
lasuite@modernisation.gouv.fr
</TextStyled>
</li>
<li>
Adresse :{' '}
<Text $weight="bold" $display="inline">
DINUM
</Text>
, 20 avenue de Ségur 75007 Paris
</li>
</Text>
<Text as="p" $display="inline">
Nous essayons de répondre dans les 2 jours ouvrés.
</Text>
<Text as="h2" $margin={{ bottom: 'xtiny' }}>
Voie de recours
</Text>
<Text as="p" $display="inline">
Cette procédure est à utiliser dans le cas suivant : vous avez signalé
au responsable du site internet un défaut d&apos;accessibilité qui
vous empêche d&apos;accéder à un contenu ou à un des services du
portail et vous n&apos;avez pas obtenu de réponse satisfaisante.
</Text>
<Text as="p" $display="inline" $margin={{ bottom: 'tiny' }}>
Vous pouvez :
</Text>
<Text as="p" $display="inline" $margin={{ top: 'tiny' }}>
<li>
Écrire un message au{' '}
<TextStyled
as="a"
href="https://formulaire.defenseurdesdroits.fr/formulaire_saisine/"
$display="inline"
>
Défenseur des droits
</TextStyled>
</li>
<li>
Contacter le délégué du{' '}
<TextStyled
as="a"
href="https://www.defenseurdesdroits.fr/carte-des-delegues"
$display="inline"
>
Défenseur des droits dans votre région
</TextStyled>
</li>
<li>
Envoyer un courrier par la poste (gratuit, ne pas mettre de timbre)
:{' '}
<Text $weight="bold" $display="inline">
Défenseur des droits Libre réponse 71120 75342 Paris CEDEX 07
</Text>
</li>
</Text>
</Box>
</Box>
);
};
Page.getLayout = function getLayout(page: ReactElement) {
return <PageLayout>{page}</PageLayout>;
};
export default Page;

View File

@@ -0,0 +1,67 @@
import { ReactElement } from 'react';
import { useTranslation } from 'react-i18next';
import { Box, Text, TextStyled } from '@/components';
import { useCunninghamTheme } from '@/cunningham';
import { PageLayout } from '@/layouts';
import { NextPageWithLayout } from '@/types/next';
const Page: NextPageWithLayout = () => {
const { t } = useTranslation();
const { colorsTokens } = useCunninghamTheme();
return (
<Box>
<Box
as="h1"
$background={colorsTokens()['primary-100']}
$margin="none"
$padding="large"
>
{t('Legal notice')}
</Box>
<Box $padding={{ horizontal: 'large', vertical: 'big' }}>
<Text as="h2" $margin={{ bottom: 'xtiny' }}>
Éditeur
</Text>
<Text as="p">
Équipe La Suite Numérique de la Direction interministérielle du
numérique DINUM, 20 avenue de Ségur 75007 Paris.
</Text>
<Text as="h2" $margin={{ bottom: 'xtiny' }}>
Directeur de la publication
</Text>
<Text as="p">Directeur interministériel du numérique.</Text>
<Text as="h2" $margin={{ bottom: 'xtiny' }}>
Copyright
</Text>
<Text as="p" $display="inline">
Illustration :{' '}
<Text $weight="bold" $display="inline">
DINUM
</Text>
</Text>
<Text as="h2" $margin={{ bottom: 'xtiny' }}>
Plus d&apos;infos ?
</Text>
<Text as="p" $display="inline">
L&apos;équipe de La Suite Numérique peut être contactée directement à{' '}
<TextStyled
as="a"
href="lasuite@modernisation.gouv.fr"
$display="inline"
>
lasuite@modernisation.gouv.fr
</TextStyled>
.
</Text>
</Box>
</Box>
);
};
Page.getLayout = function getLayout(page: ReactElement) {
return <PageLayout>{page}</PageLayout>;
};
export default Page;

View File

@@ -0,0 +1,110 @@
import { ReactElement } from 'react';
import { useTranslation } from 'react-i18next';
import { Box, Text, TextStyled } from '@/components';
import { useCunninghamTheme } from '@/cunningham';
import { PageLayout } from '@/layouts';
import { NextPageWithLayout } from '@/types/next';
const Page: NextPageWithLayout = () => {
const { t } = useTranslation();
const { colorsTokens } = useCunninghamTheme();
return (
<Box>
<Box
as="h1"
$background={colorsTokens()['primary-100']}
$margin="none"
$padding="large"
>
{t('Personal data and cookies')}
</Box>
<Box $padding={{ horizontal: 'large', vertical: 'big' }}>
<Text as="h2" $margin={{ bottom: 'xtiny' }}>
Cookies déposés
</Text>
<Text as="p">
Ce site dépose un petit fichier texte (un « cookie ») sur votre
ordinateur lorsque vous le consultez. Cela nous permet de mesurer le
nombre de visites et de comprendre quelles sont les pages les plus
consultées.
</Text>
<Text as="p">
Vous pouvez vous opposer au suivi de votre navigation sur ce site web.
Cela protégera votre vie privée, mais empêchera également le
propriétaire d&apos;apprendre de vos actions et de créer une meilleure
expérience pour vous et les autres utilisateurs.
</Text>
<Text as="h2" $margin={{ bottom: 'xtiny' }}>
Ce site n&apos;affiche pas de bannière de consentement aux cookies,
pourquoi ?
</Text>
<Text as="p">
C&apos;est vrai, vous n&apos;avez pas eu à cliquer sur un bloc qui
recouvre la moitié de la page pour dire que vous êtes d&apos;accord
avec le dépôt de cookies même si vous ne savez pas ce que ça veut
dire !
</Text>
<Text as="p">
Rien d&apos;exceptionnel, pas de passe-droit lié à un .gouv.fr . Nous
respectons simplement la loi, qui dit que certains outils de suivi
d&apos;audience, correctement configurés pour respecter la vie privée,
sont exemptés d&apos;autorisation préalable.
</Text>
<Text as="p" $display="inline">
Nous utilisons pour cela{' '}
<TextStyled as="a" href="https://matomo.org/" $display="inline">
Matomo
</TextStyled>
, un outil{' '}
<TextStyled
as="a"
href="https://matomo.org/free-software/"
$display="inline"
>
libre
</TextStyled>
, paramétré pour être en conformité avec la{' '}
<TextStyled
as="a"
href="https://www.cnil.fr/fr/cookies-et-autres-traceurs/regles/cookies-solutions-pour-les-outils-de-mesure-daudience"
$display="inline"
>
recommandation « Cookies »
</TextStyled>{' '}
de la{' '}
<span
style={{
textDecorationStyle: 'dotted',
textDecorationLine: 'underline',
}}
>
CNIL
</span>
. Cela signifie que votre adresse IP, par exemple, est anonymisée
avant d&apos;être enregistrée. Il est donc impossible d&apos;associer
vos visites sur ce site à votre personne.
</Text>
<Text as="h2" $margin={{ bottom: 'xtiny' }}>
Je contribue à enrichir vos données, puis-je y accéder ?
</Text>
<p>
Bien sûr ! Les statistiques d&apos;usage de la majorité de nos
produits, dont lasuite.numerique.gouv.fr, sont disponibles en accès
libre sur{' '}
<TextStyled as="a" href="stats.data.gouv.fr" $display="inline">
stats.data.gouv.fr
</TextStyled>
.
</p>
</Box>
</Box>
);
};
Page.getLayout = function getLayout(page: ReactElement) {
return <PageLayout>{page}</PageLayout>;
};
export default Page;