diff --git a/src/frontend/apps/desk/src/core/PageLayout.tsx b/src/frontend/apps/desk/src/core/PageLayout.tsx
new file mode 100644
index 0000000..5a6340d
--- /dev/null
+++ b/src/frontend/apps/desk/src/core/PageLayout.tsx
@@ -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 (
+
+
+
+ {children}
+
+
+
+ );
+}
diff --git a/src/frontend/apps/desk/src/core/index.ts b/src/frontend/apps/desk/src/core/index.ts
index 6af2968..3e5bb64 100644
--- a/src/frontend/apps/desk/src/core/index.ts
+++ b/src/frontend/apps/desk/src/core/index.ts
@@ -1,2 +1,3 @@
export * from './AppProvider';
export * from './MainLayout';
+export * from './PageLayout';
diff --git a/src/frontend/apps/desk/src/features/footer/Footer.tsx b/src/frontend/apps/desk/src/features/footer/Footer.tsx
index d887c1a..b1e1022 100644
--- a/src/frontend/apps/desk/src/features/footer/Footer.tsx
+++ b/src/frontend/apps/desk/src/features/footer/Footer.tsx
@@ -37,6 +37,7 @@ export const Footer = () => {
$gap="1.5rem"
$align="center"
$justify="space-between"
+ $css="flex-wrap: wrap;"
>
@@ -50,7 +51,6 @@ export const Footer = () => {
{
))}
+
+ {[
+ {
+ label: t('Legal Notice'),
+ href: '/legal-notice',
+ },
+ {
+ label: t('Personal data and cookies'),
+ href: '/personal-data-cookies',
+ },
+ {
+ label: t('Accessibility: non-compliant'),
+ href: '/accessibility',
+ },
+ ].map(({ label, href }) => (
+
+
+ {label}
+
+
+ ))}
+
) => {
+ return (
+
+ {children}
+
+ );
+};
+
+const Page: NextPageWithLayout = () => {
+ const { t } = useTranslation();
+ const { colorsTokens } = useCunninghamTheme();
+
+ return (
+
+
+ {t('Accessibility statement')}
+
+
+ {t('Declaration established on June 25, 2024.')}
+
+ {t(`The National Agency for Territorial Cohesion undertakes to make its
+ service accessible, in accordance with article 47 of law no. 2005-102
+ of February 11, 2005.`)}
+
+ {t(
+ `This accessibility statement applies to La Régie (Suite Territoriale)`,
+ )}{' '}
+ (https://regie.numerique.gouv.fr/).
+
+
+ {t('Compliance status')}
+
+
+ {t(
+ 'La Régie (Suite Territoriale) is non-compliant with the RGAA. The site has not yet been audited.',
+ )}
+
+
+ {t('Improvement and contact')}
+
+
+ {t(
+ `If you are unable to access content or a service, you can contact the manager of La Régie (Suite Territoriale)
+ to be directed to an accessible alternative or obtain the content in another form.`,
+ )}
+
+ -
+ {t(
+ `Address: National Agency for Territorial Cohesion - 20, avenue de Ségur TSA 10717 75 334 Paris Cedex 07 Paris`,
+ )}
+
+ -
+ {t('E-mail:')}{' '}
+
+ suiteterritoriale@anct.gouv.fr
+
+
+
+
+
+ {t('Remedy')}
+
+
+ {t(
+ `This procedure is to be used in the following case: you have reported to the website
+ manager an accessibility defect which prevents you from accessing content or one of the
+ portal's services and you have not obtained a satisfactory response.`,
+ )}
+
+
+ {t('You can:')}
+
+
+
+ Write a message to the
+
+ Defender of Rights
+
+
+
+
+
+ Contact the delegate of the
+
+ Defender of Rights in your region
+
+
+
+
+ {t('Send a letter by post (free of charge, no stamp needed):')}{' '}
+
+ {t(
+ 'Defender of Rights - Free response - 71120 75342 Paris CEDEX 07',
+ )}
+
+
+
+
+
+
+ );
+};
+
+Page.getLayout = function getLayout(page: ReactElement) {
+ return {page};
+};
+
+export default Page;
diff --git a/src/frontend/apps/desk/src/pages/legal-notice/index.tsx b/src/frontend/apps/desk/src/pages/legal-notice/index.tsx
new file mode 100644
index 0000000..5e3135c
--- /dev/null
+++ b/src/frontend/apps/desk/src/pages/legal-notice/index.tsx
@@ -0,0 +1,72 @@
+import { ReactElement } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import { Box, Text, TextStyled } from '@/components';
+import { PageLayout } from '@/core';
+import { useCunninghamTheme } from '@/cunningham';
+import { NextPageWithLayout } from '@/types/next';
+
+const Page: NextPageWithLayout = () => {
+ const { t } = useTranslation();
+ const { colorsTokens } = useCunninghamTheme();
+
+ return (
+
+
+ {t('Legal notice')}
+
+
+
+ {t('Publisher')}
+
+
+ {t(
+ 'French Interministerial Directorate for Digital Affairs (DINUM), 20 avenue de Ségur 75007 Paris.',
+ )}
+
+
+ {t('Publication Director')}
+
+
+ {t('Stéphanie Schaer: Interministerial Digital Director (DINUM).')}
+
+
+ {t('Copyright')}
+
+
+ {t('Illustration:')}{' '}
+
+ DINUM
+
+
+
+ {t('More info?')}
+
+
+ {t(
+ 'The team in charge of the digital workspace "La Suite numérique" can be contacted directly at',
+ )}{' '}
+
+ lasuite@modernisation.gouv.fr
+
+ .
+
+
+
+ );
+};
+
+Page.getLayout = function getLayout(page: ReactElement) {
+ return {page};
+};
+
+export default Page;
diff --git a/src/frontend/apps/desk/src/pages/personal-data-cookies/index.tsx b/src/frontend/apps/desk/src/pages/personal-data-cookies/index.tsx
new file mode 100644
index 0000000..2f76983
--- /dev/null
+++ b/src/frontend/apps/desk/src/pages/personal-data-cookies/index.tsx
@@ -0,0 +1,66 @@
+import { ReactElement } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import { Box, Text } from '@/components';
+import { PageLayout } from '@/core';
+import { useCunninghamTheme } from '@/cunningham';
+import { NextPageWithLayout } from '@/types/next';
+
+const Page: NextPageWithLayout = () => {
+ const { t } = useTranslation();
+ const { colorsTokens } = useCunninghamTheme();
+
+ return (
+
+
+ {t('Personal data and cookies')}
+
+
+
+ {t('Cookies placed')}
+
+
+ {t(
+ 'This site places a small text file (a "cookie") on your computer when you visit it.',
+ )}
+ {t(
+ 'This allows us to measure the number of visits and understand which pages are the most viewed.',
+ )}
+
+
+ {t('You can oppose the tracking of your browsing on this website.')}{' '}
+ {t(
+ 'This will protect your privacy, but will also prevent the owner from learning from your actions and creating a better experience for you and other users.',
+ )}
+
+
+ {t('This site does not display a cookie consent banner, why?')}
+
+
+ {t(
+ "It's true, you didn't have to click on a block that covers half the page to say you agree to the placement of cookies — even if you don't know what it means!",
+ )}
+
+
+ {t(
+ 'Nothing exceptional, no special privileges related to a .gouv.fr.',
+ )}{' '}
+ {t(
+ 'We simply comply with the law, which states that certain audience measurement tools, properly configured to respect privacy, are exempt from prior authorization.',
+ )}
+
+
+
+ );
+};
+
+Page.getLayout = function getLayout(page: ReactElement) {
+ return {page};
+};
+
+export default Page;
diff --git a/src/frontend/apps/e2e/__tests__/app-desk/footer.spec.ts b/src/frontend/apps/e2e/__tests__/app-desk/footer.spec.ts
index 45e188c..c18d220 100644
--- a/src/frontend/apps/e2e/__tests__/app-desk/footer.spec.ts
+++ b/src/frontend/apps/e2e/__tests__/app-desk/footer.spec.ts
@@ -33,10 +33,56 @@ 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',
),
).toBeVisible();
});
+
+ const legalPages = [
+ {
+ linkName: 'Legal Notice',
+ pageName: 'Legal Notice',
+ url: '/legal-notice',
+ },
+ {
+ linkName: 'Personal data and cookies',
+ pageName: 'Personal data and cookies',
+ url: '/personal-data-cookies',
+ },
+ {
+ linkName: 'Accessibility: non-compliant',
+ pageName: 'Accessibility statement',
+ url: '/accessibility',
+ },
+ ];
+ for (const { linkName, url, pageName } of legalPages) {
+ test(`checks ${linkName} page`, async ({ page }) => {
+ const footer = page.locator('footer').first();
+ await footer.getByRole('link', { name: linkName }).click();
+
+ await expect(
+ page
+ .getByRole('heading', {
+ name: pageName,
+ })
+ .first(),
+ ).toBeVisible();
+
+ await expect(page).toHaveURL(url);
+ });
+ }
});