From d0443605780e7c022a0cd5c197c5bb34932eb90c Mon Sep 17 00:00:00 2001 From: Alexandre Monney Date: Mon, 9 Dec 2024 11:44:04 +0100 Subject: [PATCH] feat(orga): create statistics component Co-authored-by: Vincent Hardouin --- orga/app/components/statistics/index.gjs | 47 ++++++++++++++ orga/app/styles/app.scss | 2 + orga/app/styles/components/statistics.scss | 15 +++++ .../templates/authenticated/statistics.hbs | 3 + orga/mirage/config.js | 14 +++++ orga/tests/acceptance/statistics-test.js | 44 +++++++++++++ .../components/statistics/index-test.gjs | 62 +++++++++++++++++++ 7 files changed, 187 insertions(+) create mode 100644 orga/app/components/statistics/index.gjs create mode 100644 orga/app/styles/components/statistics.scss create mode 100644 orga/app/templates/authenticated/statistics.hbs create mode 100644 orga/tests/acceptance/statistics-test.js create mode 100644 orga/tests/integration/components/statistics/index-test.gjs diff --git a/orga/app/components/statistics/index.gjs b/orga/app/components/statistics/index.gjs new file mode 100644 index 00000000000..b14b06e65c3 --- /dev/null +++ b/orga/app/components/statistics/index.gjs @@ -0,0 +1,47 @@ +import { t } from 'ember-intl'; + +import Header from '../table/header'; +import CoverRateGauge from './cover-rate-gauge'; +import TagLevel from './tag-level'; + +const analysisByTubes = (model) => { + return model.data.sort( + (a, b) => a.competence_code.localeCompare(b.competence_code) || a.sujet.localeCompare(b.sujet), + ); +}; + + diff --git a/orga/app/styles/app.scss b/orga/app/styles/app.scss index 2b830f2e070..2f30e8c10aa 100644 --- a/orga/app/styles/app.scss +++ b/orga/app/styles/app.scss @@ -51,6 +51,8 @@ @import 'components/sup-organization-participant/replace-students-modal'; @import 'components/import-banner'; @import 'components/import-information-banner'; +@import 'components/statistics'; +@import 'components/statistics/cover-rate-gauge'; // pages @import 'pages/login'; diff --git a/orga/app/styles/components/statistics.scss b/orga/app/styles/components/statistics.scss new file mode 100644 index 00000000000..6ae5162a2d0 --- /dev/null +++ b/orga/app/styles/components/statistics.scss @@ -0,0 +1,15 @@ +.statistics-page-header { + display: flex; + gap: var(--pix-spacing-2x); + align-items: baseline; + + &__date { + @extend %pix-body-xs; + } +} + +tbody > tr { + &:nth-child(odd) { + background-color: var(--pix-neutral-20); + } +} diff --git a/orga/app/templates/authenticated/statistics.hbs b/orga/app/templates/authenticated/statistics.hbs new file mode 100644 index 00000000000..34079a2bdad --- /dev/null +++ b/orga/app/templates/authenticated/statistics.hbs @@ -0,0 +1,3 @@ +{{page-title (t "pages.statistics.title")}} + + \ No newline at end of file diff --git a/orga/mirage/config.js b/orga/mirage/config.js index b3ed4bae7e2..f534f0969ae 100644 --- a/orga/mirage/config.js +++ b/orga/mirage/config.js @@ -276,6 +276,20 @@ function routes() { this.get('/organizations/:id/participants', findFilteredPaginatedOrganizationParticipants); + this.get('/organizations/:id/organization-learners-level-by-tubes', (schema, request) => { + return schema.analysisByTubes.create({ + data: [ + { + competence_code: '2.1', + competence: 'Interagir', + sujet: 'Gérer ses contacts', + niveau_par_user: '1.30', + niveau_par_sujet: '1.50', + }, + ], + }); + }); + this.get('/organization-learners/:id', (schema, request) => { const participantId = request.params.id; diff --git a/orga/tests/acceptance/statistics-test.js b/orga/tests/acceptance/statistics-test.js new file mode 100644 index 00000000000..3db9f15836a --- /dev/null +++ b/orga/tests/acceptance/statistics-test.js @@ -0,0 +1,44 @@ +import { visit } from '@1024pix/ember-testing-library'; +import { currentURL } from '@ember/test-helpers'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import { t } from 'ember-intl/test-support'; +import { setupApplicationTest } from 'ember-qunit'; +import { module, test } from 'qunit'; + +import authenticateSession from '../helpers/authenticate-session'; +import setupIntl from '../helpers/setup-intl'; +import { createPrescriberForOrganization } from '../helpers/test-init'; + +module('Acceptance | Statistics', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + setupIntl(hooks); + + module('When prescriber is not logged in', function () { + test('it should not be accessible by an unauthenticated prescriber', async function (assert) { + // when + await visit('/statistiques'); + + // then + assert.deepEqual(currentURL(), '/connexion'); + }); + }); + + module('When prescriber is logged in and has cover rate feature', function () { + test('user should access to page', async function (assert) { + // given + const user = createPrescriberForOrganization({ lang: 'fr', pixOrgaTermsOfServiceAccepted: true }, {}, 'ADMIN', { + COVER_RATE: true, + }); + await authenticateSession(user.id); + + // when + const screen = await visit('/statistiques'); + + // then + assert.dom(screen.getByRole('heading', { level: 1, name: t('pages.statistics.title') })).exists(); + assert.dom(screen.getByRole('table')).exists(); + assert.ok(screen.getAllByRole('cell')); + }); + }); +}); diff --git a/orga/tests/integration/components/statistics/index-test.gjs b/orga/tests/integration/components/statistics/index-test.gjs new file mode 100644 index 00000000000..da68971a492 --- /dev/null +++ b/orga/tests/integration/components/statistics/index-test.gjs @@ -0,0 +1,62 @@ +import { render } from '@1024pix/ember-testing-library'; +import { t } from 'ember-intl/test-support'; +import Statistics from 'pix-orga/components/statistics/index'; +import { module, test } from 'qunit'; + +import setupIntlRenderingTest from '../../../helpers/setup-intl-rendering'; + +module('Integration | Component | Statistics | Index', function (hooks) { + setupIntlRenderingTest(hooks); + + test('it should display title', async function (assert) { + //given + const model = { + data: [], + }; + + //when + const screen = await render(); + + //then + assert.ok(screen.getByText(t('pages.statistics.title'))); + }); + + test('it should display table headers', async function (assert) { + //given + const model = { + data: [], + }; + + //when + const screen = await render(); + + //then + assert.ok(screen.getByRole('columnheader', { name: t('pages.statistics.table.headers.skills') })); + assert.ok(screen.getByRole('columnheader', { name: t('pages.statistics.table.headers.subjects') })); + assert.ok(screen.getByRole('columnheader', { name: t('pages.statistics.table.headers.reached-level') })); + assert.ok(screen.getByRole('columnheader', { name: t('pages.statistics.table.headers.cover-rate') })); + }); + + test('it should display rows data', async function (assert) { + //given + const model = { + data: [ + { + competence_code: '2.1', + competence: 'Interagir', + sujet: 'Gérer ses contacts', + niveau_par_user: '1.30', + niveau_par_sujet: '1.50', + }, + ], + }; + + //when + const screen = await render(); + + //then + assert.ok(screen.getByRole('cell', { name: '2.1 Interagir' })); + assert.ok(screen.getByRole('cell', { name: 'Gérer ses contacts' })); + assert.ok(screen.getByRole('cell', { name: t('pages.statistics.level.novice') })); + }); +});