diff --git a/src/client/components/features/ServicesJeunes/ServicesJeunes.module.scss b/src/client/components/features/ServicesJeunes/ServicesJeunes.module.scss
index bd14c6b94a..88cb897a4d 100644
--- a/src/client/components/features/ServicesJeunes/ServicesJeunes.module.scss
+++ b/src/client/components/features/ServicesJeunes/ServicesJeunes.module.scss
@@ -5,10 +5,6 @@
}
.container {
- @include utilities.media(medium) {
- padding-top: 2rem;
- }
-
& div > ul > li {
flex-grow: 1;
flex-basis: 100%;
diff --git a/src/client/components/features/ServicesJeunes/ServicesJeunes.tsx b/src/client/components/features/ServicesJeunes/ServicesJeunes.tsx
index 748e17e898..ca189f5239 100644
--- a/src/client/components/features/ServicesJeunes/ServicesJeunes.tsx
+++ b/src/client/components/features/ServicesJeunes/ServicesJeunes.tsx
@@ -24,13 +24,16 @@ export function ServicesJeunes(props: ServicesJeunesProps) {
return (
<>
-
+ { props.cardList.length > 0 ? (
+
+ )
+ : Aucun service jeune disponible. Veuillez modifier votre sélection.
}
>
);
diff --git a/src/client/components/useRouter.mock.ts b/src/client/components/useRouter.mock.ts
index cf8485db3d..2987f26c7e 100644
--- a/src/client/components/useRouter.mock.ts
+++ b/src/client/components/useRouter.mock.ts
@@ -17,7 +17,10 @@ interface MockUseRouter {
isReady?: boolean
}
-export function mockUseRouter({ asPath = '', pathname = '', query = {}, route = '', prefetch = jest.fn(), push = jest.fn(), reload = jest.fn(), replace = jest.fn(), back = jest.fn(), isReady = true }: MockUseRouter) {
+export function mockUseRouter({ asPath = '', pathname = '', query = {},
+ route = '', prefetch = jest.fn(), push = jest.fn(),
+ reload = jest.fn(), replace = jest.fn(), back = jest.fn(),
+ isReady = true }: MockUseRouter) {
useRouter.mockImplementation(() => ({
asPath,
back,
diff --git a/src/pages/services-jeunes/index.module.scss b/src/pages/services-jeunes/index.module.scss
index 6d86c203c4..a12dacf24b 100644
--- a/src/pages/services-jeunes/index.module.scss
+++ b/src/pages/services-jeunes/index.module.scss
@@ -1,8 +1,21 @@
@use "@styles/utilities-deprecated";
+@use "@styles/utilities";
.section {
padding-inline: 1rem;
margin-bottom: 3rem;
+
+ @include utilities.media(medium) {
+ padding-inline: 5rem;
+ }
+}
+
+.selectCategorie {
+ margin-bottom: 1rem;
+}
+
+.etiquetteList {
+ margin-bottom: 2rem;
}
.cartesActualitesList {
diff --git a/src/pages/services-jeunes/index.page.test.tsx b/src/pages/services-jeunes/index.page.test.tsx
index f8f684ccef..0a6a6d16aa 100644
--- a/src/pages/services-jeunes/index.page.test.tsx
+++ b/src/pages/services-jeunes/index.page.test.tsx
@@ -13,6 +13,7 @@ import { aManualAnalyticsService } from '~/client/services/analytics/analytics.s
import ServicesJeunePage, { getStaticProps } from '~/pages/services-jeunes/index.page';
import { createFailure, createSuccess } from '~/server/errors/either';
import { ErreurMetier } from '~/server/errors/erreurMetier.types';
+import { ServiceJeune } from '~/server/services-jeunes/domain/servicesJeunes';
import { aServiceJeune, aServiceJeuneList } from '~/server/services-jeunes/domain/servicesJeunes.fixture';
import { dependencies } from '~/server/start';
@@ -30,11 +31,19 @@ jest.mock('~/server/start', () => ({
},
}));
+jest.mock('next/navigation', () => ({
+ usePathname: jest.fn().mockReturnValue('/services-jeunes'),
+ useSearchParams: () => ({
+ getAll: jest.fn().mockReturnValue([]),
+ }),
+}));
+
describe('Page Services Jeunes', () => {
beforeEach(() => {
mockSmallScreen();
mockUseRouter({});
mockScrollIntoView();
+
});
afterEach(() => {
jest.clearAllMocks();
@@ -131,83 +140,220 @@ describe('Page Services Jeunes', () => {
});
describe('Si des services jeunes sont récupérés', () => {
- it('affiche au maximum 6 services initialement', () => {
- // Given
- const serviceJeuneList = [
- aServiceJeune({ titre: 'service 1' }),
- aServiceJeune({ titre: 'service 2' }),
- aServiceJeune({ titre: 'service 3' }),
- aServiceJeune({ titre: 'service 4' }),
- aServiceJeune({ titre: 'service 5' }),
- aServiceJeune({ titre: 'service 6' }),
- aServiceJeune({ titre: 'service 7' }),
- ];
- const analyticsService = aManualAnalyticsService();
-
- // When
- render(
-
-
- ,
- );
-
- // Then
- const mesuresJeunesSection = screen.getByRole('region', { name: 'les services jeunes' });
- const servicesJeunesList = within(mesuresJeunesSection).getAllByRole('listitem');
- expect(servicesJeunesList.length).toBe(6);
+ describe('Sélection des filtres', () => {
+ describe('aucun filtre n’est renseigné', () => {
+ it('affiche l’ensemble des types de services', () => {
+ // Given
+ const serviceJeuneList = [
+ aServiceJeune({ categorie: ServiceJeune.Categorie.ACCOMPAGNEMENT, titre: 'service 1' }),
+ aServiceJeune({ categorie: ServiceJeune.Categorie.AIDES_FINANCIERES, titre: 'service 2' }),
+ aServiceJeune({ categorie: ServiceJeune.Categorie.ENGAGEMENT, titre: 'service 3' }),
+ aServiceJeune({ categorie: ServiceJeune.Categorie.ENTREE_VIE_PROFESSIONELLE, titre: 'service 4' }),
+ aServiceJeune({ categorie: ServiceJeune.Categorie.LOGEMENT, titre: 'service 5' }),
+ aServiceJeune({ categorie: ServiceJeune.Categorie.ORIENTATION_FORMATION, titre: 'service 6' }),
+ ];
+ const analyticsService = aManualAnalyticsService();
+
+ // When
+ render(
+
+
+ ,
+ );
+
+ // Then
+ const mesuresJeunesSection = screen.getByRole('region', { name: 'les services jeunes' });
+ const servicesJeunesList = within(mesuresJeunesSection).getAllByRole('list')[1];
+ const servicesJeunesResultats = within(servicesJeunesList).getAllByRole('listitem');
+ expect(servicesJeunesResultats.length).toBe(6);
+ });
+ });
+ describe('au moins un filtre est renseigné', () => {
+ beforeEach(() => {
+ mockUseRouter({ query : { filtre : ['Accompagnement', 'Logement', 'Engagement'] } });
+ });
+ it('affiche la liste des filtres dans des étiquettes', () => {
+ // Given
+ const serviceJeuneList = [
+ aServiceJeune({ categorie: ServiceJeune.Categorie.ACCOMPAGNEMENT, titre: 'service 1' }),
+ aServiceJeune({ categorie: ServiceJeune.Categorie.AIDES_FINANCIERES, titre: 'service 2' }),
+ aServiceJeune({ categorie: ServiceJeune.Categorie.ENGAGEMENT, titre: 'service 3' }),
+ aServiceJeune({ categorie: ServiceJeune.Categorie.ENTREE_VIE_PROFESSIONELLE, titre: 'service 4' }),
+ aServiceJeune({ categorie: ServiceJeune.Categorie.LOGEMENT, titre: 'service 5' }),
+ aServiceJeune({ categorie: ServiceJeune.Categorie.ORIENTATION_FORMATION, titre: 'service 6' }),
+ ];
+ const analyticsService = aManualAnalyticsService();
+
+ // When
+ render(
+
+
+ ,
+ );
+
+ // Then
+ const mesuresJeunesSection = screen.getByRole('region', { name: 'les services jeunes' });
+ const servicesJeunesList = within(mesuresJeunesSection).getAllByRole('list')[0];
+ const servicesJeunesEtiquettes = within(servicesJeunesList).getAllByRole('listitem');
+ expect(servicesJeunesEtiquettes.length).toBe(3);
+ });
+ it('supprime le filtre au clic sur son étiquette', async () => {
+ // Given
+ const routerPush = jest.fn();
+ mockUseRouter({ push: routerPush, query: { filtre : ['Accompagnement', 'Logement', 'Engagement'] } });
+ const user = userEvent.setup();
+
+ const serviceJeuneList = [
+ aServiceJeune({ categorie: ServiceJeune.Categorie.ACCOMPAGNEMENT, titre: 'service 1' }),
+ aServiceJeune({ categorie: ServiceJeune.Categorie.AIDES_FINANCIERES, titre: 'service 2' }),
+ ];
+ const analyticsService = aManualAnalyticsService();
+
+ // When
+ render(
+
+
+ ,
+ );
+ const mesuresJeunesSectionBefore = screen.getByRole('region', { name: 'les services jeunes' });
+ const servicesJeunesListBefore = within(mesuresJeunesSectionBefore).getAllByRole('list')[0];
+ const servicesJeunesEtiquettesBefore = within(servicesJeunesListBefore).getAllByRole('listitem');
+ expect(servicesJeunesEtiquettesBefore.length).toBe(3);
+
+ const resetButton = within(servicesJeunesEtiquettesBefore[0]).getByRole('button');
+ await user.click(resetButton);
+
+ // Then
+ expect(routerPush).toHaveBeenCalledTimes(1);
+ expect(routerPush).toHaveBeenCalledWith(expect.stringContaining('filtre=Logement'));
+ expect(routerPush).toHaveBeenCalledWith(expect.stringContaining('filtre=Engagement'));
+ });
+ it('affiche les services des catégories filtrées', () => {
+ const serviceJeuneList = [
+ aServiceJeune({ categorie: ServiceJeune.Categorie.ACCOMPAGNEMENT, titre: 'service 1' }),
+ aServiceJeune({ categorie: ServiceJeune.Categorie.AIDES_FINANCIERES, titre: 'service 2' }),
+ aServiceJeune({ categorie: ServiceJeune.Categorie.ENGAGEMENT, titre: 'service 3' }),
+ aServiceJeune({ categorie: ServiceJeune.Categorie.ENTREE_VIE_PROFESSIONELLE, titre: 'service 4' }),
+ aServiceJeune({ categorie: ServiceJeune.Categorie.LOGEMENT, titre: 'service 5' }),
+ aServiceJeune({ categorie: ServiceJeune.Categorie.ORIENTATION_FORMATION, titre: 'service 6' }),
+ ];
+ const analyticsService = aManualAnalyticsService();
+
+ // When
+ render(
+
+
+ ,
+ );
+
+ // Then
+ const mesuresJeunesSection = screen.getByRole('region', { name: 'les services jeunes' });
+ const servicesJeunesList = within(mesuresJeunesSection).getAllByRole('list')[1];
+ const servicesJeunesEtiquettes = within(servicesJeunesList).getAllByRole('listitem');
+ expect(servicesJeunesEtiquettes.length).toBe(3);
+ });
+ });
});
- it('affiche un bouton voir plus quand il y a plus de 6 services', () => {
+ describe('Liste de résultats', () => {
+ it('affiche un message d’erreur quand aucun service n’est disponible', () => {
+ // Given
+ mockUseRouter({ query: { filtre : ['Accompagnement'] } });
+ const serviceJeuneList = [
+ aServiceJeune({ categorie: ServiceJeune.Categorie.AIDES_FINANCIERES, titre: 'service 2' }),
+ ];
+ const analyticsService = aManualAnalyticsService();
+
+ // When
+ render(
+
+
+ ,
+ );
+
+ // Then
+ const mesuresJeunesSection = screen.getByRole('region', { name: 'les services jeunes' });
+ const messageErreur = within(mesuresJeunesSection).getByText('Aucun service jeune disponible. Veuillez modifier votre sélection.');
+ expect(messageErreur).toBeVisible();
+ });
+ it('affiche au maximum 6 services initialement', () => {
// Given
- const serviceJeuneList = [
- aServiceJeune({ titre: 'service 1' }),
- aServiceJeune({ titre: 'service 2' }),
- aServiceJeune({ titre: 'service 3' }),
- aServiceJeune({ titre: 'service 4' }),
- aServiceJeune({ titre: 'service 5' }),
- aServiceJeune({ titre: 'service 6' }),
- aServiceJeune({ titre: 'service 7' }),
- ];
- const analyticsService = aManualAnalyticsService();
-
- // When
- render(
-
-
- ,
- );
-
- // Then
- const mesuresJeunesSection = screen.getByRole('region', { name: 'les services jeunes' });
- const voirPlusDeServicesJeunesBouton = within(mesuresJeunesSection).getByRole('button', { name: 'Voir plus de services conçus pour les jeunes' });
- expect(voirPlusDeServicesJeunesBouton).toBeVisible();
- });
- it('affiche un bouton voir moins quand plus de 6 services jeunes sont visibles', async () => {
+ const serviceJeuneList = [
+ aServiceJeune({ titre: 'service 1' }),
+ aServiceJeune({ titre: 'service 2' }),
+ aServiceJeune({ titre: 'service 3' }),
+ aServiceJeune({ titre: 'service 4' }),
+ aServiceJeune({ titre: 'service 5' }),
+ aServiceJeune({ titre: 'service 6' }),
+ aServiceJeune({ titre: 'service 7' }),
+ ];
+ const analyticsService = aManualAnalyticsService();
+
+ // When
+ render(
+
+
+ ,
+ );
+
+ // Then
+ const mesuresJeunesSection = screen.getByRole('region', { name: 'les services jeunes' });
+ const servicesJeunesList = within(mesuresJeunesSection).getAllByRole('list')[1];
+ const servicesJeunesResultats = within(servicesJeunesList).getAllByRole('listitem');
+ expect(servicesJeunesResultats.length).toBe(6);
+ });
+ it('affiche un bouton voir plus quand il y a plus de 6 services', () => {
// Given
- const serviceJeuneList = [
- aServiceJeune({ titre: 'service 1' }),
- aServiceJeune({ titre: 'service 2' }),
- aServiceJeune({ titre: 'service 3' }),
- aServiceJeune({ titre: 'service 4' }),
- aServiceJeune({ titre: 'service 5' }),
- aServiceJeune({ titre: 'service 6' }),
- aServiceJeune({ titre: 'service 7' }),
- ];
- const analyticsService = aManualAnalyticsService();
-
- render(
-
-
- ,
- );
- const mesuresJeunesSection = screen.getByRole('region', { name: 'les services jeunes' });
- const voirPlusDeServicesJeunesBouton = within(mesuresJeunesSection).getByRole('button', { name: 'Voir plus de services conçus pour les jeunes' });
-
- // When
- await userEvent.click(voirPlusDeServicesJeunesBouton);
-
- // Then
- const voirMoinsDeServicesJeunesBouton = within(mesuresJeunesSection).getByRole('button', { name: 'Voir moins de services conçus pour les jeunes' });
- expect(voirMoinsDeServicesJeunesBouton).toBeVisible();
+ const serviceJeuneList = [
+ aServiceJeune({ titre: 'service 1' }),
+ aServiceJeune({ titre: 'service 2' }),
+ aServiceJeune({ titre: 'service 3' }),
+ aServiceJeune({ titre: 'service 4' }),
+ aServiceJeune({ titre: 'service 5' }),
+ aServiceJeune({ titre: 'service 6' }),
+ aServiceJeune({ titre: 'service 7' }),
+ ];
+ const analyticsService = aManualAnalyticsService();
+
+ // When
+ render(
+
+
+ ,
+ );
+
+ // Then
+ const mesuresJeunesSection = screen.getByRole('region', { name: 'les services jeunes' });
+ const voirPlusDeServicesJeunesBouton = within(mesuresJeunesSection).getByRole('button', { name: 'Voir plus de services conçus pour les jeunes' });
+ expect(voirPlusDeServicesJeunesBouton).toBeVisible();
+ });
+ it('affiche un bouton voir moins quand plus de 6 services jeunes sont visibles', async () => {
+ // Given
+ const serviceJeuneList = [
+ aServiceJeune({ titre: 'service 1' }),
+ aServiceJeune({ titre: 'service 2' }),
+ aServiceJeune({ titre: 'service 3' }),
+ aServiceJeune({ titre: 'service 4' }),
+ aServiceJeune({ titre: 'service 5' }),
+ aServiceJeune({ titre: 'service 6' }),
+ aServiceJeune({ titre: 'service 7' }),
+ ];
+ const analyticsService = aManualAnalyticsService();
+
+ render(
+
+
+ ,
+ );
+ const mesuresJeunesSection = screen.getByRole('region', { name: 'les services jeunes' });
+ const voirPlusDeServicesJeunesBouton = within(mesuresJeunesSection).getByRole('button', { name: 'Voir plus de services conçus pour les jeunes' });
+
+ // When
+ await userEvent.click(voirPlusDeServicesJeunesBouton);
+
+ // Then
+ const voirMoinsDeServicesJeunesBouton = within(mesuresJeunesSection).getByRole('button', { name: 'Voir moins de services conçus pour les jeunes' });
+ expect(voirMoinsDeServicesJeunesBouton).toBeVisible();
+ });
});
});
});
diff --git a/src/pages/services-jeunes/index.page.tsx b/src/pages/services-jeunes/index.page.tsx
index 3bad971f3b..1057ddd8e0 100644
--- a/src/pages/services-jeunes/index.page.tsx
+++ b/src/pages/services-jeunes/index.page.tsx
@@ -1,10 +1,17 @@
import { GetStaticPropsResult } from 'next';
-import React from 'react';
+import { usePathname } from 'next/navigation';
+import { useRouter } from 'next/router';
+import React, { useCallback } from 'react';
import { ServicesJeunes } from '~/client/components/features/ServicesJeunes/ServicesJeunes';
import { Head } from '~/client/components/head/Head';
+import { Champ } from '~/client/components/ui/Form/Champ/Champ';
+import { SelectMultiple } from '~/client/components/ui/Form/Select/SelectMultiple';
import { LightHero, LightHeroPrimaryText, LightHeroSecondaryText } from '~/client/components/ui/Hero/LightHero';
+import { Icon } from '~/client/components/ui/Icon/Icon';
+import { TagList } from '~/client/components/ui/Tag/TagList';
import useAnalytics from '~/client/hooks/useAnalytics';
+import { getArrayQueryParam } from '~/client/utils/queryParams.utils';
import analytics from '~/pages/espace-jeune/index.analytics';
import { isFailure } from '~/server/errors/either';
import { ServiceJeune } from '~/server/services-jeunes/domain/servicesJeunes';
@@ -19,6 +26,30 @@ interface ServicesJeunePageProps {
export default function ServicesJeunesPage({ serviceJeuneList }: ServicesJeunePageProps) {
useAnalytics(analytics);
+ const router = useRouter();
+ const pathname = usePathname();
+ const filtreList = getArrayQueryParam(router.query.filtre) ?? [];
+
+ const toggleOption = useCallback(
+ (option: HTMLElement) => {
+ if(filtreList.includes(option.dataset.value!) && option.getAttribute('aria-selected') === 'true'){
+ return filtreList.filter((e) => e !== option.dataset.value!).map((e) => 'filtre=' + e).join('&');
+ } else if (!filtreList.includes(option.dataset.value!) && option.getAttribute('aria-selected') === 'false') {
+ return filtreList.map((e) => 'filtre=' + e).join('&').concat('&filtre=' + option.dataset.value!);
+ }
+ return '';
+ },
+ [filtreList],
+ );
+
+ function removeFilterAndGenerateQueryString(filtre: string) {
+ return filtreList.filter((e) => e !== filtre).map((e) => 'filtre=' + e).join('&');
+ }
+
+ const servicesJeunesVisibles = filtreList.length > 0 ? serviceJeuneList.filter((service) => {
+ return filtreList.includes(service.categorie!);
+ }) : serviceJeuneList;
+
return (
<>
-
+
+
+ Types de service à destination des jeunes
+ Sélectionnez votre/vos choix
+
+ {
+ router.push(pathname + '?' + toggleOption(option));
+ }}
+ optionsAriaLabel={'Toto'}>
+ {Object.values(ServiceJeune.Categorie).map((option, index) =>
+ {option},
+ )}
+
+
+
+ {
+ return (
+
+ );
+ },
+ )} />
+
+
>
);