Skip to content

Commit af733d2

Browse files
[FEATURE] Page résultats de campagne : afficher les badges obtenus sur le total des participations (PIX-16241)
#11387
2 parents 483e385 + 2de0e98 commit af733d2

File tree

23 files changed

+300
-38
lines changed

23 files changed

+300
-38
lines changed

api/db/seeds/data/team-contenu/data-builder.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ async function _createCoreTargetProfile(databaseBuilder) {
193193
cappedTubesDTO,
194194
badgeId: 600,
195195
altMessage: '1 RT double critère Campaign & Tubes',
196-
imageUrl: 'some_image.svg',
196+
imageUrl: 'https://images.pix.fr/badges/Logos_badge_Prêt-CléA_Num NEW 2020.svg',
197197
message: '1 RT double critère Campaign & Tubes',
198198
title: '1 RT double critère Campaign & Tubes',
199199
key: 'SOME_KEY_FOR_RT_600',
@@ -207,7 +207,7 @@ async function _createCoreTargetProfile(databaseBuilder) {
207207
cappedTubesDTO,
208208
badgeId: 601,
209209
altMessage: '1 RT simple critère Campaign',
210-
imageUrl: 'some_other_image.svg',
210+
imageUrl: 'https://images.pix.fr/badges/Pix_plus_Droit-%20Pret-certif_Bronze--Initie.svg',
211211
message: '1 RT simple critère Campaign',
212212
title: '1 RT simple critère Campaign',
213213
key: 'SOME_KEY_FOR_RT_601',

api/db/seeds/data/team-evaluation/data-builder.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ async function createCoreTargetProfile(databaseBuilder) {
9494
cappedTubesDTO,
9595
badgeId: 700,
9696
altMessage: '1 RT double critère Campaign & Tubes',
97-
imageUrl: 'some_image.svg',
97+
imageUrl: 'https://images.pix.fr/badges/Logos_badge_Prêt-CléA_Num NEW 2020.svg',
9898
message: '1 RT double critère Campaign & Tubes',
9999
title: '1 RT double critère Campaign & Tubes',
100100
key: 'SOME_KEY_FOR_RT_700',
@@ -108,7 +108,7 @@ async function createCoreTargetProfile(databaseBuilder) {
108108
cappedTubesDTO,
109109
badgeId: 701,
110110
altMessage: '1 RT simple critère Campaign',
111-
imageUrl: 'some_other_image.svg',
111+
imageUrl: 'https://images.pix.fr/badges/Pix_plus_Droit-%20Pret-certif_Bronze--Initie.svg',
112112
message: '1 RT simple critère Campaign',
113113
title: '1 RT simple critère Campaign',
114114
key: 'SOME_KEY_FOR_RT_701',

api/db/seeds/data/team-prescription/build-target-profiles.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ async function _createTargetProfileWithBadgesStages(databaseBuilder) {
5959
cappedTubesDTO,
6060
badgeId: BADGES_TUBES_CAMP_ID,
6161
altMessage: '1 RT double critère Campaign & Tubes',
62-
imageUrl: 'https://images.pix.fr/badges/Badge_OLYMPIX.svg',
63-
message: '1 RT double critère Campaign & Tubes 60/50',
64-
title: '1 RT double critère Campaign & Tubes 60/50',
62+
imageUrl: 'https://images.pix.fr/badges/Logos_badge_Prêt-CléA_Num NEW 2020.svg',
63+
message: '1 RT double critère Campaign & Tubes',
64+
title: '1 RT double critère Campaign & Tubes',
6565
key: `SOME_KEY_FOR_RT_${BADGES_TUBES_CAMP_ID}`,
6666
isCertifiable: false,
6767
isAlwaysVisible: true,
@@ -85,9 +85,9 @@ async function _createTargetProfileWithBadgesStages(databaseBuilder) {
8585
cappedTubesDTO,
8686
badgeId: BADGES_CAMP_ID,
8787
altMessage: '1 RT simple critère Campaign',
88-
imageUrl: 'https://images.pix.fr/badges/Badge_Pixome%CC%80tre-Lune.svg',
89-
message: '1 RT simple critère Campaign 20',
90-
title: '1 RT simple critère Campaign 20',
88+
imageUrl: 'https://images.pix.fr/badges/Pix_plus_Droit-%20Pret-certif_Bronze--Initie.svg',
89+
message: '1 RT simple critère Campaign',
90+
title: '1 RT simple critère Campaign',
9191
key: `SOME_KEY_FOR_RT_${BADGES_CAMP_ID}`,
9292
isCertifiable: false,
9393
isAlwaysVisible: true,

api/src/prescription/campaign/domain/read-models/BadgeAcquisitionParticipationStatistic.js

+1-5
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@ export default class BadgeAcquisitionParticipationStatistic {
22
constructor({ badge, count, totalParticipationCount }) {
33
this.badge = badge;
44
this.count = count;
5-
this.totalParticipationCount = totalParticipationCount;
6-
}
7-
8-
get percentage() {
9-
return this.totalParticipationCount === 0 ? 0 : Math.round((this.count / this.totalParticipationCount) * 100);
5+
this.percentage = totalParticipationCount === 0 ? 0 : Math.round((count / totalParticipationCount) * 100);
106
}
117
}

api/src/prescription/campaign/infrastructure/serializers/jsonapi/badge-acquisitions-statistics-serializer.js

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ const serialize = (model) =>
99
data: {
1010
attributes: ['badge', 'count', 'percentage'],
1111
},
12+
transform(record) {
13+
record.data = record.data.sort((a, b) => b.percentage - a.percentage);
14+
return record;
15+
},
1216
}).serialize(model);
1317

1418
export { serialize };

api/tests/prescription/campaign/unit/infrastructure/serializers/jsonapi/badge-acquisitions-statistics-serializer_test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ describe('Unit | Serializer | JSONAPI | badge-acquisitions-statistics-serializer
2222
id: '1',
2323
attributes: {
2424
data: [
25-
{ badge: badge1, percentage: 12, count: 1 },
2625
{ badge: badge2, percentage: 24, count: 2 },
26+
{ badge: badge1, percentage: 12, count: 1 },
2727
],
2828
},
2929
},

orga/app/adapters/campaign-stats.js

+5
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,9 @@ export default class CampaignStatsAdapter extends ApplicationAdapter {
2020
const url = `${this.host}/${this.namespace}/campaigns/${campaignId}/stats/participations-by-mastery-rate`;
2121
return this.ajax(url, 'GET');
2222
}
23+
24+
getBadgeAcquisitions(campaignId) {
25+
const url = `${this.host}/${this.namespace}/campaigns/${campaignId}/stats/badge-acquisitions`;
26+
return this.ajax(url, 'GET');
27+
}
2328
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import PixTooltip from '@1024pix/pix-ui/components/pix-tooltip';
2+
import { service } from '@ember/service';
3+
import Component from '@glimmer/component';
4+
import { tracked } from '@glimmer/tracking';
5+
import { t } from 'ember-intl';
6+
7+
import ChartCard from '../../ui/chart-card';
8+
9+
export default class CampaignBadgeAcquisitions extends Component {
10+
@service store;
11+
12+
@tracked data = [];
13+
@tracked totalStage = [];
14+
@tracked loading = true;
15+
16+
constructor(...args) {
17+
super(...args);
18+
const { campaignId } = this.args;
19+
20+
const adapter = this.store.adapterFor('campaign-stats');
21+
adapter.getBadgeAcquisitions(campaignId).then((response) => {
22+
this.data = response.data.attributes.data;
23+
});
24+
}
25+
26+
<template>
27+
<ChartCard class="badge-acquisitions" @title={{t "cards.badges-acquisitions.title"}} @info={{true}} ...attributes>
28+
<ul class="badge-acquisitions__list">
29+
{{#each this.data as |badgeAcquisition|}}
30+
<li class="badge-acquisitions__list-item">
31+
<PixTooltip @id="badge-tooltip-{{badgeAcquisition.badge.id}}" @position="left" @isInline={{true}}>
32+
<:triggerElement>
33+
<img
34+
src={{badgeAcquisition.badge.imageUrl}}
35+
alt={{badgeAcquisition.badge.altMessage}}
36+
tabindex="0"
37+
aria-describedby="badge-tooltip-{{badgeAcquisition.badge.id}}"
38+
/>
39+
</:triggerElement>
40+
<:tooltip>
41+
{{badgeAcquisition.badge.title}}
42+
</:tooltip>
43+
</PixTooltip>
44+
<span class="badge-acquisitions__count">
45+
{{badgeAcquisition.count}}
46+
</span>
47+
<span class="badge-acquisitions__percentage">
48+
{{t "cards.badges-acquisitions.obtained"}}
49+
({{badgeAcquisition.percentage}}%)
50+
</span>
51+
</li>
52+
{{/each}}
53+
</ul>
54+
</ChartCard>
55+
</template>
56+
}
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1+
import CampaignBadgeAcquisitions from '../charts/campaign-badge-acquisitions';
12
import ParticipantsByMasteryPercentage from './participants-by-mastery-percentage';
23
import ParticipantsByStage from './participants-by-stage';
34

45
<template>
5-
{{#if @campaign.hasStages}}
6-
<ParticipantsByStage
7-
@campaignId={{@campaign.id}}
8-
@onSelectStage={{@onSelectStage}}
9-
class="assessment-results__charts hide-on-mobile"
10-
/>
11-
{{else}}
12-
<ParticipantsByMasteryPercentage @campaignId={{@campaign.id}} class="assessment-results__charts hide-on-mobile" />
13-
{{/if}}
6+
<div class="stats">
7+
{{#if @campaign.hasStages}}
8+
<ParticipantsByStage @campaignId={{@campaign.id}} @onSelectStage={{@onSelectStage}} class="participants" />
9+
{{else}}
10+
<ParticipantsByMasteryPercentage @campaignId={{@campaign.id}} class="participants hide-on-mobile" />
11+
{{/if}}
12+
{{#if @campaign.hasBadges}}
13+
<CampaignBadgeAcquisitions @campaignId={{@campaign.id}} />
14+
{{/if}}
15+
</div>
1416
</template>

orga/app/components/copy-paste-button.hbs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{{#if (is-clipboard-supported)}}
22
<PixTooltip
33
@id="copy-paste-button"
4-
@position="top"
4+
@position="left"
55
@isInline={{true}}
66
class="copy-paste-button__tooltip hide-on-mobile"
77
>

orga/app/components/ui/chart-card.gjs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import PixIcon from '@1024pix/pix-ui/components/pix-icon';
2+
import PixTooltip from '@1024pix/pix-ui/components/pix-tooltip';
3+
import { t } from 'ember-intl';
4+
5+
<template>
6+
<section class="chart-card" ...attributes>
7+
<h3 class="chart-card__title">
8+
{{@title}}
9+
{{#if @info}}<PixTooltip @isWide={{true}} @position="left">
10+
<:triggerElement>
11+
<PixIcon @name="help" class="chart-card__tooltip-icon" @plainIcon={{true}} @ariaHidden={{true}} />
12+
</:triggerElement>
13+
<:tooltip>
14+
{{t "cards.badges-acquisitions.information"}}
15+
</:tooltip>
16+
</PixTooltip>{{/if}}
17+
</h3>
18+
{{yield}}
19+
</section>
20+
</template>

orga/app/components/ui/chart-card.hbs

-6
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
@use 'pix-design-tokens/typography';
2+
@use 'pix-design-tokens/breakpoints';
3+
4+
.badge-acquisitions {
5+
@include breakpoints.device-is('desktop') {
6+
width: 33.33%;
7+
}
8+
9+
width: 100%;
10+
11+
&__list {
12+
display: grid;
13+
grid-row-gap: var(--pix-spacing-1x);
14+
grid-column-gap: var(--pix-spacing-4x);
15+
grid-template-rows: repeat(1, 1fr);
16+
grid-template-columns: repeat(2, 1fr);
17+
width: fit-content;
18+
19+
li:nth-child(4n) {
20+
flex-basis: 100%;
21+
}
22+
}
23+
24+
&__count{
25+
@extend %pix-title-xs;
26+
}
27+
28+
&__percentage {
29+
@extend %pix-body-xs;
30+
}
31+
32+
&__list-item {
33+
display: flex;
34+
gap: var(--pix-spacing-2x);
35+
align-items: center;
36+
height: 40px;
37+
font-weight: 700;
38+
39+
img {
40+
width: 32px;
41+
height: 36px;
42+
}
43+
44+
}
45+
}

orga/app/styles/components/campaign/charts/participants-by-stage.scss

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
@use 'pix-design-tokens/breakpoints';
2+
13
.participants-by-stage {
24
position: relative;
35
display: flex;
@@ -33,6 +35,10 @@
3335
}
3436

3537
&__container {
38+
@include breakpoints.device-is('mobile') {
39+
display: none;
40+
}
41+
3642
flex-grow: 1;
3743

3844
.pix-tooltip__content {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
@use 'pix-design-tokens/breakpoints';
2+
3+
.stats {
4+
@include breakpoints.device-is('desktop') {
5+
flex-direction: row;
6+
}
7+
8+
display: flex;
9+
flex-direction: column;
10+
gap: var(--pix-spacing-6x);
11+
align-items: stretch;
12+
margin-bottom: var(--pix-spacing-6x);
13+
}
14+
15+
.participants {
16+
@include breakpoints.device-is('desktop') {
17+
width: calc(66.66% - var(--pix-spacing-6x));
18+
}
19+
20+
width: 100%;
21+
}

orga/app/styles/components/campaign/index.scss

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
@use 'charts/participants-by-day';
1010
@use 'charts/participants-by-mastery-percentage';
1111
@use 'charts/participants-by-stage';
12+
@use 'charts/results-distribution';
13+
@use 'charts/campaign-badge-acquisitions';
1214
@use 'charts/participants-by-status';
1315
@use 'header/tabs';
1416
@use 'header/title';

orga/app/styles/components/ui/cards.scss

+9
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,17 @@
1313
&__title {
1414
@extend %pix-title-xs;
1515

16+
display: flex;
17+
gap: 4px;
1618
margin-top: 0;
1719
margin-bottom: 32px;
1820
color: var(--pix-neutral-500);
1921
}
22+
23+
&__tooltip-icon {
24+
width: 1rem;
25+
height:1rem;
26+
margin: 0 var(--pix-spacing-2x);
27+
fill: var(--pix-neutral-500);
28+
}
2029
}

orga/app/styles/pages/authenticated/campaigns/details/assessment-results.scss

-6
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,4 @@
77
filter: grayscale(1);
88
}
99
}
10-
11-
&__charts {
12-
margin-bottom: 24px;
13-
}
14-
15-
1610
}

0 commit comments

Comments
 (0)