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.
Files changed (19) hide show
  1. package/package.json +1 -1
  2. package/src/components/appointment/PbAppointmentForm.stories.mdx +94 -0
  3. package/src/components/appointment/PbAppointmentForm.vue +57 -0
  4. package/src/components/appointment/PbAppointmentStartSection.vue +52 -1
  5. 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
  6. package/src/components/pedagogy/PbPedagogy.stories.mdx +2 -2
  7. package/src/components/pedagogy/PbPedagogy.vue +41 -9
  8. package/src/components/pedagogy/default-payload.json +6 -1
  9. 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
  10. 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
  11. package/src/components/question/PbQuestion.vue +2 -2
  12. package/src/components/question/list-select/PbListSelect.vue +1 -1
  13. package/src/components/scenario/{PbScenario-Features-Test.stories.mdx → PbScenario-Features-Appointment.stories.mdx} +59 -3
  14. package/src/components/scenario/PbScenario.vue +2 -0
  15. package/src/components/scenario/scenarii/appointment-qualification-kitchen.json +242 -69
  16. package/src/services/api/appointmentQualificationsApi.ts +35 -1
  17. package/src/services/api/mocks/inhabitantsMock.ts +1 -0
  18. package/src/stores/modules/appointmentQualificationStore.ts +58 -0
  19. package/src/components/pedagogy/PbPedagogyStore.ts +0 -17
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "project-booster-vue",
3
- "version": "9.6.0",
3
+ "version": "9.8.1",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -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">Gagnez du temps en préparant votre Rendez-vous</div>
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 { pbPedagogyStore } from './PbPedagogyStore';
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(pbPedagogyStore, [])]}
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
- <div class="pb-pedagogy__content-description">
8
- <m-icon :icon="IMAGE_SRC" />
9
- <div class="pb-pedagogy__content-description-text" v-html="payload.viewModel.description" />
10
- </div>
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
- window.open(card.viewModel.url, '_blank');
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": " Les mesures et &nbsp; <span class='pb-pedagogy__content-description-bold'> plans de votre pièce </span> &nbsp; sont importants pour le rendez-vous. Ils\n permettront à votre conseiller de créer un &nbsp; <span class='pb-pedagogy__content-description-bold'> plan 3D adapté </span> &nbsp; à votre cuisine.\n <span class='pb-pedagogy__content-description-bold'> Vous pouvez les ajouter à partir à partir du mail que vous avez reçu. </span>",
5
+ "description": [
6
+ {
7
+ "label": "Les mesures et &nbsp; <span class='pb-pedagogy__content-description-bold'> plans de votre pièce </span> &nbsp; sont importants pour le rendez-vous. Ils\n permettront à votre conseiller de créer un &nbsp; <span class='pb-pedagogy__content-description-bold'> plan 3D adapté </span> &nbsp; à 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 overriden values will change
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 questio is answered
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, Preview, Meta, Props, ArgsTable, Source, Canvas } from '@storybook/addon-docs';
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={{ scenarios: DEFAULT_PAYLOAD, runtimeOptions: { hasConfigurations: true } }}
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": ["isAnswerMatching('START_SCENARIO', 'LATER')"],
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
- "code": "__END__"
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
- "code": "ADD_PLAN_LATER"
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
- "code": "ADD_PLAN_LATER"
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
- "code": "__END__"
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
- "code": "__END__"
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
- "code": "__END__"
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
- "ADD_PLAN_LATER": {
768
- "code": "ADD_PLAN_LATER",
950
+ "START_LATER": {
951
+ "code": "START_LATER",
769
952
  "type": "STEP",
770
953
  "component": "PbPedagogy",
771
954
  "payload": {
772
- "code": "ADD_PLAN_LATER",
955
+ "code": "START_LATER",
773
956
  "viewModel": {
774
- "title": "Retrouvez le lien pour ajouter un plan dans le mail de confirmation du RDV",
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": "N’oubliez pas d’ajouter un plan avec les mesures de votre pièce. Votre conseiller à besoin de ces informations pour la conception de votre cuisine en 3D.",
777
- "downloadButton": {
778
- "label": "Télécharger le guide pour faire votre plan",
779
- "theme": "bordered",
780
- "href": "https://storage.googleapis.com/project-booster-media/vad/PDF/Plan_Prise-de-mesure_Leroy-Merlin.pdf"
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": "Estimer votre budget cuisine en quelques clics",
972
+ "code": "Retrouver mon projet dans mon compte Leroy Merlin",
786
973
  "viewModel": {
787
- "url": "https://www.leroymerlin.fr/estimez-le-cout-de-votre-prochaine-cuisine.html?leadSource=Appointment_Qualification&leadSourceDetail=Cuisine",
788
- "image": "https://media.leroymerlin.fr/Capture/37/bc/a121f7e74212ad2d356fd3cf2c8a/estimer-mon-budget-cuisine5e5d20ae063b330009a4a372.jpg?width=500&auto=webp&crop=16:9",
789
- "title": "Estimer votre budget cuisine en quelques clics",
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
- "START_LATER": {
827
- "code": "START_LATER",
1008
+ "PROJECT_UPDATED": {
1009
+ "code": "PROJECT_UPDATED",
828
1010
  "type": "STEP",
829
1011
  "component": "PbPedagogy",
830
1012
  "payload": {
831
- "code": "START_LATER",
1013
+ "code": "PROJECT_UPDATED",
832
1014
  "viewModel": {
833
- "title": "Retrouvez le lien pour continuer la préparation de votre RDV dans le mail de confirmation du RDV",
834
- "icon": "https://storage.googleapis.com/project-booster-media/vad/fin-de-parcours/mail_80.svg",
835
- "description": "N’oubliez pas de poursuivre la préparation de votre RDV. Votre conseiller à besoin de ces informations pour la conception de votre cuisine en 3D"
836
- },
837
- "cards": [
838
- {
839
- "code": "Estimer votre budget cuisine en quelques clics",
840
- "viewModel": {
841
- "url": "https://www.leroymerlin.fr/estimez-le-cout-de-votre-prochaine-cuisine.html?leadSource=Appointment_Qualification&leadSourceDetail=Cuisine",
842
- "image": "https://media.leroymerlin.fr/Capture/37/bc/a121f7e74212ad2d356fd3cf2c8a/estimer-mon-budget-cuisine5e5d20ae063b330009a4a372.jpg?width=500&auto=webp&crop=16:9",
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
- "code": "Des idées et conseils pour votre cuisine",
862
- "viewModel": {
863
- "value": "3",
864
- "url": "https://www.leroymerlin.fr/inspiration/les-meilleures-idees-pour-chaque-piece/cuisine/",
865
- "image": "https://storage.googleapis.com/project-booster-media/vad/fin-de-parcours/inspiration-cuisine.jpg",
866
- "title": "Des idées et conseils pour votre cuisine",
867
- "width": "full",
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": "Vos informations ont été mises à jour",
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": "Votre conseiller a accès à vos plans et informations utiles pour le rendez-vous. Si vous souhaitez encore ajouter des plans ou mesures, cliquez sur le lien dans le mail de rappel"
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
- export { declarationsWithAppointment, saveAnswersByAppointmentQualificationId, getAppointmentQualification };
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
+ };
@@ -6,6 +6,7 @@ export const getInhabitantByIdResolver = (req: RestRequest, res: ResponseComposi
6
6
  ctx.json({
7
7
  firstName: 'Jean',
8
8
  lastName: 'Dupont',
9
+ email: 'jean.dupont@yopmail.com',
9
10
  }),
10
11
  );
11
12
  };
@@ -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 };