project-booster-vue 10.22.26 → 10.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -15,7 +15,8 @@ Team: project-booster@adeo.com
15
15
  - ~~Sébastien Martinage~~
16
16
  - ~~Adrien Stadler~~
17
17
  - ~~Narjisse Loulanti~~
18
- - Ekaterina Kelekhsaeva: ekaterina.kelekhsaeva1@ext.adeo.com
18
+ - ~~Ekaterina Kelekhsaeva~~
19
+ - Yann Delaporte: yann.delaporte@ext.adeo.com
19
20
 
20
21
  #### Developers
21
22
 
@@ -29,10 +30,11 @@ Team: project-booster@adeo.com
29
30
  - ~~Clément Buchart~~
30
31
  - ~~Mickaël Margollé~~
31
32
  - ~~Jean-Baptiste Renault~~
32
- - Anthony Pillot: anthony.pillot@ext.leroymerlin.fr
33
- - Maxime Drecourt: maxime.drecourt@ext.adeo.com
34
- - Yassine Bourakba: yassine.bourakba@ext.adeo.com
33
+ - ~~Maxime Drecourt~~
34
+ - ~~Yassine Bourakba~~
35
+ - Anthony Pillot: anthony.pillot@ext.adeo.com
35
36
  - Samir Aliche: samir.aliche@ext.adeo.com
37
+ - Adrien Déprez: adrien.deprez@ext.adeo.com
36
38
 
37
39
  ## Get started
38
40
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "project-booster-vue",
3
- "version": "10.22.26",
3
+ "version": "10.23.0",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -50,19 +50,26 @@
50
50
  </template>
51
51
 
52
52
  <script lang="ts" setup>
53
- import { useStore } from 'vuex';
53
+ import { ScenarioStepAnswer } from '@/types/pb/Scenario';
54
54
  import { MButton, MLink } from '@mozaic-ds/vue-3';
55
- import { ScenarioProduct, ScenarioStepAnswer } from '@/types/pb/Scenario';
56
- import { defineProps, PropType, onMounted, ref, Ref, computed } from 'vue';
55
+ import { PropType, defineProps, onMounted, ref } from 'vue';
56
+ import { useStore } from 'vuex';
57
57
  import { PayloadAction } from '../types/genericPayload';
58
- import { formatEvent, EventTypeEnum } from '../services/event';
59
58
 
60
59
  const emit = defineEmits(['go-back', 'step-completed']);
61
60
 
62
61
  const store = useStore();
63
62
  const metadata = store.getters['metaData/metaData'];
64
63
  const refProduct = store.getters['products/getRefProduct'];
65
- const product = computed(() => store.getters['products/getCurrentProduct']);
64
+ const product = ref(store.getters['products/getCurrentProduct']);
65
+
66
+ if (!product.value) {
67
+ product.value = {
68
+ designation: 'Désignation par défaut',
69
+ photo: 'Photo par défaut',
70
+ value: 'Valeur par défaut',
71
+ };
72
+ }
66
73
 
67
74
  const props = defineProps({
68
75
  /**
@@ -12,8 +12,9 @@
12
12
  :left-icon="BACK_ICON"
13
13
  class="pb-restitution-list__back-button"
14
14
  @click.once="callAction(payload.backLabel.action)"
15
- >{{ payload.backLabel.label || "Recommencer l'estimation" }}</m-link
16
15
  >
16
+ {{ payload.backLabel.label || "Recommencer l'estimation" }}
17
+ </m-link>
17
18
  </m-flex>
18
19
  <div class="pb-restitution-list__title">{{ payload?.viewModel?.title }}</div>
19
20
 
@@ -40,33 +41,59 @@
40
41
  >
41
42
  <default>{{ notification.text }}</default>
42
43
  <footer>
43
- <MLink size="m" :href="notification.linkHref" target="_blank">
44
+ <m-link size="m" :href="notification.linkHref" target="_blank">
44
45
  {{ notification.linkLabel }}
45
- </MLink>
46
+ </m-link>
46
47
  </footer>
47
48
  </m-notification>
48
49
  </m-flex>
49
50
  </m-flex>
50
51
  </m-flex>
51
52
 
52
- <div class="pb-restitution-list__footer" direction="row" v-if="showButtonBar">
53
- <div class="pb-restitution-list__footer__call" v-for="button in payload.callToActions" :key="button.label">
54
- <m-button
55
- :label="button.label"
56
- @click="callAction(button.action)"
57
- :theme="button.bordered ? 'bordered' : 'solid'"
58
- v-if="areConditionsValid(button.conditions)"
59
- :data-cerberus="sanitizeCerberusAttribut('PB-RESTITUTION', button.label)"
60
- />
61
- </div>
62
- <div class="pb-restitution-list__footer__save">
63
- <pb-project-item-save
64
- v-model:show-save-item="showSaveProjectItem"
65
- @item-saved="handleItemCreated"
66
- @dialog-close="handleDialogClose"
67
- v-if="isLoggedIn"
68
- :data-cerberus="sanitizeCerberusAttribut('PB-RESTITUTION', 'save-estimate')"
69
- />
53
+ <div class="pb-restitution-list__footer" v-if="showButtonBar">
54
+ <div class="pb-restitution-list__footer__content">
55
+ <div class="pb-restitution-list__footer__content__call">
56
+ <div v-for="button in payload.callToActions" :key="button.label">
57
+ <m-button
58
+ class="pb-restitution-list__footer__content__call__button"
59
+ :label="button.label"
60
+ @click="callAction(button.action)"
61
+ :theme="button.bordered ? 'bordered' : 'solid'"
62
+ v-if="areConditionsValid(button.conditions)"
63
+ :data-cerberus="sanitizeCerberusAttribut('PB-RESTITUTION', button.label)"
64
+ />
65
+ </div>
66
+ <div class="pb-restitution-list__footer__content__save">
67
+ <pb-project-item-save
68
+ v-model:show-save-item="showSaveProjectItem"
69
+ @item-saved="handleItemCreated"
70
+ @dialog-close="handleDialogClose"
71
+ v-if="isLoggedIn"
72
+ :data-cerberus="sanitizeCerberusAttribut('PB-RESTITUTION', 'save-estimate')"
73
+ />
74
+ </div>
75
+ </div>
76
+ <div class="pb-restitution-list__footer__content__card" v-if="payload.cards">
77
+ <div class="pb-restitution-list__footer__content__card__item" v-for="card in payload.cards">
78
+ <m-card
79
+ outlined
80
+ v-bind="{
81
+ title: card.title,
82
+ imgSrc: card.image.src,
83
+ imgAlt: card.image.alt,
84
+ }"
85
+ >
86
+ <template v-slot:default>
87
+ <div>
88
+ <p>{{ card.text }}</p>
89
+ </div>
90
+ </template>
91
+ <template v-slot:footer>
92
+ <m-link size="m" :href="card.link.href">{{ card.link.label }}</m-link>
93
+ </template>
94
+ </m-card>
95
+ </div>
96
+ </div>
70
97
  </div>
71
98
  </div>
72
99
 
@@ -120,21 +147,21 @@
120
147
  </template>
121
148
 
122
149
  <script lang="ts">
123
- import { defineComponent, PropType } from 'vue';
124
- import { mapGetters } from 'vuex';
125
- import MFlex from '../../mozaic/flex/MFlex.vue';
126
- import PbProjectItemSave from '../../projects/project-item-save/PbProjectItemSave.vue';
150
+ import { sanitizeCerberusAttribut } from '@/services/sanitize';
127
151
  import { NotificationOptions } from '@/types/pb/Notification';
128
152
  import { RestitutionListPayload, RestitutionPayloadCallToAction } from '@/types/pb/Restitution';
129
153
  import { ScenarioStepAnswer } from '@/types/pb/Scenario';
130
- import PbRestitutionListBlock from './MPbRestitutionListBlock.vue';
131
- import { Project } from '../../../types/pb/Project';
154
+ import { MButton, MCard, MLink, MModal, MNotification } from '@mozaic-ds/vue-3';
155
+ import { PropType, defineComponent } from 'vue';
156
+ import { mapGetters } from 'vuex';
132
157
  import { areConditionsValid } from '../../../services/scenarioConditionals';
133
- import { MModal, MButton, MLink, MNotification } from '@mozaic-ds/vue-3';
158
+ import { Project } from '../../../types/pb/Project';
159
+ import MFlex from '../../mozaic/flex/MFlex.vue';
160
+ import PbProjectItemSave from '../../projects/project-item-save/PbProjectItemSave.vue';
161
+ import { EventTypeEnum, formatEvent } from '../services/event';
162
+ import PbRestitutionListBlock from './MPbRestitutionListBlock.vue';
134
163
  const BACK_ICON =
135
164
  'https://storage.googleapis.com/project-booster-media/mozaic-icons/svg/Navigation_Arrow_Arrow--Left_16px.svg';
136
- import { sanitizeCerberusAttribut } from '@/services/sanitize';
137
- import { formatEvent, EventTypeEnum } from '../services/event';
138
165
 
139
166
  export default defineComponent({
140
167
  components: {
@@ -145,6 +172,7 @@ export default defineComponent({
145
172
  PbRestitutionListBlock,
146
173
  PbProjectItemSave,
147
174
  MNotification,
175
+ MCard,
148
176
  },
149
177
  data() {
150
178
  return {
@@ -304,6 +332,7 @@ export default defineComponent({
304
332
  @import 'pb-variables';
305
333
 
306
334
  $responsive-breakpoint: 'm';
335
+
307
336
  .hidden {
308
337
  display: none;
309
338
  }
@@ -367,30 +396,53 @@ $responsive-breakpoint: 'm';
367
396
 
368
397
  &__footer {
369
398
  display: flex;
370
- flex-direction: column;
371
399
  justify-content: center;
372
- padding: $mu050;
373
400
 
374
- @include set-from-screen($responsive-breakpoint) {
375
- width: 720px;
376
- flex-direction: row;
377
- margin: 0 auto;
378
- }
401
+ &__content {
402
+ display: grid;
403
+ grid-template-columns: repeat(2, 1fr);
404
+ grid-template-areas: 'call' 'card';
405
+ row-gap: 2rem;
379
406
 
380
- &__call {
381
- width: 100%;
382
- margin: 0 0 $mu050 0;
407
+ justify-content: center;
383
408
 
384
- @include set-from-screen($responsive-breakpoint) {
385
- width: auto;
386
- margin: 0 $mu050 0 0;
387
- }
409
+ &__call {
410
+ grid-area: call;
411
+ grid-column: 1 / 3;
412
+
413
+ display: flex;
414
+ flex-direction: row;
415
+ justify-content: center;
388
416
 
389
- button {
390
417
  width: 100%;
391
418
 
392
- @include set-from-screen($responsive-breakpoint) {
393
- width: auto;
419
+ &__button {
420
+ width: 150px;
421
+ margin: 0 $mu100 0 $mu100;
422
+
423
+ @include set-from-screen($responsive-breakpoint) {
424
+ width: 280px;
425
+ }
426
+ }
427
+ }
428
+
429
+ &__card {
430
+ grid-area: card;
431
+ grid-column: 1 / 3;
432
+
433
+ row-gap: 1rem;
434
+
435
+ display: flex;
436
+ flex-direction: row;
437
+ justify-content: center;
438
+
439
+ &__item {
440
+ width: 150px;
441
+ margin: 0 $mu100 0 $mu100;
442
+
443
+ @include set-from-screen($responsive-breakpoint) {
444
+ width: 280px;
445
+ }
394
446
  }
395
447
  }
396
448
  }
@@ -583,4 +635,13 @@ $responsive-breakpoint: 'm';
583
635
  margin-top: $mu075;
584
636
  width: 100%;
585
637
  }
638
+
639
+ :deep(.mc-card__img) {
640
+ height: 100%;
641
+ object-fit: cover;
642
+ }
643
+
644
+ :deep(.mc-card--bordered) {
645
+ height: 100%;
646
+ }
586
647
  </style>
@@ -13,19 +13,10 @@
13
13
  ]
14
14
  },
15
15
  "callToActions": [
16
- {
17
- "type": "button",
18
- "label": "Être rappelé par un expert",
19
- "action": {
20
- "type": "STEP",
21
- "code": "STEP_CODE"
22
- },
23
- "bordered": false
24
- },
25
16
  {
26
17
  "conditions": ["runtimeOptions.projectMode === true"],
27
18
  "type": "button",
28
- "label": "J'enregistre mon estimation",
19
+ "label": "Enregistrer mon estimation",
29
20
  "bordered": true,
30
21
  "action": {
31
22
  "type": "MODAL",
@@ -35,13 +26,48 @@
35
26
  {
36
27
  "conditions": ["!runtimeOptions.projectMode && !runtimeOptions.estimateCreated"],
37
28
  "type": "button",
38
- "label": "J'enregistre mon estimation",
29
+ "label": "Enregistrer mon estimation",
39
30
  "action": {
40
31
  "type": "MODAL",
41
32
  "code": "SUMMARY",
42
33
  "component": "PbProjectItemSave"
43
34
  },
44
35
  "bordered": true
36
+ },
37
+ {
38
+ "type": "button",
39
+ "label": "Être rappelé par un expert",
40
+ "action": {
41
+ "type": "STEP",
42
+ "code": "STEP_CODE"
43
+ },
44
+ "bordered": false
45
+ }
46
+ ],
47
+ "cards": [
48
+ {
49
+ "title": "Concevoir ma salle de bain en 3D",
50
+ "text": "Concevez votre salle de bain vous-même avec notre configurateur 3D et finalisez votre projet en magasin.",
51
+ "image": {
52
+ "src": "https://storage.googleapis.com/project-booster-media/bathroom/exit-options/bathroom-3d.jpg",
53
+ "alt": "Concevoir ma salle de bain en 3D"
54
+ },
55
+ "link": {
56
+ "label": "Découvrir le configurateur 3D",
57
+ "href": "https://sdb3d.leroymerlin.fr/Page_Tunnel/tunnel-sdb_is6.html"
58
+ }
59
+ },
60
+ {
61
+ "title": "Prendre rendez-vous",
62
+ "text": "Vous avez les mesures de votre salle de bains ? Consultez un expert en magasin ou à distance pour finaliser votre projet.",
63
+ "image": {
64
+ "src": "https://storage.googleapis.com/project-booster-media/common/services/appointment.jpg",
65
+ "alt": "Prendre rendez-vous pour ma salle de bains"
66
+ },
67
+ "link": {
68
+ "label": "Prendre rendez-vous",
69
+ "href": "/services/realisez-votre-projet-salle-de-bains.html"
70
+ }
45
71
  }
46
72
  ]
47
73
  }
@@ -68,8 +68,8 @@ export interface RestitutionDialogViewModel {
68
68
 
69
69
  export interface RestitutionPayloadCallToAction {
70
70
  type: 'button' | 'link' | 'MODAL';
71
- conditions?: string[];
72
- label?: string;
71
+ conditions: string[];
72
+ label: string;
73
73
  message?: string;
74
74
  href?: string;
75
75
  bordered?: boolean;
@@ -88,7 +88,27 @@ export interface RestitutionListPayload {
88
88
  viewModel: RestitutionListViewModelPayload;
89
89
  callToActions: RestitutionPayloadCallToAction[];
90
90
  exitOptions: RestitutionExitOptions;
91
- backLabel: any;
91
+ backLabel: {
92
+ label: string;
93
+ action: {
94
+ type: string;
95
+ code: string;
96
+ };
97
+ };
98
+ cards: RestitutionListCard[];
99
+ }
100
+
101
+ export interface RestitutionListCard {
102
+ title: string;
103
+ text: string;
104
+ image: {
105
+ src: string;
106
+ alt: string;
107
+ };
108
+ link: {
109
+ href: string;
110
+ label: string;
111
+ };
92
112
  }
93
113
 
94
114
  export interface RestitutionListViewModelPayload {