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 committed Sep 20, 2024
1 parent 8541cbd commit 70cdb10
Show file tree
Hide file tree
Showing 10 changed files with 284 additions and 12 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,6 +14,8 @@ import QuitResults from '../../../campaigns/assessment/skill-review/quit-results
</header>
<EvaluationResultsTabs
@badges={{@model.campaignParticipationResult.campaignParticipationBadges}}
@campaignParticipationResultId={{@model.campaignParticipationResult.id}}
@isParticipationShared={{@model.campaignParticipationResult.isShared}}
@trainings={{@model.trainings}}
/>
</div>
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,4 +1,5 @@
@import 'assessment/skill-review/quit-results';
@import 'assessment/skill-review/share-badge-icons';
@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 @@ -73,7 +73,7 @@ module('Integration | Components | Campaigns | Assessment | Skill Review | Evalu

this.set('badges', []);

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,130 @@
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 works', 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();
});
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ module('Integration | Components | Routes | Campaigns | Assessment | Evaluation

this.set('model', {
campaign,
campaignParticipationResult: { campaignParticipationBadges: [] },
trainings: [Symbol('training')],
campaignParticipationResult: { campaignParticipationBadges: [Symbol('badge')] },
trainings: [],
});

// when
Expand Down
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 70cdb10

Please sign in to comment.