Skip to content

Commit

Permalink
feat(mon-pix): add trainings tab content
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeyffrey authored Sep 25, 2024
1 parent fea5add commit 8b993f0
Show file tree
Hide file tree
Showing 9 changed files with 288 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ export default class EvaluationResultsTabs extends Component {
</Panel>
{{#if this.showTrainingsTab}}
<Panel @index={{2}}>
<Trainings />
<Trainings
@trainings={{@trainings}}
@isParticipationShared={{@isParticipationShared}}
@campaignParticipationResultId={{@campaignParticipationResultId}}
/>
</Panel>
{{/if}}
</:panels>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,81 @@
import PixButton from '@1024pix/pix-ui/components/pix-button';
import PixMessage from '@1024pix/pix-ui/components/pix-message';
import { action } from '@ember/object';
import { inject as service } from '@ember/service';
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { t } from 'ember-intl';

<template>
<h2 class="evaluation-results-tab__title">{{t "pages.skill-review.tabs.trainings.title"}}</h2>
<p class="evaluation-results-tab__description">{{t "pages.skill-review.tabs.trainings.description"}}</p>
</template>
import TrainingCard from '../../../../training/card';

export default class EvaluationResultsTabsTrainings extends Component {
@service store;

@tracked isShareResultsLoading = false;
@tracked isShareResultsError = false;
@tracked isParticipationShared = false;

constructor() {
super(...arguments);

this.isParticipationShared = this.args.isParticipationShared;
}

@action
async shareResults() {
const adapter = this.store.adapterFor('campaign-participation-result');

try {
this.isShareResultsError = false;
this.isShareResultsLoading = true;

await adapter.share(this.args.campaignParticipationResultId);

this.isParticipationShared = true;
} catch {
this.isShareResultsError = true;
} finally {
this.isShareResultsLoading = false;
}
}

<template>
<div
class="evaluation-results-tab__trainings
{{unless this.isParticipationShared 'evaluation-results-tab__trainings--with-modal'}}"
>
<div
class="evaluation-results-tab__trainings-content"
inert={{unless this.isParticipationShared "true"}}
role={{unless this.isParticipationShared "presentation"}}
>
<h2 class="evaluation-results-tab__title">{{t "pages.skill-review.tabs.trainings.title"}}</h2>
<p class="evaluation-results-tab__description">{{t "pages.skill-review.tabs.trainings.description"}}</p>

<ul class="evaluation-results-tab__trainings-list">
{{#each @trainings as |training|}}
<li class="evaluation-results-tab__training">
<TrainingCard @training={{training}} />
</li>
{{/each}}
</ul>
</div>

{{#unless this.isParticipationShared}}
<div class="evaluation-results-tab__share-results-modal" role="dialog">
<div class="evaluation-results-tab-share-results-modal__content">
<p>{{t "pages.skill-review.tabs.trainings.modal.content" htmlSafe=true}}</p>
<PixButton @triggerAction={{this.shareResults}} @isLoading={{this.isShareResultsLoading}}>
{{t "pages.skill-review.actions.send"}}
</PixButton>
{{#if this.isShareResultsError}}
<PixMessage @type="error" @withIcon={{true}}>
{{t "pages.skill-review.tabs.trainings.modal.share-error"}}
</PixMessage>
{{/if}}
</div>
</div>
{{/unless}}
</div>
</template>
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import QuitResults from '../../../campaigns/assessment/skill-review/quit-results
</header>
<EvaluationResultsTabs
@badges={{@model.campaignParticipationResult.campaignParticipationBadges}}
@campaignParticipationResultId={{@model.campaignParticipationResult.id}}
@competenceResults={{@model.campaignParticipationResult.competenceResults}}
@isParticipationShared={{@model.campaignParticipationResult.isShared}}
@totalStage={{@model.campaignParticipationResult.reachedStage.totalStage}}
@trainings={{@model.trainings}}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
.evaluation-results-tab__trainings {
position: relative;

&--with-modal {
padding: 0 var(--pix-spacing-4x) var(--pix-spacing-4x);
}

&--with-modal .evaluation-results-tab__trainings-content {
filter: blur(2px);
}
}

.evaluation-results-tab__trainings-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr));
gap: var(--pix-spacing-6x);
margin-top: var(--pix-spacing-8x);
}

.evaluation-results-tab__share-results-modal {
position: absolute;
inset: -1rem 0 0;
z-index: 1;

&::before {
position: absolute;
background-color: var(--pix-primary-900);
border-radius: 1.5rem;
opacity: 0.4;
content: '';
inset: 0;
}
}

.evaluation-results-tab-share-results-modal__content {
@extend %pix-body-m;

position: absolute;
top: 50%;
left: 50%;
display: flex;
flex-direction: column;
gap: var(--pix-spacing-8x);
align-items: center;
max-width: 36rem;
padding: var(--pix-spacing-8x);
text-align: center;
background-color: var(--pix-neutral-0);
border: 1px solid var(--pix-neutral-100);
border-radius: 1.5rem;
transform: translate(-50%, -50%);
}
3 changes: 2 additions & 1 deletion mon-pix/app/styles/components/campaigns/index.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@import 'assessment/skill-review/quit-results';
@import 'assessment/skill-review/share-badge-icons';
@import 'assessment/skill-review/evaluation-results-tabs/results-details';
@import 'assessment/skill-review/evaluation-results-tabs/rewards';
@import 'assessment/skill-review/quit-results';
@import 'assessment/skill-review/evaluation-results-tabs/trainings';
@import 'invited/learner-reconciliation';
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ module('Integration | Components | Campaigns | Assessment | Skill Review | Evalu
const acquiredBadge = store.createRecord('badge', { isAcquired: true });
this.set('badges', [acquiredBadge]);

const training = store.createRecord('training');
const training = store.createRecord('training', { duration: { days: 2 } });
this.set('trainings', [training]);

// when
Expand Down Expand Up @@ -79,7 +79,7 @@ module('Integration | Components | Campaigns | Assessment | Skill Review | Evalu
this.set('badges', []);
this.set('competenceResults', []);

const training = store.createRecord('training');
const training = store.createRecord('training', { duration: { days: 2 } });
this.set('trainings', [training]);

// when
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { render } from '@1024pix/ember-testing-library';
import { click } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
import { t } from 'ember-intl/test-support';
import { module, test } from 'qunit';
import sinon from 'sinon';

import setupIntlRenderingTest from '../../../../../../helpers/setup-intl-rendering';

module('Integration | Components | Campaigns | Assessment | Evaluation Results Tabs | Trainings', function (hooks) {
setupIntlRenderingTest(hooks);

module('when participation is already shared', function () {
test('it should display the trainings list', async function (assert) {
// given
const store = this.owner.lookup('service:store');
const training1 = store.createRecord('training', {
title: 'Mon super training',
link: 'https://exemple.net/',
duration: { days: 2 },
});
const training2 = store.createRecord('training', {
title: 'Mon autre super training',
link: 'https://exemple.net/',
duration: { days: 2 },
});

this.set('trainings', [training1, training2]);

// when
const screen = await render(
hbs`<Campaigns::Assessment::SkillReview::EvaluationResultsTabs::Trainings
@trainings={{this.trainings}}
@isParticipationShared='true'
/>`,
);

// then
assert.dom(screen.getByRole('heading', { name: t('pages.skill-review.tabs.trainings.title') })).isVisible();
assert.dom(screen.getByText(t('pages.skill-review.tabs.trainings.description'))).isVisible();

assert.strictEqual(screen.getAllByRole('link').length, 2);
assert.dom(screen.getByText('Mon super training')).isVisible();
assert.dom(screen.getByText('Mon autre super training')).isVisible();

assert.dom(screen.queryByRole('dialog')).doesNotExist();
});
});

module('when participation is not already shared', function (hooks) {
let screen;

hooks.beforeEach(async function () {
// given
this.set('isParticipationShared', false);
this.set('campaignParticipationResultId', 1);

// when
screen = await render(
hbs`<Campaigns::Assessment::SkillReview::EvaluationResultsTabs::Trainings
@isParticipationShared={{this.isParticipationShared}}
@campaignParticipationResultId={{this.campaignParticipationResultId}}
/>`,
);
});

test('it should display a dialog with share results button', async function (assert) {
// then
assert.dom(screen.getByRole('dialog')).isVisible();
assert.dom(screen.getByText(/Envoyez vos résultats pour permettre/)).isVisible();
assert.dom(screen.getByRole('button', { name: t('pages.skill-review.actions.send') })).isVisible();
});

test('it should have an inert trainings list', async function (assert) {
// then
const trainingsListTitle = screen.getByRole('heading', {
name: t('pages.skill-review.tabs.trainings.title'),
});
assert.dom(trainingsListTitle).isVisible();
assert.dom(trainingsListTitle.closest('[role="presentation"]')).hasAttribute('inert');
});

module('when clicking on the share results button', function (hooks) {
let adapter;

hooks.beforeEach(function () {
const store = this.owner.lookup('service:store');
adapter = store.adapterFor('campaign-participation-result');
});

test('it should call the share method of the adapter', async function (assert) {
// given
const createShareStub = sinon.stub(adapter, 'share');

// when
await click(screen.queryByRole('button', { name: t('pages.skill-review.actions.send') }));

// then
assert.ok(createShareStub.calledOnce);
sinon.assert.calledWithExactly(createShareStub, 1);
});

module('when share action succeeds', function () {
test('it hide the dialog and show the trainings list', async function (assert) {
// given
sinon.stub(adapter, 'share');

// when
await click(screen.queryByRole('button', { name: t('pages.skill-review.actions.send') }));

// then
assert.dom(screen.queryByRole('dialog')).doesNotExist();

const trainingsListTitle = screen.getByRole('heading', {
name: t('pages.skill-review.tabs.trainings.title'),
});
assert.dom(trainingsListTitle.closest('[role="presentation"]')).doesNotExist();
});
});

module('when share action fails', function () {
test('it should display an error message', async function (assert) {
// given
sinon.stub(adapter, 'share').rejects();

// when
await click(screen.queryByRole('button', { name: t('pages.skill-review.actions.send') }));

// then
assert.dom(screen.queryByRole('dialog')).exists();
assert.dom(screen.getByText(t('pages.skill-review.tabs.trainings.modal.share-error'))).exists();
});
});
});
});
});
6 changes: 5 additions & 1 deletion mon-pix/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1740,7 +1740,11 @@
"trainings": {
"title": "Want to learn more?",
"description": "Get personalized training recommendations to continue progressing and feed your curiosity to help you achieve your full potential.",
"tab-label": "Trainings"
"tab-label": "Trainings",
"modal": {
"content": "Send us your results to enable the course organizer to support you.'<br />'After sharing, you'll have access to these training courses!",
"share-error": "There was an error sending your results. Please try again."
}
}
},
"trainings": {
Expand Down
6 changes: 5 additions & 1 deletion mon-pix/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -1740,7 +1740,11 @@
"trainings": {
"title": "Vous souhaitez en apprendre plus ?",
"description": "Obtenez des recommandations de formations personnalisées pour continuer à progresser et nourrir votre curiosité pour vous aider à réaliser votre plein potentiel.",
"tab-label": "Formations"
"tab-label": "Formations",
"modal": {
"content": "Envoyez vos résultats pour permettre à l’organisateur du parcours de vous accompagner.'<br />'Après avoir partagé, vous bénéficierez d'un accès à ces formations&nbsp;!",
"share-error": "Il y a eu une erreur lors de l'envoi de vos résultats. Veuillez réessayer."
}
}
},
"trainings": {
Expand Down

0 comments on commit 8b993f0

Please sign in to comment.