-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(mon-pix): add trainings tab content
- Loading branch information
Showing
9 changed files
with
288 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
83 changes: 79 additions & 4 deletions
83
...ix/app/components/campaigns/assessment/skill-review/evaluation-results-tabs/trainings.gjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
52 changes: 52 additions & 0 deletions
52
...tyles/components/campaigns/assessment/skill-review/evaluation-results-tabs/trainings.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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%); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
136 changes: 136 additions & 0 deletions
136
.../tests/integration/components/campaigns/assessment/skill-review/rewards/trainings-test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 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(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters