project-booster-vue 9.6.0 → 9.8.1
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 +1 -1
- package/src/components/appointment/PbAppointmentForm.stories.mdx +94 -0
- package/src/components/appointment/PbAppointmentForm.vue +57 -0
- package/src/components/appointment/PbAppointmentStartSection.vue +52 -1
- package/src/components/appointment/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-components-appointment-qualification-pb-appointment-form-/360/237/246/240-101-sandbox-1-snap.png +0 -0
- package/src/components/pedagogy/PbPedagogy.stories.mdx +2 -2
- package/src/components/pedagogy/PbPedagogy.vue +41 -9
- package/src/components/pedagogy/default-payload.json +6 -1
- package/src/components/projects/project-hub/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-components-projects-pb-project-hub-/360/237/246/240-features-appointment-showcase-with-store-appointment-1-snap.png +0 -0
- package/src/components/projects/project-hub/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-components-projects-pb-project-hub-/360/237/246/240-features-appointment-showcase-with-visio-appointment-1-snap.png +0 -0
- package/src/components/question/PbQuestion.vue +2 -2
- package/src/components/question/list-select/PbListSelect.vue +1 -1
- package/src/components/scenario/{PbScenario-Features-Test.stories.mdx → PbScenario-Features-Appointment.stories.mdx} +59 -3
- package/src/components/scenario/PbScenario.vue +2 -0
- package/src/components/scenario/scenarii/appointment-qualification-kitchen.json +242 -69
- package/src/services/api/appointmentQualificationsApi.ts +35 -1
- package/src/services/api/mocks/inhabitantsMock.ts +1 -0
- package/src/stores/modules/appointmentQualificationStore.ts +58 -0
- package/src/components/pedagogy/PbPedagogyStore.ts +0 -17
package/package.json
CHANGED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Story, Meta, ArgsTable, Canvas } from '@storybook/addon-docs';
|
|
2
|
+
import { nestedAppDecorator } from '../../../.storybook/nested-app-decorator';
|
|
3
|
+
import PbAppointmentForm from './PbAppointmentForm';
|
|
4
|
+
import appointmentQualificationStore from '../../stores/modules/appointmentQualificationStore';
|
|
5
|
+
import inhabitantsStore from '../../stores/modules/inhabitantsStore';
|
|
6
|
+
import { rest } from 'msw';
|
|
7
|
+
import { useStore } from 'vuex';
|
|
8
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
9
|
+
import { getInhabitantByIdResolver } from '../../services/api/mocks/inhabitantsMock';
|
|
10
|
+
import { declarationsWithAppointmentResolver } from '../../services/api/mocks/appointmentQualificationMock';
|
|
11
|
+
import SCENARIO from '../scenario/scenarii/appointment-qualification-kitchen.json';
|
|
12
|
+
|
|
13
|
+
<Meta
|
|
14
|
+
title="Project Booster/Components/Appointment qualification/ PbAppointmentForm 🦠"
|
|
15
|
+
component={PbAppointmentForm}
|
|
16
|
+
argTypes={{}}
|
|
17
|
+
parameters={{
|
|
18
|
+
layout: 'fullscreen',
|
|
19
|
+
}}
|
|
20
|
+
decorators={[
|
|
21
|
+
nestedAppDecorator(
|
|
22
|
+
{
|
|
23
|
+
modules: {
|
|
24
|
+
appointmentQualification: appointmentQualificationStore,
|
|
25
|
+
inhabitants: inhabitantsStore,
|
|
26
|
+
},
|
|
27
|
+
mutations: {
|
|
28
|
+
eventBusSendEvent(state, { code, payload }) {
|
|
29
|
+
console.log('event bus data : ', code, payload);
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
actions: {
|
|
33
|
+
sendEventToBus({ commit }, action) {
|
|
34
|
+
commit('eventBusSendEvent', action);
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
[],
|
|
39
|
+
),
|
|
40
|
+
]}
|
|
41
|
+
/>
|
|
42
|
+
|
|
43
|
+
# 🦠 `PbAppointmentForm` - Component
|
|
44
|
+
|
|
45
|
+
The `PbAppointmentForm` component that include in a iframe the clicRDV form.
|
|
46
|
+
|
|
47
|
+
export const TemplateSandbox = (args, { argTypes }) => ({
|
|
48
|
+
props: Object.keys(argTypes),
|
|
49
|
+
components: { PbAppointmentForm },
|
|
50
|
+
setup() {
|
|
51
|
+
const store = useStore();
|
|
52
|
+
store.dispatch('appointmentQualification/initSessions', {
|
|
53
|
+
formId: 'appointment-qualification-kitchen',
|
|
54
|
+
correlationId: uuidv4(),
|
|
55
|
+
businessUnit: '001',
|
|
56
|
+
source: 'APPOINTMENT_QUALIFICATION',
|
|
57
|
+
sourceDetail: 'KITCHEN',
|
|
58
|
+
calendarId: '375615',
|
|
59
|
+
storeId: '006',
|
|
60
|
+
appointmentQualificationFormStructure: SCENARIO,
|
|
61
|
+
});
|
|
62
|
+
store.commit('appointmentQualification/setCurrentAppointmentQualification', {
|
|
63
|
+
inhabitantProjectId: uuidv4(),
|
|
64
|
+
appointmentQualificationId: uuidv4(),
|
|
65
|
+
});
|
|
66
|
+
store.commit('inhabitants/setCurrentInhabitant', {
|
|
67
|
+
firstName: 'Jean',
|
|
68
|
+
lastName: 'Dupont',
|
|
69
|
+
email: 'jean.dupont@yopmail.com',
|
|
70
|
+
});
|
|
71
|
+
store.commit('appointmentQualification/setClicRDVBaseUrl', 'https://sandbox-user.clicrdv.com');
|
|
72
|
+
return { args };
|
|
73
|
+
},
|
|
74
|
+
template: `<pb-appointment-form />
|
|
75
|
+
/>`,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
<Canvas>
|
|
79
|
+
<Story
|
|
80
|
+
inline={false}
|
|
81
|
+
height="862px"
|
|
82
|
+
name="101 Sandbox"
|
|
83
|
+
parameters={{
|
|
84
|
+
msw: [
|
|
85
|
+
rest.get('/api/inhabitant-api/users/:buId/:inhabitantId', getInhabitantByIdResolver),
|
|
86
|
+
rest.post('/api/declarations-without-appointment', declarationsWithAppointmentResolver),
|
|
87
|
+
],
|
|
88
|
+
}}
|
|
89
|
+
>
|
|
90
|
+
{TemplateSandbox.bind({})}
|
|
91
|
+
</Story>
|
|
92
|
+
</Canvas>
|
|
93
|
+
|
|
94
|
+
<ArgsTable story="101 Sandbox" />
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<m-flex class="pb-appointment-form__container">
|
|
3
|
+
<iframe v-if="appointmentFormUrl" :src="appointmentFormUrl" style="border: 0; min-height: 110rem; width: 100%">
|
|
4
|
+
<p>
|
|
5
|
+
Your browser doesn't support iframes. To book an appointment, please follow this link :
|
|
6
|
+
<a :href="appointmentFormUrl">{{ appointmentFormUrl }}</a>
|
|
7
|
+
</p>
|
|
8
|
+
</iframe>
|
|
9
|
+
</m-flex>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script lang="ts">
|
|
13
|
+
import { computed, defineComponent } from 'vue';
|
|
14
|
+
import { useStore } from 'vuex';
|
|
15
|
+
import MFlex from '../mozaic/flex/MFlex.vue';
|
|
16
|
+
|
|
17
|
+
export default defineComponent({
|
|
18
|
+
name: 'PbAppointmentForm',
|
|
19
|
+
components: { MFlex },
|
|
20
|
+
|
|
21
|
+
setup() {
|
|
22
|
+
const store = useStore();
|
|
23
|
+
|
|
24
|
+
const appointmentFormUrl = computed(() => {
|
|
25
|
+
const sessions = store.getters['appointmentQualification/getSessions'];
|
|
26
|
+
const currentAppointmentQualification =
|
|
27
|
+
store.getters['appointmentQualification/getCurrentAppointmentQualification'];
|
|
28
|
+
const currentUser = store.getters['inhabitants/getCurrentInhabitant'];
|
|
29
|
+
const baseUrl = store.getters['appointmentQualification/getClicRDVBaseUrl'];
|
|
30
|
+
|
|
31
|
+
let url = `${baseUrl}{/leroy-merlin-${sessions.storeId}`;
|
|
32
|
+
url += `?calendar_id=${sessions.calendarId}`;
|
|
33
|
+
url += `&vevent[str5]=${currentAppointmentQualification.inhabitantProjectId}`;
|
|
34
|
+
url += `&fiche[email]=${currentUser.email}`;
|
|
35
|
+
url += `&fiche[lastname]=${currentUser.lastName}`;
|
|
36
|
+
url += `&fiche[firstname]=${currentUser.firstName}`;
|
|
37
|
+
|
|
38
|
+
return url;
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
appointmentFormUrl,
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<style lang="scss" scoped>
|
|
49
|
+
@import 'pb-variables';
|
|
50
|
+
|
|
51
|
+
.pb-appointment-form {
|
|
52
|
+
&__container {
|
|
53
|
+
margin: 0 auto;
|
|
54
|
+
width: 100%;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
</style>
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<m-flex full-width class="pb-appointment-section">
|
|
3
3
|
<m-flex align-items="center" full-width class="pb-appointment-section__content" direction="column">
|
|
4
|
-
<div class="pb-appointment-section__content-title">
|
|
4
|
+
<div class="pb-appointment-section__content-title">
|
|
5
|
+
{{ decorate(payload.viewModel.title, payload.defaultDecoratorValue) }}
|
|
6
|
+
</div>
|
|
5
7
|
<m-flex
|
|
6
8
|
justify-content="center"
|
|
7
9
|
align-items="center"
|
|
@@ -50,6 +52,7 @@ import MFlex from '../mozaic/flex/MFlex.vue';
|
|
|
50
52
|
import PbItemsList from '../items/PbItemsList.vue';
|
|
51
53
|
import MButton from '../mozaic/buttons/MButton.vue';
|
|
52
54
|
import { ScenarioStepAnswer, ScenarioStepPayload } from '@/types/pb/Scenario';
|
|
55
|
+
import objectPath from 'object-path';
|
|
53
56
|
|
|
54
57
|
export default defineComponent({
|
|
55
58
|
name: 'PbAppointmentStartSection',
|
|
@@ -62,6 +65,20 @@ export default defineComponent({
|
|
|
62
65
|
type: Object as PropType<ScenarioStepPayload>,
|
|
63
66
|
default: () => null,
|
|
64
67
|
},
|
|
68
|
+
/**
|
|
69
|
+
* The options provided at runtime to customize component behaviour
|
|
70
|
+
*/
|
|
71
|
+
runtimeOptions: {
|
|
72
|
+
type: Object,
|
|
73
|
+
default: () => ({}),
|
|
74
|
+
},
|
|
75
|
+
/**
|
|
76
|
+
* The previous answers to inject
|
|
77
|
+
*/
|
|
78
|
+
answers: {
|
|
79
|
+
type: Object as PropType<Map<string, ScenarioStepAnswer[]>>,
|
|
80
|
+
default: () => new Map<string, ScenarioStepAnswer[]>(),
|
|
81
|
+
},
|
|
65
82
|
},
|
|
66
83
|
methods: {
|
|
67
84
|
selectAnswer(answer: ScenarioStepAnswer) {
|
|
@@ -70,6 +87,40 @@ export default defineComponent({
|
|
|
70
87
|
nextStep: undefined,
|
|
71
88
|
});
|
|
72
89
|
},
|
|
90
|
+
decorate(valueToDecorate: string, defaultValue = '') {
|
|
91
|
+
if (valueToDecorate) {
|
|
92
|
+
valueToDecorate = `\`${valueToDecorate}\``;
|
|
93
|
+
try {
|
|
94
|
+
return this.doEval(valueToDecorate, defaultValue);
|
|
95
|
+
} catch (e) {
|
|
96
|
+
console.error(e);
|
|
97
|
+
return valueToDecorate;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return valueToDecorate;
|
|
101
|
+
},
|
|
102
|
+
decorateBoolean(valueToDecorate: string, defaultValue = false) {
|
|
103
|
+
if (valueToDecorate) {
|
|
104
|
+
return this.doEval(valueToDecorate, defaultValue);
|
|
105
|
+
}
|
|
106
|
+
return valueToDecorate;
|
|
107
|
+
},
|
|
108
|
+
doEval(valueToEval: string, defaultValue: string | boolean) {
|
|
109
|
+
return new Function('getAnswerValue', 'answers', 'defaultValue', 'runtimeOptions', `return ${valueToEval}`).call(
|
|
110
|
+
this,
|
|
111
|
+
this.getAnswerValue,
|
|
112
|
+
Object.fromEntries(this.answers),
|
|
113
|
+
defaultValue,
|
|
114
|
+
this.runtimeOptions,
|
|
115
|
+
);
|
|
116
|
+
},
|
|
117
|
+
getAnswerValue(answerCode: string, path: string) {
|
|
118
|
+
if (!this.answers.get(answerCode) || this.answers.get(answerCode)?.length === 0) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return objectPath.get(this.answers.get(answerCode)?.at(0) as any, path);
|
|
123
|
+
},
|
|
73
124
|
},
|
|
74
125
|
});
|
|
75
126
|
</script>
|
|
@@ -2,7 +2,7 @@ import { Anchor, Story, Preview, Meta, Props, ArgsTable, Source, Canvas } from '
|
|
|
2
2
|
import DEFAULT_PAYLOAD from './default-payload';
|
|
3
3
|
import { nestedAppDecorator } from '../../../.storybook/nested-app-decorator';
|
|
4
4
|
import PbPedagogy from './PbPedagogy';
|
|
5
|
-
import
|
|
5
|
+
import store from '../../stores/store';
|
|
6
6
|
|
|
7
7
|
<Meta
|
|
8
8
|
title="Project Booster/Components/Pedagogy/ PbPedagogy 🦠"
|
|
@@ -23,7 +23,7 @@ import { pbPedagogyStore } from './PbPedagogyStore';
|
|
|
23
23
|
parameters={{
|
|
24
24
|
layout: 'fullscreen',
|
|
25
25
|
}}
|
|
26
|
-
decorators={[nestedAppDecorator(
|
|
26
|
+
decorators={[nestedAppDecorator(store, [])]}
|
|
27
27
|
/>
|
|
28
28
|
|
|
29
29
|
# 🦠 `PbPedagogy` - Component
|
|
@@ -4,10 +4,16 @@
|
|
|
4
4
|
<m-icon class="pb-pedagogy__content-icon" :icon="payload.viewModel.icon" color="primary-01-500" size="xl" />
|
|
5
5
|
<div class="pb-pedagogy__content-title">{{ payload.viewModel.title }}</div>
|
|
6
6
|
|
|
7
|
-
<
|
|
8
|
-
<
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
<m-flex class="pb-pedagogy__content-description" v-if="payload.viewModel.description" direction="column">
|
|
8
|
+
<div
|
|
9
|
+
class="pb-pedagogy__content-description-line"
|
|
10
|
+
v-for="(line, index) in payload.viewModel.description"
|
|
11
|
+
:key="index"
|
|
12
|
+
>
|
|
13
|
+
<m-icon :icon="line.icon" v-if="line.icon" />
|
|
14
|
+
<div class="pb-pedagogy__content-description-line-text" v-html="line.label" />
|
|
15
|
+
</div>
|
|
16
|
+
</m-flex>
|
|
11
17
|
<m-button
|
|
12
18
|
v-if="payload.viewModel.downloadButton"
|
|
13
19
|
:theme="payload.viewModel.downloadButton.theme"
|
|
@@ -15,12 +21,20 @@
|
|
|
15
21
|
class="pb-pedagogy__content-upload-button"
|
|
16
22
|
@click="handleButtonLinkClicked"
|
|
17
23
|
/>
|
|
24
|
+
<m-button
|
|
25
|
+
v-if="payload.multiSelect"
|
|
26
|
+
theme="primary"
|
|
27
|
+
:label="payload.multiSelect.actions.VALIDATE.label"
|
|
28
|
+
class="pb-pedagogy__content-action-button"
|
|
29
|
+
@click="handleValidateClicked"
|
|
30
|
+
/>
|
|
18
31
|
<m-flex
|
|
19
32
|
justify-content="center"
|
|
20
33
|
align-items="center"
|
|
21
34
|
full-width
|
|
22
35
|
class="pb-pedagogy__content-cards"
|
|
23
36
|
direction="column"
|
|
37
|
+
v-if="payload.cards"
|
|
24
38
|
>
|
|
25
39
|
<div class="pb-pedagogy__content-cards-title">Pour aller plus loin</div>
|
|
26
40
|
<pb-cards-list :cards="payload.cards" @card-click="handleCardClick" />
|
|
@@ -35,6 +49,7 @@ import MButton from '../mozaic/buttons/MButton.vue';
|
|
|
35
49
|
import MFlex from '../mozaic/flex/MFlex.vue';
|
|
36
50
|
import MIcon from '../mozaic/icon/MIcon.vue';
|
|
37
51
|
import PbCardsList from '../cards/PbCardsList.vue';
|
|
52
|
+
import { mapGetters } from 'vuex';
|
|
38
53
|
|
|
39
54
|
interface PedagogyCardViewmodel {
|
|
40
55
|
url: string;
|
|
@@ -51,8 +66,6 @@ interface PedagogyCard {
|
|
|
51
66
|
viewModel: PedagogyCardViewmodel;
|
|
52
67
|
}
|
|
53
68
|
|
|
54
|
-
const IMAGE_SRC = 'https://storage.googleapis.com/project-booster-media/vad/lm-advisor.png';
|
|
55
|
-
|
|
56
69
|
export default defineComponent({
|
|
57
70
|
name: 'PbPedagogy',
|
|
58
71
|
components: { PbCardsList, MButton, MIcon, MFlex },
|
|
@@ -66,9 +79,13 @@ export default defineComponent({
|
|
|
66
79
|
},
|
|
67
80
|
},
|
|
68
81
|
data: () => ({
|
|
69
|
-
IMAGE_SRC,
|
|
70
82
|
value: [],
|
|
71
83
|
}),
|
|
84
|
+
computed: {
|
|
85
|
+
...mapGetters('appointmentQualification', {
|
|
86
|
+
currentAppointmentQualification: 'getCurrentAppointmentQualification',
|
|
87
|
+
}),
|
|
88
|
+
},
|
|
72
89
|
watch: {
|
|
73
90
|
value(newValue) {
|
|
74
91
|
const selectedCard = this.payload.cards.find((card: PedagogyCard) => card.value === newValue);
|
|
@@ -107,7 +124,18 @@ export default defineComponent({
|
|
|
107
124
|
},
|
|
108
125
|
},
|
|
109
126
|
});
|
|
110
|
-
|
|
127
|
+
const targetUrl = card.viewModel.url.replace(
|
|
128
|
+
'@@PB_PROJECT_ID_FILLER@@',
|
|
129
|
+
this.currentAppointmentQualification.inhabitantProjectId,
|
|
130
|
+
);
|
|
131
|
+
window.open(targetUrl, '_blank');
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
async handleValidateClicked() {
|
|
135
|
+
this.$emit('step-completed', {
|
|
136
|
+
answers: [],
|
|
137
|
+
nextStep: this.payload.multiSelect.actions.VALIDATE.nextStep,
|
|
138
|
+
});
|
|
111
139
|
},
|
|
112
140
|
},
|
|
113
141
|
});
|
|
@@ -154,7 +182,7 @@ $responsive-breakpoint: 'm';
|
|
|
154
182
|
min-height: $mu400;
|
|
155
183
|
}
|
|
156
184
|
|
|
157
|
-
&-description {
|
|
185
|
+
&-description-line {
|
|
158
186
|
align-items: center;
|
|
159
187
|
display: flex;
|
|
160
188
|
flex-direction: column;
|
|
@@ -185,6 +213,10 @@ $responsive-breakpoint: 'm';
|
|
|
185
213
|
margin-top: $mu200;
|
|
186
214
|
}
|
|
187
215
|
|
|
216
|
+
&-action-button {
|
|
217
|
+
margin-top: $mu200;
|
|
218
|
+
}
|
|
219
|
+
|
|
188
220
|
&-cards {
|
|
189
221
|
margin-top: $mu200;
|
|
190
222
|
|
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
"viewModel": {
|
|
3
3
|
"title": "Un email de rappel pour préparer votre RDV vous sera envoyé",
|
|
4
4
|
"icon": "https://storage.googleapis.com/project-booster-media/vad/fin-de-parcours/mail_80.svg",
|
|
5
|
-
"description":
|
|
5
|
+
"description": [
|
|
6
|
+
{
|
|
7
|
+
"label": "Les mesures et <span class='pb-pedagogy__content-description-bold'> plans de votre pièce </span> sont importants pour le rendez-vous. Ils\n permettront à votre conseiller de créer un <span class='pb-pedagogy__content-description-bold'> plan 3D adapté </span> à votre cuisine.\n <span class='pb-pedagogy__content-description-bold'> Vous pouvez les ajouter à partir à partir du mail que vous avez reçu. </span>",
|
|
8
|
+
"icon": "https://storage.googleapis.com/project-booster-media/vad/lm-advisor.png"
|
|
9
|
+
}
|
|
10
|
+
],
|
|
6
11
|
"downloadButton": {
|
|
7
12
|
"label": "Comment faire son plan ? (PDF)",
|
|
8
13
|
"theme": "bordered",
|
|
@@ -297,7 +297,7 @@ export default defineComponent({
|
|
|
297
297
|
props: {
|
|
298
298
|
/**
|
|
299
299
|
* The component view model and business data as an object. The provided prop
|
|
300
|
-
* is merged with the default payload value so only
|
|
300
|
+
* is merged with the default payload value so only overridden values will change
|
|
301
301
|
* from the default ones.
|
|
302
302
|
*/
|
|
303
303
|
payload: {
|
|
@@ -320,7 +320,7 @@ export default defineComponent({
|
|
|
320
320
|
default: true,
|
|
321
321
|
},
|
|
322
322
|
/**
|
|
323
|
-
* Name for the event to send when the step is
|
|
323
|
+
* Name for the event to send when the step is question is answered
|
|
324
324
|
*/
|
|
325
325
|
completedEventName: {
|
|
326
326
|
type: String,
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
justify-content="center"
|
|
45
45
|
>
|
|
46
46
|
<m-button
|
|
47
|
-
v-if="payload.skippable && !hasSelectedAnswers"
|
|
47
|
+
v-if="payload.skippable && (!hasSelectedAnswers || payload.viewModel.alwaysDisplaySkippable)"
|
|
48
48
|
class="pb-list-select__next-button"
|
|
49
49
|
:label="payload.skippable.label"
|
|
50
50
|
:left-icon="payload.skippable.leftIcon"
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { nestedAppDecorator } from '../../../.storybook/nested-app-decorator';
|
|
2
|
-
import { Story,
|
|
2
|
+
import { Story, Meta, ArgsTable, Source, Canvas } from '@storybook/addon-docs';
|
|
3
3
|
import PbScenario from './PbScenario';
|
|
4
4
|
import DEFAULT_PAYLOAD from './scenarii/appointment-qualification-kitchen.json';
|
|
5
5
|
import store from '../../stores/store';
|
|
6
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
6
7
|
import { useStore } from 'vuex';
|
|
7
8
|
import { rest } from 'msw';
|
|
8
9
|
import {
|
|
@@ -17,6 +18,7 @@ import {
|
|
|
17
18
|
getDocumentsImageFileResolver,
|
|
18
19
|
uploadDocumentResolver,
|
|
19
20
|
} from '../../services/api/mocks/documentsMock';
|
|
21
|
+
import { getInhabitantByIdResolver } from '../../services/api/mocks/inhabitantsMock.ts';
|
|
20
22
|
|
|
21
23
|
<Meta
|
|
22
24
|
title="Project Booster/Scenario/PbScenario 🦠/ VAD"
|
|
@@ -60,10 +62,24 @@ export const TemplateSandbox = (args, { argTypes }) => {
|
|
|
60
62
|
components: { PbScenario },
|
|
61
63
|
setup() {
|
|
62
64
|
const store = useStore();
|
|
65
|
+
store.dispatch('documentsPlans/updateContext', { type: 'DOCUMENT', subType: 'PLAN' });
|
|
66
|
+
store.dispatch('documentsPictures/updateContext', { type: 'DOCUMENT', subType: 'PHOTO' });
|
|
63
67
|
store.dispatch('projects/loadProject', '001');
|
|
64
68
|
store.dispatch('configurations/loadConfigurations', '001');
|
|
65
69
|
store.dispatch('configurations/defineConfiguratorTypes', [DEFAULT_PAYLOAD.__START__.meta.configuratorType]);
|
|
66
70
|
store.dispatch('configurations/searchConfigurations', '001');
|
|
71
|
+
store.dispatch('inhabitants/loadInhabitant', '123456');
|
|
72
|
+
store.dispatch('appointmentQualification/loadClicRDVBaseUrl');
|
|
73
|
+
store.dispatch('appointmentQualification/initSessions', {
|
|
74
|
+
formId: 'appointment-qualification-kitchen',
|
|
75
|
+
correlationId: uuidv4(),
|
|
76
|
+
businessUnit: '001',
|
|
77
|
+
source: 'APPOINTMENT_QUALIFICATION',
|
|
78
|
+
sourceDetail: 'KITCHEN',
|
|
79
|
+
calendarId: '375615',
|
|
80
|
+
storeId: '006',
|
|
81
|
+
appointmentQualificationFormStructure: DEFAULT_PAYLOAD,
|
|
82
|
+
});
|
|
67
83
|
return { args };
|
|
68
84
|
},
|
|
69
85
|
template: `<div style="height: 64px; width: 100%; background-color: lightblue">HEADER</div>
|
|
@@ -83,7 +99,10 @@ export const TemplateSandbox = (args, { argTypes }) => {
|
|
|
83
99
|
name="101 Sandbox"
|
|
84
100
|
inline={false}
|
|
85
101
|
height="758px"
|
|
86
|
-
args={{
|
|
102
|
+
args={{
|
|
103
|
+
scenarios: DEFAULT_PAYLOAD,
|
|
104
|
+
runtimeOptions: { hasConfigurations: true, postQualificationAppointment: true },
|
|
105
|
+
}}
|
|
87
106
|
parameters={{
|
|
88
107
|
storyshots: { disable: true },
|
|
89
108
|
msw: [
|
|
@@ -118,7 +137,7 @@ export const TemplateSandbox = (args, { argTypes }) => {
|
|
|
118
137
|
name="Without simulations"
|
|
119
138
|
inline={false}
|
|
120
139
|
height="758px"
|
|
121
|
-
args={{ scenarios: DEFAULT_PAYLOAD }}
|
|
140
|
+
args={{ scenarios: DEFAULT_PAYLOAD, runtimeOptions: { postQualificationAppointment: true } }}
|
|
122
141
|
parameters={{
|
|
123
142
|
storyshots: { disable: true },
|
|
124
143
|
msw: [
|
|
@@ -140,6 +159,43 @@ Simple scenario used in this demo:
|
|
|
140
159
|
|
|
141
160
|
<Source language="json" code={JSON.stringify(DEFAULT_PAYLOAD, null, ' ')} />
|
|
142
161
|
|
|
162
|
+
# qualification before appointment
|
|
163
|
+
|
|
164
|
+
<Canvas>
|
|
165
|
+
<Story
|
|
166
|
+
name="Qualification before appointment"
|
|
167
|
+
inline={false}
|
|
168
|
+
height="758px"
|
|
169
|
+
args={{
|
|
170
|
+
scenarios: DEFAULT_PAYLOAD,
|
|
171
|
+
runtimeOptions: { hasConfigurations: true, postQualificationAppointment: false },
|
|
172
|
+
}}
|
|
173
|
+
parameters={{
|
|
174
|
+
storyshots: { disable: true },
|
|
175
|
+
msw: [
|
|
176
|
+
rest.get('/api/inhabitant-projects/:inhabitantProjectId', getProjectByIdResolver),
|
|
177
|
+
rest.get('/api/inhabitant-api/users/:buId/:inhabitantId', getInhabitantByIdResolver),
|
|
178
|
+
rest.get('/api/simulations', getConfigurationsByProjectIdResolver),
|
|
179
|
+
rest.get(
|
|
180
|
+
'/api/inhabitant-projects/:inhabitantProjectId/simulations',
|
|
181
|
+
getEmptyConfigurationsByProjectIdResolver,
|
|
182
|
+
),
|
|
183
|
+
rest.post('/api/inhabitant-projects/:inhabitantProjectId/simulations/:simulationId', notContentResolver),
|
|
184
|
+
rest.post('/api/events/documents', acceptedResolver),
|
|
185
|
+
rest.get('/api/inhabitant-projects/:projectId/documents/', getDocumentsByInhabitantProjectIdResolver),
|
|
186
|
+
rest.get(
|
|
187
|
+
'/api/inhabitant-projects/:projectId/documents/:documentId/thumbnail',
|
|
188
|
+
getDocumentsImageThumbnailResolver,
|
|
189
|
+
),
|
|
190
|
+
rest.get('/api/inhabitant-projects/:projectId/documents/:documentId/file', getDocumentsImageFileResolver),
|
|
191
|
+
rest.post('/api/inhabitant-projects/:projectId/documents', uploadDocumentResolver),
|
|
192
|
+
],
|
|
193
|
+
}}
|
|
194
|
+
>
|
|
195
|
+
{TemplateSandbox.bind({})}
|
|
196
|
+
</Story>
|
|
197
|
+
</Canvas>
|
|
198
|
+
|
|
143
199
|
## Scenario-event payload
|
|
144
200
|
|
|
145
201
|
A event emitted has a `code`, `payload` and `context`. The `payload` depends on the `code`.
|
|
@@ -86,6 +86,7 @@ import { useRouter, useRoute } from 'vue-router';
|
|
|
86
86
|
import MFlex from '../mozaic/flex/MFlex.vue';
|
|
87
87
|
import PbAmountInput from '../question/amount-input/PbAmountInput.vue';
|
|
88
88
|
import PbAppointmentStartSection from '../appointment/PbAppointmentStartSection.vue';
|
|
89
|
+
import PbAppointmentForm from '../appointment/PbAppointmentForm.vue';
|
|
89
90
|
import PbDimensionsInput from '../question/dimensions-input/PbDimensionsInput.vue';
|
|
90
91
|
import PbListSelect from '../question/list-select/PbListSelect.vue';
|
|
91
92
|
import PbLoginRedirect from '../question/login-redirect/PbLoginRedirect.vue';
|
|
@@ -133,6 +134,7 @@ export default defineComponent({
|
|
|
133
134
|
PbSpaceInput,
|
|
134
135
|
PbUploadDocument,
|
|
135
136
|
PbConfigurationsImport,
|
|
137
|
+
PbAppointmentForm,
|
|
136
138
|
},
|
|
137
139
|
|
|
138
140
|
props: {
|
|
@@ -24,6 +24,9 @@
|
|
|
24
24
|
"type": "STEP",
|
|
25
25
|
"component": "PbAppointmentStartSection",
|
|
26
26
|
"payload": {
|
|
27
|
+
"viewModel": {
|
|
28
|
+
"title": "${runtimeOptions.postQualificationAppointment === false ? 'Gagnez du temps en préparant votre rendez-vous' : 'Préparez votre Rendez-vous.'}"
|
|
29
|
+
},
|
|
27
30
|
"answers": {
|
|
28
31
|
"CONTINUE": {
|
|
29
32
|
"code": "CONTINUE",
|
|
@@ -75,14 +78,116 @@
|
|
|
75
78
|
}
|
|
76
79
|
},
|
|
77
80
|
{
|
|
78
|
-
"conditions": [
|
|
81
|
+
"conditions": [
|
|
82
|
+
"isAnswerMatching('START_SCENARIO', 'LATER') && runtimeOptions.postQualificationAppointment === true"
|
|
83
|
+
],
|
|
79
84
|
"nextStep": {
|
|
80
85
|
"code": "START_LATER"
|
|
81
86
|
}
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"conditions": [
|
|
90
|
+
"isAnswerMatching('START_SCENARIO', 'LATER') && runtimeOptions.postQualificationAppointment === false"
|
|
91
|
+
],
|
|
92
|
+
"nextStep": {
|
|
93
|
+
"code": "LMFR_QUESTION_QUALIFICATION_EXIT"
|
|
94
|
+
}
|
|
82
95
|
}
|
|
83
96
|
]
|
|
84
97
|
}
|
|
85
98
|
},
|
|
99
|
+
"LMFR_QUESTION_QUALIFICATION_EXIT": {
|
|
100
|
+
"code": "LMFR_QUESTION_QUALIFICATION_EXIT",
|
|
101
|
+
"type": "STEP",
|
|
102
|
+
"component": "PbListSelect",
|
|
103
|
+
"payload": {
|
|
104
|
+
"viewModel": {
|
|
105
|
+
"label": "Pouvez-vous nous dire pourquoi vous souhaitez préparer votre RDV plus tard ?",
|
|
106
|
+
"backLabel": "Question précédente",
|
|
107
|
+
"separator": true,
|
|
108
|
+
"padding": true,
|
|
109
|
+
"actionLabel": "Continuer",
|
|
110
|
+
"sortBy": {
|
|
111
|
+
"type": ["numeric"],
|
|
112
|
+
"order": ["Asc"],
|
|
113
|
+
"path": ["meta.ranking"]
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
"answers": {
|
|
117
|
+
"NOT_UNDERSTOOD": {
|
|
118
|
+
"code": "NOT_UNDERSTOOD",
|
|
119
|
+
"viewModel": {
|
|
120
|
+
"title": "Je n’ai pas compris ce qu’on attend de moi"
|
|
121
|
+
},
|
|
122
|
+
"meta": {
|
|
123
|
+
"ranking": 1
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
"NO_PLAN": {
|
|
127
|
+
"code": "NO_PLAN",
|
|
128
|
+
"viewModel": {
|
|
129
|
+
"title": "Je n'ai pas de plan"
|
|
130
|
+
},
|
|
131
|
+
"meta": {
|
|
132
|
+
"ranking": 2
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
"PROJECT_UNDEFINED": {
|
|
136
|
+
"code": "PROJECT_UNDEFINED",
|
|
137
|
+
"viewModel": {
|
|
138
|
+
"title": "Mon projet n’est pas clair pour le moment"
|
|
139
|
+
},
|
|
140
|
+
"meta": {
|
|
141
|
+
"ranking": 3
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
"PROJECT_STORE": {
|
|
145
|
+
"code": "PROJECT_STORE",
|
|
146
|
+
"viewModel": {
|
|
147
|
+
"title": "Je préfère me déplacer directement en magasin"
|
|
148
|
+
},
|
|
149
|
+
"meta": {
|
|
150
|
+
"ranking": 4
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
"OTHER": {
|
|
154
|
+
"code": "OTHER",
|
|
155
|
+
"customizeValue": true,
|
|
156
|
+
"viewModel": {
|
|
157
|
+
"title": "Autre"
|
|
158
|
+
},
|
|
159
|
+
"meta": {
|
|
160
|
+
"ranking": 5
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
"nextStep": {
|
|
166
|
+
"code": "LMFR_QUESTION_QUALIFICATION_EXIT_CONFIRMATION"
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
"LMFR_QUESTION_QUALIFICATION_EXIT_CONFIRMATION": {
|
|
170
|
+
"code": "LMFR_QUESTION_QUALIFICATION_EXIT_CONFIRMATION",
|
|
171
|
+
"type": "STEP",
|
|
172
|
+
"component": "PbPedagogy",
|
|
173
|
+
"payload": {
|
|
174
|
+
"code": "LMFR_QUESTION_QUALIFICATION_EXIT_CONFIRMATION",
|
|
175
|
+
"viewModel": {
|
|
176
|
+
"title": "Merci pour votre réponse",
|
|
177
|
+
"icon": "https://storage.googleapis.com/project-booster-media/vad/fin-de-parcours/check_80.svg"
|
|
178
|
+
},
|
|
179
|
+
"multiSelect": {
|
|
180
|
+
"actions": {
|
|
181
|
+
"VALIDATE": {
|
|
182
|
+
"label": "Continuer et prendre RDV",
|
|
183
|
+
"nextStep": {
|
|
184
|
+
"code": "APPOINTMENT_FORM"
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
},
|
|
86
191
|
"LMFR_QUESTION_SCENARIO": {
|
|
87
192
|
"code": "LMFR_QUESTION_SCENARIO",
|
|
88
193
|
"type": "SCENARIO",
|
|
@@ -441,7 +546,20 @@
|
|
|
441
546
|
"image": "https://storage.googleapis.com/project-booster-media/vad/plans/noplan-later.jpg"
|
|
442
547
|
},
|
|
443
548
|
"nextStep": {
|
|
444
|
-
"
|
|
549
|
+
"conditionals": [
|
|
550
|
+
{
|
|
551
|
+
"conditions": ["runtimeOptions.postQualificationAppointment === true"],
|
|
552
|
+
"nextStep": {
|
|
553
|
+
"code": "__END__"
|
|
554
|
+
}
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
"conditions": ["runtimeOptions.postQualificationAppointment === false"],
|
|
558
|
+
"nextStep": {
|
|
559
|
+
"code": "PROJECT_UPDATED"
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
]
|
|
445
563
|
}
|
|
446
564
|
}
|
|
447
565
|
}
|
|
@@ -466,7 +584,7 @@
|
|
|
466
584
|
"component": "PbQuestion",
|
|
467
585
|
"payload": {
|
|
468
586
|
"viewModel": {
|
|
469
|
-
"label": "${answers.LMFR_QUESTION_PLAN[0].code === 'HAVE_PLAN' ? 'Sur votre plan, vérifiez que vous avez les bonnes mesures :' : 'Réalisez rapidement un plan avec les mesures de votre pièce en 3 étapes'}",
|
|
587
|
+
"label": "${${answers.LMFR_QUESTION_PLAN[0].code === 'HAVE_PLAN' ? 'Sur votre plan, vérifiez que vous avez les bonnes mesures :' : 'Réalisez rapidement un plan avec les mesures de votre pièce en 3 étapes'}",
|
|
470
588
|
"subtitle": "${answers.LMFR_QUESTION_PLAN[0].code === 'HAVE_PLAN' ? 'Votre conseiller aura besoin de ces mesures pour créer votre plan de cuisine en 3D.' : 'Sur une feuille, dessinez la pièce et reportez les bonnes mesures, prenez une photo du plan et ajoutez la.'}",
|
|
471
589
|
"widthFromL": "1of3",
|
|
472
590
|
"forceOneCardPerLineOnMobile": true,
|
|
@@ -486,7 +604,20 @@
|
|
|
486
604
|
"width": "full",
|
|
487
605
|
"widthFromM": "fit",
|
|
488
606
|
"nextStep": {
|
|
489
|
-
"
|
|
607
|
+
"conditionals": [
|
|
608
|
+
{
|
|
609
|
+
"conditions": ["runtimeOptions.postQualificationAppointment === true"],
|
|
610
|
+
"nextStep": {
|
|
611
|
+
"code": "START_LATER"
|
|
612
|
+
}
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
"conditions": ["runtimeOptions.postQualificationAppointment === false"],
|
|
616
|
+
"nextStep": {
|
|
617
|
+
"code": "PROJECT_UPDATED"
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
]
|
|
490
621
|
}
|
|
491
622
|
},
|
|
492
623
|
{
|
|
@@ -602,7 +733,20 @@
|
|
|
602
733
|
"width": "full",
|
|
603
734
|
"widthFromM": "fit",
|
|
604
735
|
"nextStep": {
|
|
605
|
-
"
|
|
736
|
+
"conditionals": [
|
|
737
|
+
{
|
|
738
|
+
"conditions": ["runtimeOptions.postQualificationAppointment === true"],
|
|
739
|
+
"nextStep": {
|
|
740
|
+
"code": "START_LATER"
|
|
741
|
+
}
|
|
742
|
+
},
|
|
743
|
+
{
|
|
744
|
+
"conditions": ["runtimeOptions.postQualificationAppointment === false"],
|
|
745
|
+
"nextStep": {
|
|
746
|
+
"code": "PROJECT_UPDATED"
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
]
|
|
606
750
|
}
|
|
607
751
|
}
|
|
608
752
|
],
|
|
@@ -652,7 +796,20 @@
|
|
|
652
796
|
"width": "full",
|
|
653
797
|
"widthFromM": "fit",
|
|
654
798
|
"nextStep": {
|
|
655
|
-
"
|
|
799
|
+
"conditionals": [
|
|
800
|
+
{
|
|
801
|
+
"conditions": ["runtimeOptions.postQualificationAppointment === true"],
|
|
802
|
+
"nextStep": {
|
|
803
|
+
"code": "__END__"
|
|
804
|
+
}
|
|
805
|
+
},
|
|
806
|
+
{
|
|
807
|
+
"conditions": ["runtimeOptions.postQualificationAppointment === false"],
|
|
808
|
+
"nextStep": {
|
|
809
|
+
"code": "PROJECT_UPDATED"
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
]
|
|
656
813
|
}
|
|
657
814
|
},
|
|
658
815
|
{
|
|
@@ -739,7 +896,20 @@
|
|
|
739
896
|
"width": "full",
|
|
740
897
|
"widthFromM": "fit",
|
|
741
898
|
"nextStep": {
|
|
742
|
-
"
|
|
899
|
+
"conditionals": [
|
|
900
|
+
{
|
|
901
|
+
"conditions": ["runtimeOptions.postQualificationAppointment === true"],
|
|
902
|
+
"nextStep": {
|
|
903
|
+
"code": "__END__"
|
|
904
|
+
}
|
|
905
|
+
},
|
|
906
|
+
{
|
|
907
|
+
"conditions": ["runtimeOptions.postQualificationAppointment === false"],
|
|
908
|
+
"nextStep": {
|
|
909
|
+
"code": "PROJECT_UPDATED"
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
]
|
|
743
913
|
}
|
|
744
914
|
}
|
|
745
915
|
],
|
|
@@ -748,7 +918,20 @@
|
|
|
748
918
|
"VALIDATE": {
|
|
749
919
|
"label": "Continuer",
|
|
750
920
|
"nextStep": {
|
|
751
|
-
"
|
|
921
|
+
"conditionals": [
|
|
922
|
+
{
|
|
923
|
+
"conditions": ["runtimeOptions.postQualificationAppointment === true"],
|
|
924
|
+
"nextStep": {
|
|
925
|
+
"code": "__END__"
|
|
926
|
+
}
|
|
927
|
+
},
|
|
928
|
+
{
|
|
929
|
+
"conditions": ["runtimeOptions.postQualificationAppointment === false"],
|
|
930
|
+
"nextStep": {
|
|
931
|
+
"code": "PROJECT_UPDATED"
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
]
|
|
752
935
|
}
|
|
753
936
|
}
|
|
754
937
|
}
|
|
@@ -764,29 +947,33 @@
|
|
|
764
947
|
}
|
|
765
948
|
}
|
|
766
949
|
},
|
|
767
|
-
"
|
|
768
|
-
"code": "
|
|
950
|
+
"START_LATER": {
|
|
951
|
+
"code": "START_LATER",
|
|
769
952
|
"type": "STEP",
|
|
770
953
|
"component": "PbPedagogy",
|
|
771
954
|
"payload": {
|
|
772
|
-
"code": "
|
|
955
|
+
"code": "START_LATER",
|
|
773
956
|
"viewModel": {
|
|
774
|
-
"title": "Retrouvez le lien pour
|
|
957
|
+
"title": "Retrouvez le lien pour continuer la préparation de votre RDV dans le mail de confirmation du RDV",
|
|
775
958
|
"icon": "https://storage.googleapis.com/project-booster-media/vad/fin-de-parcours/mail_80.svg",
|
|
776
|
-
"description":
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
959
|
+
"description": [
|
|
960
|
+
{
|
|
961
|
+
"icon": "https://storage.googleapis.com/project-booster-media/vad/lm-advisor.png",
|
|
962
|
+
"label": "Retrouvez votre projet dans votre compte Leroy Merlin, vous pourrez encore ajouter des plans et photos."
|
|
963
|
+
},
|
|
964
|
+
{
|
|
965
|
+
"icon": "https://storage.googleapis.com/project-booster-media/vad/lm-advisor.png",
|
|
966
|
+
"label": "Votre conseiller a accès à vos plans et informations utiles pour le rendez-vous."
|
|
967
|
+
}
|
|
968
|
+
]
|
|
782
969
|
},
|
|
783
970
|
"cards": [
|
|
784
971
|
{
|
|
785
|
-
"code": "
|
|
972
|
+
"code": "Retrouver mon projet dans mon compte Leroy Merlin",
|
|
786
973
|
"viewModel": {
|
|
787
|
-
"url": "https://www.leroymerlin.fr/
|
|
788
|
-
"image": "https://
|
|
789
|
-
"title": "
|
|
974
|
+
"url": "https://www.leroymerlin.fr/espace-perso/espace-projets.html#/projects/@@PB_PROJECT_ID_FILLER@@",
|
|
975
|
+
"image": "https://storage.googleapis.com/project-booster-media/vad/fin-de-parcours/Qualif-RDV-VAD-%20Conseiller-de-vente.png",
|
|
976
|
+
"title": "Retrouver mon projet dans mon compte Leroy Merlin",
|
|
790
977
|
"width": "full",
|
|
791
978
|
"widthFromM": "1of3",
|
|
792
979
|
"widthFromL": "1of3"
|
|
@@ -816,62 +1003,45 @@
|
|
|
816
1003
|
}
|
|
817
1004
|
}
|
|
818
1005
|
]
|
|
819
|
-
},
|
|
820
|
-
"slots": {
|
|
821
|
-
"stickyTop": {
|
|
822
|
-
"display": false
|
|
823
|
-
}
|
|
824
1006
|
}
|
|
825
1007
|
},
|
|
826
|
-
"
|
|
827
|
-
"code": "
|
|
1008
|
+
"PROJECT_UPDATED": {
|
|
1009
|
+
"code": "PROJECT_UPDATED",
|
|
828
1010
|
"type": "STEP",
|
|
829
1011
|
"component": "PbPedagogy",
|
|
830
1012
|
"payload": {
|
|
831
|
-
"code": "
|
|
1013
|
+
"code": "PROJECT_UPDATED",
|
|
832
1014
|
"viewModel": {
|
|
833
|
-
"title": "
|
|
834
|
-
"icon": "https://storage.googleapis.com/project-booster-media/vad/fin-de-parcours/
|
|
835
|
-
"description":
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
"
|
|
842
|
-
"
|
|
843
|
-
"title": "Estimer votre budget cuisine en quelques clics",
|
|
844
|
-
"width": "full",
|
|
845
|
-
"widthFromM": "1of3",
|
|
846
|
-
"widthFromL": "1of3"
|
|
847
|
-
}
|
|
848
|
-
},
|
|
849
|
-
{
|
|
850
|
-
"code": "Découvrir nos gammes de cuisines",
|
|
851
|
-
"viewModel": {
|
|
852
|
-
"url": "https://www.leroymerlin.fr/produits/cuisine/cuisine-equipee-delinia-id/",
|
|
853
|
-
"image": "https://storage.googleapis.com/project-booster-media/kitchen/kitchen-range.jpeg",
|
|
854
|
-
"title": "Découvrir nos gammes de cuisines",
|
|
855
|
-
"width": "full",
|
|
856
|
-
"widthFromM": "1of3",
|
|
857
|
-
"widthFromL": "1of3"
|
|
1015
|
+
"title": "Les informations de votre projet ont été mises à jour",
|
|
1016
|
+
"icon": "https://storage.googleapis.com/project-booster-media/vad/fin-de-parcours/check_80.svg",
|
|
1017
|
+
"description": [
|
|
1018
|
+
{
|
|
1019
|
+
"label": "Retrouvez votre projet dans votre compte Leroy Merlin, vous pourrez encore ajouter des plans et photos",
|
|
1020
|
+
"icon": "https://storage.googleapis.com/project-booster-media/vad/lm-advisor.png"
|
|
1021
|
+
},
|
|
1022
|
+
{
|
|
1023
|
+
"label": "Votre conseiller a accès à vos plans et informations utiles pour le rendez-vous.",
|
|
1024
|
+
"icon": "https://storage.googleapis.com/project-booster-media/vad/lm-advisor.png"
|
|
858
1025
|
}
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
"
|
|
865
|
-
"
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
"widthFromM": "1of3",
|
|
869
|
-
"widthFromL": "1of3"
|
|
1026
|
+
]
|
|
1027
|
+
},
|
|
1028
|
+
"multiSelect": {
|
|
1029
|
+
"actions": {
|
|
1030
|
+
"VALIDATE": {
|
|
1031
|
+
"label": "Continuer et prendre RDV",
|
|
1032
|
+
"nextStep": {
|
|
1033
|
+
"code": "APPOINTMENT_FORM"
|
|
1034
|
+
}
|
|
870
1035
|
}
|
|
871
1036
|
}
|
|
872
|
-
|
|
1037
|
+
}
|
|
873
1038
|
}
|
|
874
1039
|
},
|
|
1040
|
+
"APPOINTMENT_FORM": {
|
|
1041
|
+
"code": "APPOINTMENT_FORM",
|
|
1042
|
+
"type": "STEP",
|
|
1043
|
+
"component": "PbAppointmentForm"
|
|
1044
|
+
},
|
|
875
1045
|
"__END__": {
|
|
876
1046
|
"code": "__END__",
|
|
877
1047
|
"type": "END",
|
|
@@ -879,9 +1049,12 @@
|
|
|
879
1049
|
"payload": {
|
|
880
1050
|
"code": "__END__",
|
|
881
1051
|
"viewModel": {
|
|
882
|
-
"title": "
|
|
1052
|
+
"title": "Les informations de votre projet ont été mises à jour",
|
|
883
1053
|
"icon": "https://storage.googleapis.com/project-booster-media/vad/fin-de-parcours/check_80.svg",
|
|
884
|
-
"description":
|
|
1054
|
+
"description": {
|
|
1055
|
+
"label": "Votre conseiller aura accès à vos plans et informations utiles pour le rendez-vous. Si vous souhaitez encore ajouter des plans retrouvez votre projet dans votre compte Leroy Merlin.",
|
|
1056
|
+
"icon": "https://storage.googleapis.com/project-booster-media/vad/lm-advisor.png"
|
|
1057
|
+
}
|
|
885
1058
|
},
|
|
886
1059
|
"cards": [
|
|
887
1060
|
{
|
|
@@ -57,4 +57,38 @@ const declarationsWithAppointment = async (data: any) => {
|
|
|
57
57
|
);
|
|
58
58
|
};
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
const declarationsWithoutAppointment = async (data: any) => {
|
|
61
|
+
const response = await clientApi.post('/declarations-without-appointment', data, {
|
|
62
|
+
headers: { 'Content-Type': 'application/json' },
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
return JSON.parse(
|
|
66
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
67
|
+
return `: "${he.escape($1)}"`;
|
|
68
|
+
}),
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const linkInhabitantProjectToAppointmentQualification = async (data: any, inhabitantProjectId: any) => {
|
|
73
|
+
const response = await clientApi.post(
|
|
74
|
+
`/inhabitant-projects/${inhabitantProjectId}/appointment-qualifications`,
|
|
75
|
+
data,
|
|
76
|
+
{
|
|
77
|
+
headers: { 'Content-Type': 'application/json' },
|
|
78
|
+
},
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
return JSON.parse(
|
|
82
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
83
|
+
return `: "${he.escape($1)}"`;
|
|
84
|
+
}),
|
|
85
|
+
);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export {
|
|
89
|
+
linkInhabitantProjectToAppointmentQualification,
|
|
90
|
+
declarationsWithAppointment,
|
|
91
|
+
saveAnswersByAppointmentQualificationId,
|
|
92
|
+
getAppointmentQualification,
|
|
93
|
+
declarationsWithoutAppointment,
|
|
94
|
+
};
|
|
@@ -2,12 +2,15 @@ import {
|
|
|
2
2
|
getAppointmentQualification,
|
|
3
3
|
saveAnswersByAppointmentQualificationId,
|
|
4
4
|
declarationsWithAppointment,
|
|
5
|
+
declarationsWithoutAppointment,
|
|
6
|
+
linkInhabitantProjectToAppointmentQualification,
|
|
5
7
|
} from '../../services/api/appointmentQualificationsApi';
|
|
6
8
|
import { sendAppointmentQualificationEvent, sendAppointmentQualificationAnswers } from '../../services/api/eventsApi';
|
|
7
9
|
import { ActionContext } from 'vuex';
|
|
8
10
|
import { State } from '@/stores/state';
|
|
9
11
|
|
|
10
12
|
export interface AppointmentQualificationState {
|
|
13
|
+
clicRDVBaseUrl: string;
|
|
11
14
|
createProjectError: Error;
|
|
12
15
|
isLoadingProject: boolean;
|
|
13
16
|
appointmentLinkedError: Error;
|
|
@@ -53,6 +56,9 @@ export default {
|
|
|
53
56
|
getCurrentAppointmentQualification(state: AppointmentQualificationState) {
|
|
54
57
|
return state.currentAppointmentQualification;
|
|
55
58
|
},
|
|
59
|
+
getClicRDVBaseUrl(state: AppointmentQualificationState) {
|
|
60
|
+
return state.clicRDVBaseUrl;
|
|
61
|
+
},
|
|
56
62
|
},
|
|
57
63
|
|
|
58
64
|
mutations: {
|
|
@@ -74,6 +80,9 @@ export default {
|
|
|
74
80
|
setSession(state: AppointmentQualificationState, sessions: any) {
|
|
75
81
|
state.sessions = sessions;
|
|
76
82
|
},
|
|
83
|
+
setClicRDVBaseUrl(state: AppointmentQualificationState, baseURL: any) {
|
|
84
|
+
state.clicRDVBaseUrl = baseURL;
|
|
85
|
+
},
|
|
77
86
|
},
|
|
78
87
|
|
|
79
88
|
actions: {
|
|
@@ -125,6 +134,48 @@ export default {
|
|
|
125
134
|
commit('setIsLoadingProject', false);
|
|
126
135
|
}
|
|
127
136
|
},
|
|
137
|
+
async createDeclarationProjectWithoutAppointment({ commit, state }: AppointmentQualificationContext) {
|
|
138
|
+
try {
|
|
139
|
+
const project = {
|
|
140
|
+
businessUnit: state.sessions.businessUnit,
|
|
141
|
+
name: state.sessions.appointmentQualificationFormStructure['__START__']?.meta?.projectName,
|
|
142
|
+
sourceDetail: state.sessions.sourceDetail,
|
|
143
|
+
store: state.sessions.storeId,
|
|
144
|
+
projectKindHref: state.sessions.appointmentQualificationFormStructure['__START__']?.meta?.projectKindHref,
|
|
145
|
+
projectTypeHref: state.sessions.appointmentQualificationFormStructure['__START__']?.meta?.projectTypeHref,
|
|
146
|
+
domesticSpaceHref: state.sessions.appointmentQualificationFormStructure['__START__']?.meta?.domesticSpaceHref,
|
|
147
|
+
correlationId: state.sessions.correlationId,
|
|
148
|
+
};
|
|
149
|
+
const result = await declarationsWithoutAppointment(project);
|
|
150
|
+
commit('setCurrentAppointmentQualification', result);
|
|
151
|
+
commit('setIsLoadingProject', false);
|
|
152
|
+
} catch (e) {
|
|
153
|
+
commit('setCreateProjectError', new Error());
|
|
154
|
+
commit('setIsLoadingProject', false);
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
async linkProjectWithAppointment({ commit, state }: AppointmentQualificationContext) {
|
|
158
|
+
commit('setIsLoadingProject', true);
|
|
159
|
+
try {
|
|
160
|
+
const data = {
|
|
161
|
+
clicRDVData: {
|
|
162
|
+
calendarId: state.sessions.calendarId,
|
|
163
|
+
groupId: state.sessions.groupId,
|
|
164
|
+
appointmentId: state.sessions.appointmentId,
|
|
165
|
+
},
|
|
166
|
+
correlationId: state.sessions.correlationId,
|
|
167
|
+
};
|
|
168
|
+
const result = await linkInhabitantProjectToAppointmentQualification(
|
|
169
|
+
state.currentAppointmentQualification.inhabitantProjectId,
|
|
170
|
+
data,
|
|
171
|
+
);
|
|
172
|
+
commit('setCurrentAppointmentQualification', result);
|
|
173
|
+
commit('setIsLoadingProject', false);
|
|
174
|
+
} catch (e) {
|
|
175
|
+
commit('setIsLoadingProject', false);
|
|
176
|
+
commit('setIsAppointmentsError', e);
|
|
177
|
+
}
|
|
178
|
+
},
|
|
128
179
|
async startEndAppointmentQualificationEvent(_: AppointmentQualificationContext, event: Event) {
|
|
129
180
|
await sendAppointmentQualificationEvent(event);
|
|
130
181
|
},
|
|
@@ -140,5 +191,12 @@ export default {
|
|
|
140
191
|
initSessions({ commit }: AppointmentQualificationContext, sessions: any) {
|
|
141
192
|
commit('setSession', sessions);
|
|
142
193
|
},
|
|
194
|
+
loadClicRDVBaseUrl({ commit }: AppointmentQualificationContext) {
|
|
195
|
+
if ((<any>window).config) {
|
|
196
|
+
commit('setClicRDVBaseUrl', (<any>window).config.VUE_APP_CLICRDV_BASE_URL);
|
|
197
|
+
} else {
|
|
198
|
+
commit('setClicRDVBaseUrl', 'https://www.clicrdv.com');
|
|
199
|
+
}
|
|
200
|
+
},
|
|
143
201
|
},
|
|
144
202
|
};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { ActionContext } from 'vuex';
|
|
2
|
-
import { State } from '@/stores/state';
|
|
3
|
-
|
|
4
|
-
type PedagogyContext = ActionContext<any, State>;
|
|
5
|
-
|
|
6
|
-
const pbPedagogyStore = {
|
|
7
|
-
state: {},
|
|
8
|
-
getters: {},
|
|
9
|
-
mutations: {},
|
|
10
|
-
actions: {
|
|
11
|
-
sendEventToBus(_: PedagogyContext, action: any): void {
|
|
12
|
-
console.log('Event sent to bus: ', JSON.stringify(action, null, '\t'));
|
|
13
|
-
},
|
|
14
|
-
},
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export { pbPedagogyStore };
|