Skip to content

Commit

Permalink
[FEATURE] Ajoute une page de loader avant les résultats de fin de par…
Browse files Browse the repository at this point in the history
…cours (PIX-14944).

 #10380
  • Loading branch information
pix-service-auto-merge authored Oct 24, 2024
2 parents 64254f5 + 40ee8af commit 02d5f73
Show file tree
Hide file tree
Showing 30 changed files with 442 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ Fonctionnalité: Campagne d'évaluation
Alors je vois l'épreuve "Qui a dit « Toute méchanceté a sa source dans la faiblesse » ?"
Lorsque je clique sur "Je passe"
Et je clique sur "Voir mes résultats"
Alors je vois la page de "chargement-resultats" de la campagne
Lorsque j'attends 3200 ms
Et je clique sur "Continuer"
Alors je vois un résultat global à 50%
Alors je vois 2 résultats pour la compétence
Lorsque je clique sur "J'envoie mes résultats"
Expand Down
100 changes: 100 additions & 0 deletions mon-pix/app/components/pages/campaigns/results-loader.gjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import PixButton from '@1024pix/pix-ui/components/pix-button';
import PixIcon from '@1024pix/pix-ui/components/pix-icon';
import { action } from '@ember/object';
import { service } from '@ember/service';
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { t } from 'ember-intl';
import { modifier } from 'ember-modifier';
import { gt } from 'ember-truth-helpers';

const callOnTrue = modifier((element, [action, value]) => {
if (value) {
action();
}
});

export default class ResultsLoader extends Component {
@service router;
@tracked steps = 1;
@tracked isButtonDisabled = true;

get lineAppearanceInterval() {
return this.args.lineAppearanceInterval ?? 1200;
}

get lineTransitionDuration() {
return this.args.lineTransitionDuration ?? 300;
}

get iconTransitionDuration() {
return this.args.iconTransitionDuration ?? 300;
}

constructor(...args) {
super(...args);
const interval = setInterval(() => {
this.steps++;
if (this.steps === 3) {
clearInterval(interval);
setTimeout(() => {
this.isButtonDisabled = false;
}, this.lineTransitionDuration + this.iconTransitionDuration);
}
}, this.lineAppearanceInterval);
}

@action
onClick() {
this.router.transitionTo('campaigns.assessment.skill-review', this.args.code);
}

<template>
<main role="main" class="results-loader">
<div class="results-loader__content">
<img class="results-loader__illustration" alt="" src="/images/illustrations/score-computation.svg" />
<h1 class="results-loader__title">{{t "components.campaigns.results-loader.title"}}</h1>
<p class="results-loader__subtitle">{{t "components.campaigns.results-loader.subtitle"}}</p>
<ul class="results-loader__steps">
<Line @visible={{true}} @iconTransitionDuration={{this.iconTransitionDuration}}>
{{t "components.campaigns.results-loader.steps.competences"}}
</Line>
<Line @visible={{gt this.steps 1}} @iconTransitionDuration={{this.iconTransitionDuration}}>
{{t "components.campaigns.results-loader.steps.trainings"}}
</Line>
<Line @visible={{gt this.steps 2}} @iconTransitionDuration={{this.iconTransitionDuration}}>
{{t "components.campaigns.results-loader.steps.rewards"}}
</Line>
</ul>

<PixButton
class="results-loader__button"
@isDisabled={{this.isButtonDisabled}}
@triggerAction={{this.onClick}}
>{{t "common.actions.continue"}}</PixButton>
</div>
</main>
</template>
}

class Line extends Component {
@tracked isIconDisplayed = false;

@action
displayIcon() {
setTimeout(() => {
this.isIconDisplayed = true;
}, this.args.iconTransitionDuration);
}

<template>
<li class="line {{if @visible 'line--visible'}}" {{callOnTrue this.displayIcon @visible}}>
<PixIcon
class="line__icon {{if this.isIconDisplayed 'line__icon--visible'}}"
@name="checkCircle"
@plainIcon={{true}}
/>
{{yield}}
</li>
</template>
}
81 changes: 81 additions & 0 deletions mon-pix/app/components/pages/campaigns/results-loader.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
.results-loader {
display: flex;
align-items: center;
justify-content: center;
width: 100vw;
height: 100vh;
padding: var(--pix-spacing-8x) var(--pix-spacing-2x);

&__illustration {
align-self: center;
min-width: 210px;
max-width: 320px;
}

@media (min-width: 767px) {
&__illustration {
min-width: 320px;
}
}

&__content {
display: flex;
flex-direction: column;
justify-content: center;
}

&__button,
&__steps {
width: fit-content;
margin: auto;
margin-top: var(--pix-spacing-6x);
}

&__title {
@extend %pix-title-m;

margin-top: var(--pix-spacing-8x);
color: var(--pix-neutral-900);
text-align: center;
}

&__subtitle {
@extend %pix-title-xs;

margin-top: var(--pix-spacing-2x);
color: var(--pix-neutral-500);
text-align: center;
}

&__button {
transition: opacity 300ms ease-in;
}

.line {
display: flex;
gap: var(--pix-spacing-2x);
margin-top: var(--pix-spacing-3x);
opacity: 0;
transition: opacity 150ms ease-in;

&--visible {
opacity: 1;
}

&__icon {
width: var(--pix-spacing-6x);
height: var(--pix-spacing-6x);
opacity: 0;
transition: opacity 300ms ease-in;
fill: var(--pix-success-500);

&--visible {
opacity: 1;
}
}

&:first-child {
margin-top: 0;
}
}
}
2 changes: 1 addition & 1 deletion mon-pix/app/models/campaign-participation-badge.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default class CampaignParticipationBadge extends Badge {
@attr('number') acquisitionPercentage;

// includes
@belongsTo('campaignParticipationResult', {
@belongsTo('campaign-participation-result', {
async: true,
inverse: 'campaignParticipationBadges',
})
Expand Down
6 changes: 3 additions & 3 deletions mon-pix/app/models/campaign-participation-result.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default class CampaignParticipationResult extends Model {
@attr('number') flashPixScore;

// includes
@hasMany('campaignParticipationBadges', {
@hasMany('campaign-participation-badge', {
async: false,
inverse: 'campaignParticipationResult',
})
Expand All @@ -26,9 +26,9 @@ export default class CampaignParticipationResult extends Model {
return this.campaignParticipationBadges.filter((badge) => badge.isAcquired);
}

@hasMany('competenceResult', { async: false, inverse: 'campaignParticipationResult' }) competenceResults;
@hasMany('competence-result', { async: false, inverse: 'campaignParticipationResult' }) competenceResults;

@belongsTo('reachedStage', { async: false, inverse: 'campaignParticipationResult' }) reachedStage;
@belongsTo('reached-stage', { async: false, inverse: 'campaignParticipationResult' }) reachedStage;

get hasReachedStage() {
return this.reachedStage !== null;
Expand Down
2 changes: 1 addition & 1 deletion mon-pix/app/models/campaign-participation.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default class CampaignParticipation extends Model {
// includes
@belongsTo('assessment', { async: true, inverse: null }) assessment;
@belongsTo('campaign', { async: true, inverse: null }) campaign;
@belongsTo('campaignParticipationResult', { async: true, inverse: null }) campaignParticipationResult;
@belongsTo('campaign-participation-result', { async: true, inverse: null }) campaignParticipationResult;
@belongsTo('user', { async: true, inverse: null }) user;

@hasMany('training', { async: true, inverse: 'campaignParticipation' }) trainings;
Expand Down
3 changes: 2 additions & 1 deletion mon-pix/app/models/competence-result.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ export default class CompetenceResult extends Model {
@attr('number') reachedStage;

// includes
@belongsTo('campaignParticipationResult', { async: true, inverse: 'competenceResults' }) campaignParticipationResult;
@belongsTo('campaign-participation-result', { async: true, inverse: 'competenceResults' })
campaignParticipationResult;

get masteryRate() {
return this.masteryPercentage / 100;
Expand Down
1 change: 1 addition & 0 deletions mon-pix/app/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ Router.map(function () {
this.route('fill-in-participant-external-id', { path: '/identifiant' });
});
this.route('entrance', { path: '/entree' });
this.route('results-loader', { path: '/chargement-resultats' });
this.route('profiles-collection', { path: '/collecte' }, function () {
this.route('start-or-resume', { path: '/' });
this.route('send-profile', { path: '/envoi-profil' });
Expand Down
2 changes: 1 addition & 1 deletion mon-pix/app/routes/assessments/resume.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export default class ResumeRoute extends Route {
if (assessment.isCertification) {
this.router.replaceWith('authenticated.certifications.results', assessment.certificationNumber);
} else if (assessment.isForCampaign) {
this.router.replaceWith('campaigns.assessment.skill-review', assessment.codeCampaign);
this.router.replaceWith('campaigns.results-loader', assessment.codeCampaign);
} else if (assessment.isCompetenceEvaluation) {
this.router.replaceWith('authenticated.competences.results', assessment.competenceId, assessment.id);
} else {
Expand Down
2 changes: 1 addition & 1 deletion mon-pix/app/routes/campaigns/access.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export default class AccessRoute extends Route {
}

async afterModel(campaign) {
const ongoingCampaignParticipation = await this.store.queryRecord('campaignParticipation', {
const ongoingCampaignParticipation = await this.store.queryRecord('campaign-participation', {
campaignId: campaign.id,
userId: this.currentUser.user.id,
});
Expand Down
2 changes: 1 addition & 1 deletion mon-pix/app/routes/campaigns/assessment.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default class AssessmentRoute extends Route {

async model() {
const campaign = this.modelFor('campaigns');
const campaignParticipation = await this.store.queryRecord('campaignParticipation', {
const campaignParticipation = await this.store.queryRecord('campaign-participation', {
campaignId: campaign.id,
userId: this.currentUser.user.id,
});
Expand Down
2 changes: 1 addition & 1 deletion mon-pix/app/routes/campaigns/assessment/skill-review.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default class SkillReviewRoute extends Route {
const user = this.currentUser.user;
const { campaignParticipation, campaign } = this.modelFor('campaigns.assessment');
try {
const campaignParticipationResult = await this.store.queryRecord('campaignParticipationResult', {
const campaignParticipationResult = await this.store.queryRecord('campaign-participation-result', {
campaignId: campaign.id,
userId: user.id,
});
Expand Down
2 changes: 1 addition & 1 deletion mon-pix/app/routes/campaigns/entrance.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export default class Entrance extends Route {
}

async shouldBeginCampaignParticipation(campaign) {
const ongoingCampaignParticipation = await this.store.queryRecord('campaignParticipation', {
const ongoingCampaignParticipation = await this.store.queryRecord('campaign-participation', {
campaignId: campaign.id,
userId: this.currentUser.user.id,
});
Expand Down
2 changes: 1 addition & 1 deletion mon-pix/app/routes/campaigns/entry-point.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export default class EntryPoint extends Route {
let hasParticipated = false;
if (this.session.isAuthenticated) {
const currentUserId = this.currentUser.user.id;
const ongoingCampaignParticipation = await this.store.queryRecord('campaignParticipation', {
const ongoingCampaignParticipation = await this.store.queryRecord('campaign-participation', {
campaignId: campaign.id,
userId: currentUserId,
});
Expand Down
2 changes: 1 addition & 1 deletion mon-pix/app/routes/campaigns/profiles-collection.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default class ProfilesCollectionRoute extends Route {

async model() {
const campaign = this.modelFor('campaigns');
const campaignParticipation = await this.store.queryRecord('campaignParticipation', {
const campaignParticipation = await this.store.queryRecord('campaign-participation', {
campaignId: campaign.id,
userId: this.currentUser.user.id,
});
Expand Down
36 changes: 36 additions & 0 deletions mon-pix/app/routes/campaigns/results-loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import Route from '@ember/routing/route';
import { service } from '@ember/service';

export default class ResultsLoaderRoute extends Route {
@service currentUser;
@service session;
@service router;
@service store;

beforeModel(transition) {
this.session.requireAuthenticationAndApprovedTermsOfService(transition);
}

async model() {
const campaign = this.modelFor('campaigns');
const campaignParticipation = await this.store.queryRecord('campaign-participation', {
campaignId: campaign.id,
userId: this.currentUser.user.id,
});
return {
campaign,
campaignParticipation,
};
}

async afterModel({ campaign, campaignParticipation }) {
const assessment = await campaignParticipation?.assessment;

if (!campaignParticipation) {
this.router.replaceWith('campaigns.campaign-landing-page', campaign.code);
} else if (campaignParticipation.isShared) {
this.router.replaceWith('campaigns.assessment.skill-review', campaign.code);
} else if (campaignParticipation && !assessment.isCompleted)
this.router.replaceWith('campaigns.assessment.start-or-resume', campaign.code);
}
}
1 change: 1 addition & 0 deletions mon-pix/app/styles/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
@import 'components/circle-chart';
@import 'components/comparison-window';
@import 'components/choice-chip';
@import 'components/pages/campaigns/results-loader';
@import 'components/reset-campaign-participation-modal';
@import 'components/tabs';

Expand Down
1 change: 1 addition & 0 deletions mon-pix/app/templates/campaigns/results-loader.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<Pages::Campaigns::ResultsLoader @code={{@model.campaign.code}} />
Loading

0 comments on commit 02d5f73

Please sign in to comment.