project-booster-vue 10.0.1 → 10.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "project-booster-vue",
3
- "version": "10.0.1",
3
+ "version": "10.2.0",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -40,7 +40,7 @@
40
40
  <div v-for="button in payload.callToActions" class="m-pb-alert__buttons__button row-flex">
41
41
  <m-button
42
42
  :label="button.label"
43
- @click="callAction(button.nextStep)"
43
+ @click="callAction(button)"
44
44
  :theme="button.theme"
45
45
  :icon="button.icon"
46
46
  :iconPosition="button.iconPosition"
@@ -76,6 +76,7 @@ import { MNotification, MButton, MCard, MModal } from '@mozaic-ds/vue-3';
76
76
  import { PayloadAction } from '../types/genericPayload';
77
77
  import { sanitizeCerberusAttribut } from '@/services/sanitize';
78
78
  import { ref } from 'vue';
79
+ import { ButtonType, EventName, sendAnalyticEvent } from '../services/event';
79
80
 
80
81
  const emit = defineEmits(['go-back', 'step-completed']);
81
82
  const showModal = ref(false);
@@ -100,6 +101,12 @@ const handleCloseModal = () => {
100
101
  };
101
102
 
102
103
  const handleShowModal = (option: any) => {
104
+ sendAnalyticEvent(EventName.CLICK, {
105
+ button_name: option.viewModel.button.label || '',
106
+ button_location: '',
107
+ button_type: ButtonType.ACTION,
108
+ });
109
+
103
110
  if (option.viewModel.button.dialog) {
104
111
  showModal.value = true;
105
112
  titleModal.value = option.viewModel.title;
@@ -113,11 +120,17 @@ const handleShowModal = (option: any) => {
113
120
  * Send action to completed step
114
121
  * @param action
115
122
  */
116
- const callAction = (action: PayloadAction) => {
117
- if (action.code != '__BACK__') {
123
+ const callAction = (button: PayloadAction) => {
124
+ sendAnalyticEvent(EventName.CLICK, {
125
+ button_name: button.label || '',
126
+ button_location: '',
127
+ button_type: ButtonType.ACTION,
128
+ });
129
+
130
+ if (button.code != '__BACK__') {
118
131
  emit('step-completed', {
119
132
  answers: null,
120
- nextStep: action,
133
+ nextStep: button,
121
134
  });
122
135
  } else {
123
136
  emit('go-back');
@@ -72,7 +72,7 @@
72
72
  <m-button
73
73
  :label="payload.viewModel.nextStep.label"
74
74
  :data-cerberus="sanitizeCerberusAttribut('MPB-EXIT-OPTIONS', 'NEXT')"
75
- @click="callAction(payload.viewModel.nextStep)"
75
+ @click="callAction(payload.viewModel.nextStep, payload.viewModel.nextStep.label)"
76
76
  icon="ArrowNext48"
77
77
  iconPosition="right"
78
78
  />
@@ -88,6 +88,7 @@ import { PayloadAction } from '../types/genericPayload';
88
88
  import { areConditionsValid } from '../../../services/scenarioConditionals';
89
89
  import { sanitizeCerberusAttribut } from '@/services/sanitize';
90
90
  import { ScenarioStepAnswer } from '@/types/pb/Scenario';
91
+ import { ButtonType, EventName, sendAnalyticEvent } from '../services/event';
91
92
 
92
93
  const emit = defineEmits(['go-back', 'step-completed']);
93
94
  const message = ref('');
@@ -122,7 +123,13 @@ const props = defineProps({
122
123
  * Send action to completed step
123
124
  * @param action
124
125
  */
125
- const callAction = (action: PayloadAction) => {
126
+ const callAction = (action: PayloadAction, label: string) => {
127
+ sendAnalyticEvent(EventName.CLICK, {
128
+ button_name: label || '',
129
+ button_location: '',
130
+ button_type: ButtonType.ACTION,
131
+ });
132
+
126
133
  if (action.code != '__BACK__') {
127
134
  emit('step-completed', {
128
135
  answers: [
@@ -389,6 +389,7 @@ import {
389
389
  ScenarioStepDialog,
390
390
  ScenarioStepAnswerNotification,
391
391
  } from '@/types/pb/Scenario';
392
+ import { sendAnalyticEvent, EventName, ButtonType } from '../services/event';
392
393
 
393
394
  const BACK_ICON =
394
395
  'https://storage.googleapis.com/project-booster-media/mozaic-icons/svg/Navigation_Arrow_Arrow--Left_16px.svg';
@@ -630,15 +631,6 @@ export default defineComponent({
630
631
  this.selectedAnswers.set(answerCode, false);
631
632
  });
632
633
  this.selectedAnswers.set(answer.code, !this.selectedAnswers.get(answer.code) ?? true);
633
-
634
- /**
635
- * Emitted when step is completed
636
- * @event dynamic event name according to completedEventName prop
637
- */
638
- // this.$emit(this.completedEventName, {
639
- // answers: [answer],
640
- // nextStep: answer.nextStep,
641
- // });
642
634
  }
643
635
 
644
636
  this.$nextTick(() => {
@@ -666,6 +658,12 @@ export default defineComponent({
666
658
  }
667
659
  }
668
660
 
661
+ sendAnalyticEvent(EventName.FIELD, {
662
+ field_name: multiSelectOptions?.label || '',
663
+ field_value: answers,
664
+ funnel_name: this.payload.analytics.funnel_name,
665
+ });
666
+
669
667
  this.$emit(this.completedEventName, {
670
668
  answers: answers,
671
669
  nextStep: multiSelectOptions?.nextStep,
@@ -785,6 +783,14 @@ export default defineComponent({
785
783
  },
786
784
  },
787
785
  });
786
+
787
+ if (answer.viewModel) {
788
+ sendAnalyticEvent(EventName.CLICK, {
789
+ button_name: answer.viewModel?.title || '',
790
+ button_location: '',
791
+ button_type: ButtonType.ACTION,
792
+ });
793
+ }
788
794
  },
789
795
  displayVideoGuide(origin: string | undefined) {
790
796
  this.displayDialog = true;
@@ -123,6 +123,7 @@ import { ScenarioStepAnswer } from '@/types/pb/Scenario';
123
123
  import { Configuration } from '@/types/pb/Configuration';
124
124
  import { decorate } from '@/services/decorate';
125
125
  import { PayloadAction } from '../../types/genericPayload';
126
+ import { ButtonType, EventName, sendAnalyticEvent } from '../../services/event';
126
127
 
127
128
  const BACK_ICON =
128
129
  'https://storage.googleapis.com/project-booster-media/mozaic-icons/svg/Navigation_Arrow_Arrow--Left_16px.svg';
@@ -203,6 +204,12 @@ export default defineComponent({
203
204
  const configurationImportError = ref(false);
204
205
 
205
206
  const navigateTo = (viewModel: ConfigurationsImportViewModel) => {
207
+ sendAnalyticEvent(EventName.CLICK, {
208
+ button_name: viewModel.label || '',
209
+ button_location: '',
210
+ button_type: ButtonType.ACTION,
211
+ });
212
+
206
213
  if (viewModel.backLink) {
207
214
  (<any>window).location = decorate(props.answers, props.runtimeOptions, viewModel.backLink);
208
215
  } else {
@@ -239,6 +246,12 @@ export default defineComponent({
239
246
  };
240
247
 
241
248
  const skipQuestion = (button: ConfigurationsImportSkippable) => {
249
+ sendAnalyticEvent(EventName.CLICK, {
250
+ button_name: button.label || '',
251
+ button_location: '',
252
+ button_type: ButtonType.ACTION,
253
+ });
254
+
242
255
  store.dispatch('sendEventToBus', { code: 'SKIP-IMPORT-SIMULATIONS', payload: { projectId: projectId.value } });
243
256
  emit(props.completedEventName, {
244
257
  answers: {},
@@ -247,6 +260,12 @@ export default defineComponent({
247
260
  };
248
261
 
249
262
  const validMultiSelect = (multiSelectOptions: ConfigurationsImportMultiSelectAction) => {
263
+ sendAnalyticEvent(EventName.CLICK, {
264
+ button_name: multiSelectOptions.label || '',
265
+ button_location: '',
266
+ button_type: ButtonType.ACTION,
267
+ });
268
+
250
269
  emit(props.completedEventName, {
251
270
  answers: selectedConfigurations.value,
252
271
  nextStep: multiSelectOptions.nextStep,
@@ -254,6 +273,12 @@ export default defineComponent({
254
273
  };
255
274
 
256
275
  const callAction = (action: PayloadAction) => {
276
+ sendAnalyticEvent(EventName.CLICK, {
277
+ button_name: action.label || '',
278
+ button_location: '',
279
+ button_type: ButtonType.ACTION,
280
+ });
281
+
257
282
  if (action.code != '__BACK__') {
258
283
  emit('step-completed', {
259
284
  answers: [],
@@ -132,6 +132,7 @@ import {
132
132
  import { ScenarioStepAnswer } from '@/types/pb/Scenario';
133
133
  import { decorate, doEval } from '@/services/decorate';
134
134
  import { PayloadAction } from '../../types/genericPayload';
135
+ import { ButtonType, EventName, sendAnalyticEvent } from '../../services/event';
135
136
 
136
137
  const BACK_ICON =
137
138
  'https://storage.googleapis.com/project-booster-media/mozaic-icons/svg/Navigation_Arrow_Arrow--Left_16px.svg';
@@ -234,6 +235,12 @@ export default defineComponent({
234
235
  });
235
236
 
236
237
  const navigateTo = (viewModel: UploadDocumentViewModel) => {
238
+ sendAnalyticEvent(EventName.CLICK, {
239
+ button_name: viewModel.label || '',
240
+ button_location: '',
241
+ button_type: ButtonType.ACTION,
242
+ });
243
+
237
244
  if (viewModel.backLink) {
238
245
  window.location = doEval(props.answers, viewModel.backLink, '', props.runtimeOptions);
239
246
  } else {
@@ -252,6 +259,12 @@ export default defineComponent({
252
259
  };
253
260
 
254
261
  const validMultiSelect = (multiSelectOptions: UploadDocumentMultiSelectAction) => {
262
+ sendAnalyticEvent(EventName.CLICK, {
263
+ button_name: multiSelectOptions.label || '',
264
+ button_location: '',
265
+ button_type: ButtonType.ACTION,
266
+ });
267
+
255
268
  if (multiSelectOptions.nextStep.code == '__BACK__') {
256
269
  emit('go-back');
257
270
  } else {
@@ -263,6 +276,12 @@ export default defineComponent({
263
276
  };
264
277
 
265
278
  const skipQuestion = (button: UploadDocumentMultiSelectAction) => {
279
+ sendAnalyticEvent(EventName.CLICK, {
280
+ button_name: button.label || '',
281
+ button_location: '',
282
+ button_type: ButtonType.ACTION,
283
+ });
284
+
266
285
  emit(props.completedEventName, {
267
286
  answers: selectedDocuments.value.length ? selectedDocuments.value : null,
268
287
  nextStep: button.nextStep,
@@ -31,7 +31,8 @@ export const summary = {
31
31
  {
32
32
  componentId: 'FURNISHING',
33
33
  title: 'Pompe à chaleur installée (hors aides)',
34
- details: 'Travaux réalisés par nos artisans partenaires Leroy Merlin',
34
+ details:
35
+ '\u003cp style="margin:0;"\u003eVous n\\’êtes pas éligibles aux aides\u003c/p\u003e\u003ca style="color:#000;" href="https://leroymerlin.fr/magazine/conseils-pratiques/les-aides-financieres-pour-renovation-energetique.html" target="_blank"\u003eMieux comprendre les aides\u003c/a\u003e',
35
36
  cost: {
36
37
  min: 13000,
37
38
  max: 20000,
@@ -0,0 +1,39 @@
1
+ import { useStore } from 'vuex';
2
+
3
+ const store = useStore();
4
+
5
+ export enum EventName {
6
+ CLICK = 'button.click',
7
+ FIELD = 'step.field',
8
+ }
9
+
10
+ export enum ButtonType {
11
+ ACTION = 'action',
12
+ }
13
+
14
+ interface EventData {
15
+ button_name: string;
16
+ button_location: string;
17
+ button_type: ButtonType;
18
+ }
19
+
20
+ interface EventField {
21
+ field_name: string;
22
+ field_value: any;
23
+ funnel_name: string;
24
+ }
25
+
26
+ /**
27
+ * Send analytics emit event
28
+ * @param event_name
29
+ * @param event_data
30
+ */
31
+ export const sendAnalyticEvent = (event_name: EventName, event_data: EventData | EventField) => {
32
+ store.dispatch('sendEventToBus', {
33
+ code: 'EMIT-ANALYTIC-EVENT',
34
+ payload: {
35
+ event_name,
36
+ event_data,
37
+ },
38
+ });
39
+ };
@@ -2,6 +2,7 @@ export interface PayloadAction {
2
2
  type: string;
3
3
  code: string;
4
4
  component?: string;
5
+ label?: string;
5
6
  payload?: {
6
7
  link: string;
7
8
  };
@@ -305,6 +305,12 @@ export default defineComponent({
305
305
  props.payload.viewModel.defaultValue?.zipcode?.path,
306
306
  ) || null;
307
307
 
308
+ const city =
309
+ getAnswerValue(
310
+ props.payload.viewModel.defaultValue?.city?.answerCode,
311
+ props.payload.viewModel.defaultValue?.city?.path,
312
+ ) || null;
313
+
308
314
  const convertToTypeOf = (typedVar: string, input: any): string | number | null => {
309
315
  if (!input) {
310
316
  return null;
@@ -338,7 +344,7 @@ export default defineComponent({
338
344
  address: '',
339
345
  additionalAddress: '',
340
346
  zipcode: zipcode,
341
- city: '',
347
+ city: city,
342
348
  email: '',
343
349
  phone: '',
344
350
  optin: false,
@@ -434,7 +440,9 @@ export default defineComponent({
434
440
  // MODAL
435
441
  let showModal = ref(false);
436
442
 
437
- store.dispatch('trezor/loadPartners');
443
+ store.dispatch('trezor/loadPartners', {
444
+ typeLead: props.payload.viewModel.typeLead,
445
+ });
438
446
 
439
447
  const partners = computed(() => store.getters['trezor/getPartners']);
440
448
 
@@ -7,6 +7,10 @@
7
7
  "zipcode": {
8
8
  "answerCode": "LMFR_PREVIOUS_QUESTION",
9
9
  "path": "value"
10
+ },
11
+ "city": {
12
+ "answerCode": "LMFR_PREVIOUS_QUESTION",
13
+ "path": "value"
10
14
  }
11
15
  },
12
16
  "metadata": [
@@ -26,8 +26,8 @@ export const sendTrezorForm = async (typeLead: string, payload: object) => {
26
26
  return response;
27
27
  };
28
28
 
29
- export const getPartners = async () => {
30
- const response = await clientApi.get(`leads/partners`).catch(function (error) {
29
+ export const getPartners = async (typeLeadSlug: string) => {
30
+ const response = await clientApi.get(`leads/partners?typeLeadSlug=` + typeLeadSlug).catch(function (error) {
31
31
  throw error;
32
32
  });
33
33
 
@@ -60,9 +60,9 @@ export default {
60
60
  }
61
61
  }
62
62
  },
63
- loadPartners: async ({ commit }: TrezorContext) => {
63
+ loadPartners: async ({ commit, state }: TrezorContext, { typeLead }: { typeLead: string }) => {
64
64
  try {
65
- const result = await getPartners();
65
+ const result = await getPartners(typeLead);
66
66
  commit('setPartners', result);
67
67
  } catch (error) {}
68
68
  },
@@ -143,6 +143,7 @@ export interface ScenarioStepPayload {
143
143
  action: string;
144
144
  };
145
145
  redirectLink?: any;
146
+ analytics: any;
146
147
  }
147
148
 
148
149
  export interface ScenarioStepViewModel {