project-booster-vue 10.6.1 → 10.7.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "project-booster-vue",
3
- "version": "10.6.1",
3
+ "version": "10.7.1",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -83,17 +83,17 @@
83
83
 
84
84
  <script lang="ts" setup>
85
85
  import { MButton } from '@mozaic-ds/vue-3';
86
- import { PropType, ref, defineEmits, defineProps } from 'vue';
86
+ import { PropType, ref, defineEmits, defineProps, computed, ComputedRef } from 'vue';
87
87
  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
91
  import { useStore } from 'vuex';
92
92
  import { callAction } from '../services/navigate';
93
-
94
- const emit = defineEmits(['go-back', 'step-completed']);
95
- const message = ref('');
96
- const store = useStore();
93
+ import cloneDeep from 'lodash.clonedeep';
94
+ import DEFAULT_PAYLOAD from './default-payload.json';
95
+ import merge from 'lodash.merge';
96
+ import { decorate } from '@/services/decorate';
97
97
 
98
98
  const props = defineProps({
99
99
  /**
@@ -121,6 +121,33 @@ const props = defineProps({
121
121
  },
122
122
  });
123
123
 
124
+ const store = useStore();
125
+
126
+ const computedPayload = computed(() => {
127
+ const tempPayload = cloneDeep(DEFAULT_PAYLOAD);
128
+ return merge(tempPayload, props.payload);
129
+ });
130
+
131
+ const computeDefaultValue = (
132
+ runtimeOptions: any,
133
+ answers: Map<string, ScenarioStepAnswer[]>,
134
+ computedPayload: ComputedRef<any>,
135
+ ) => {
136
+ let message;
137
+ if (computedPayload?.value?.value) {
138
+ message = decorate(
139
+ answers,
140
+ runtimeOptions,
141
+ computedPayload?.value?.value?.message,
142
+ computedPayload?.value?.defaultDecoratorValue ?? '',
143
+ );
144
+ }
145
+ return message;
146
+ };
147
+
148
+ const emit = defineEmits(['go-back', 'step-completed']);
149
+ const message = ref(computeDefaultValue(props.runtimeOptions, props.answers!, computedPayload));
150
+
124
151
  /**
125
152
  * Send action to completed step
126
153
  * @param action
@@ -0,0 +1,63 @@
1
+ import { Anchor, Story, Preview, Meta, Props, ArgsTable, Source, Canvas } from '@storybook/addon-docs';
2
+ import DEFAULT_PAYLOAD from './default-payload';
3
+ import { nestedAppDecorator } from '../../../../.storybook/nested-app-decorator';
4
+ import MPbTimify from './MPbTimify';
5
+ import inhabitantsStore from '../../../stores/modules/inhabitantsStore';
6
+ import timifyStore from '../../../stores/modules/timifyStore';
7
+
8
+ <Meta
9
+ title="Project Booster/Rework/Timify/MPbTimify 🦠"
10
+ component={MPbTimify}
11
+ argTypes={{
12
+ payload: {
13
+ table: {
14
+ defaultValue: {
15
+ summary: 'object',
16
+ detail: JSON.stringify(DEFAULT_PAYLOAD, null, ' '),
17
+ },
18
+ },
19
+ control: {
20
+ type: 'object',
21
+ },
22
+ },
23
+ }}
24
+ parameters={{
25
+ layout: 'fullscreen',
26
+ }}
27
+ decorators={[
28
+ nestedAppDecorator(
29
+ {
30
+ modules: {
31
+ inhabitants: inhabitantsStore,
32
+ timify: timifyStore,
33
+ },
34
+ mutations: {},
35
+ actions: {},
36
+ },
37
+ [],
38
+ ),
39
+ ]}
40
+ />
41
+
42
+ # 🦠 `MPbTimify` - Component
43
+
44
+ The `MPbTimify` component to display information that user needed.
45
+
46
+ export const TemplateSandbox = (args, { argTypes }) => ({
47
+ props: Object.keys(argTypes),
48
+ components: { MPbTimify },
49
+ setup() {
50
+ return { args };
51
+ },
52
+ template: `<m-pb-timify
53
+ :payload="args.payload"
54
+ />`,
55
+ });
56
+
57
+ ## showCase
58
+
59
+ <Canvas>
60
+ <Story inline={false} height="862px" name="101 Sandbox" args={{ payload: DEFAULT_PAYLOAD }}>
61
+ {TemplateSandbox.bind({})}
62
+ </Story>
63
+ </Canvas>
@@ -0,0 +1,77 @@
1
+ <template>
2
+ <div class="m-pb-timify">
3
+ <div class="m-pb-timify__iframe" v-if="!showClicRDV">
4
+ <iframe :src="iframeUri" frameborder="0"></iframe>
5
+ </div>
6
+ <pb-appointment-form v-else :payload="payload"></pb-appointment-form>
7
+ </div>
8
+ </template>
9
+
10
+ <script lang="ts" setup>
11
+ import { ScenarioStepAnswer } from '@/types/pb/Scenario';
12
+ import { PropType, computed, onBeforeMount } from 'vue';
13
+ import { ref } from 'vue';
14
+ import { useStore } from 'vuex';
15
+ import PbAppointmentForm from '@/components/appointment/PbAppointmentForm.vue';
16
+
17
+ const props = defineProps({
18
+ /**
19
+ * The component view model and business data as an object. The provided prop
20
+ * is merged with the default payload value so only overriden values will change
21
+ * from the default ones.
22
+ */
23
+ payload: {
24
+ type: Object,
25
+ default: () => ({}),
26
+ },
27
+ /**
28
+ * The previous answers to inject
29
+ */
30
+ answers: {
31
+ type: Object as PropType<Map<string, ScenarioStepAnswer[]>>,
32
+ default: () => new Map<string, ScenarioStepAnswer[]>(),
33
+ },
34
+ });
35
+
36
+ const iframeUri = ref('https://book.timify.com/services?');
37
+ const store = useStore();
38
+ const showClicRDV = computed(() => store.getters['timify/getShowClicRDV']);
39
+ const getShowServices = computed(() => store.getters['timify/getShowServices']);
40
+ const getAccountId = computed(() => store.getters['timify/getAccountId']);
41
+ const currentUser = computed(() => store.getters['inhabitants/getCurrentInhabitant']);
42
+ const projectId = computed(() => store.getters['appointmentQualification/getCurrentAppointmentQualification']);
43
+ const collaboratorUri = computed(() => store.getters['timify/getCollaboratorUri']);
44
+
45
+ onBeforeMount(() => {
46
+ store.dispatch('timify/loadTimify', {
47
+ payload: props.payload.viewModel.appointmentCategory,
48
+ storeId: store.getters.metadata.storeId || '',
49
+ });
50
+
51
+ store.dispatch('timify/loadCollaboratorUri', {
52
+ projectId,
53
+ });
54
+
55
+ iframeUri.value += `accountId=${getAccountId.value}&showServices=${getShowServices.value}`;
56
+ iframeUri.value += `&guestFirstName=${currentUser.value.firstname}&guestLastName=${currentUser.value.lastname}&guestEmail=${currentUser.value.email}&guestPhone=${currentUser.value.phone}`;
57
+ iframeUri.value += `&externalCustomerField[inhabitantProjectId]=${projectId.value}&externalCustomerField[collaboratorLink]=${collaboratorUri.value}&hideCloseButton=true`;
58
+ });
59
+ </script>
60
+
61
+ <style lang="scss">
62
+ @import 'pb-variables';
63
+ @import '../styles/global.scss';
64
+
65
+ .m-pb-timify {
66
+ width: calc(100% - $mu250);
67
+ margin: $mu200 auto $mu250 auto;
68
+ padding: 0 $mu125;
69
+
70
+ &__iframe {
71
+ iframe {
72
+ width: 100%;
73
+ height: 100vh;
74
+ }
75
+ }
76
+ }
77
+ </style>
@@ -0,0 +1,6 @@
1
+ {
2
+ "viewModel": {
3
+ "title": "Votre prise de rendez-vous ?",
4
+ "appointmentCategory": "SDB"
5
+ }
6
+ }
@@ -149,6 +149,7 @@ import MPbNameInput from '../rework/question/name-input/MPbNameInput.vue';
149
149
  import MPbExitOptions from '../rework/exit-options/MPbExitOptions.vue';
150
150
  import MPbUploadDocument from '../rework/question/upload-document/MPbUploadDocument.vue';
151
151
  import MPbMediaUpload from '../rework/media/upload/MPbMediaUpload.vue';
152
+ import MPbTimify from '../rework/timify/MPbTimify.vue';
152
153
 
153
154
  import { areConditionsValid } from '../../services/scenarioConditionals';
154
155
  import {
@@ -204,6 +205,7 @@ export default defineComponent({
204
205
  MPbUploadDocument,
205
206
  MPbConfigurationsImport,
206
207
  MPbMediaUpload,
208
+ MPbTimify,
207
209
  },
208
210
 
209
211
  props: {
@@ -0,0 +1,33 @@
1
+ import axios from 'axios';
2
+ import { escape } from '../../services/htmlEscape';
3
+
4
+ export const clientApi = axios.create({
5
+ baseURL: '/project-booster/api',
6
+ });
7
+
8
+ if ((<any>window).config) {
9
+ clientApi.defaults.baseURL = (<any>window).config.VUE_APP_DEFAULT_BASE_URL;
10
+ }
11
+
12
+ /**
13
+ * Get timify object with appointmentCategory && storeId
14
+ * @param appointmentCategory
15
+ * @param storeId
16
+ * @returns
17
+ */
18
+ export const getTimifyObject = async (appointmentCategory: string, storeId: string) => {
19
+ try {
20
+ const response = await clientApi.get(
21
+ `/appointment-qualifications/is-timify-enabled?${
22
+ storeId ? '?storeId=' + storeId : ''
23
+ }&appointmentCategory=${appointmentCategory}`,
24
+ );
25
+ return JSON.parse(
26
+ JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
27
+ return `: "${escape($1)}"`;
28
+ }),
29
+ );
30
+ } catch (e) {
31
+ return false;
32
+ }
33
+ };
@@ -0,0 +1,87 @@
1
+ import { ActionContext } from 'vuex';
2
+ import { State } from '@/stores/state';
3
+ import { getTimifyObject } from '@/services/api/timifyApi';
4
+ import { TimifyServices, TimifyState } from '@/types/pb/Timify';
5
+
6
+ type TimifyContext = ActionContext<TimifyState, State>;
7
+
8
+ enum callboratorUris {
9
+ prod = 'https://collaborators.pb-prod-adeo-disp.tech.adeo.cloud/index.html/projects/',
10
+ prep = 'https://collaborators.pb-preprod-adeo-disp.tech.adeo.cloud/index.html/projects/',
11
+ dev = 'https://collaborators.pb-dev-adeo-disp.tech.adeo.cloud/index.html/projects/',
12
+ }
13
+
14
+ export default {
15
+ namespaced: true,
16
+ state: {
17
+ showServices: [],
18
+ accountId: '',
19
+ collaboratorUri: '',
20
+ showClicRDV: false,
21
+ },
22
+ getters: {
23
+ getShowServices(state: TimifyState) {
24
+ return state.showServices;
25
+ },
26
+ getAccountId(state: TimifyState) {
27
+ return state.accountId;
28
+ },
29
+ getCollaboratorUri(state: TimifyState) {
30
+ return state.collaboratorUri;
31
+ },
32
+ getShowClicRDV(state: TimifyState) {
33
+ return state.showClicRDV;
34
+ },
35
+ },
36
+ mutations: {
37
+ setShowServices(state: TimifyState, services: string[]) {
38
+ state.showServices = services;
39
+ },
40
+ setAccountId(state: TimifyState, accountId: string) {
41
+ state.accountId = accountId;
42
+ },
43
+ setCollaboratorUri(state: TimifyState, collaboratorUri: string) {
44
+ state.collaboratorUri = collaboratorUri;
45
+ },
46
+ setShowClicRDV(state: TimifyState, showClicRDV: boolean) {
47
+ state.showClicRDV = showClicRDV;
48
+ },
49
+ },
50
+ actions: {
51
+ async loadTimify(
52
+ { commit, state }: TimifyContext,
53
+ { appointmentCategory, storeId }: { appointmentCategory: string; storeId: string },
54
+ ) {
55
+ const timify = await getTimifyObject(appointmentCategory, storeId);
56
+
57
+ if (timify) {
58
+ if (timify.services.length) {
59
+ const servicesIds = timify.services.map((service: TimifyServices) => {
60
+ return service.id;
61
+ });
62
+ commit('setShowServices', servicesIds.toString());
63
+ } else {
64
+ commit('setShowClicRDV', true);
65
+ }
66
+
67
+ if (timify.company) {
68
+ const accountId = timify.company.id;
69
+ commit('setAccountId', accountId);
70
+ }
71
+ } else {
72
+ commit('setShowClicRDV', true);
73
+ }
74
+ },
75
+ async loadCollaboratorUri({ commit, state }: TimifyContext, { projectId }: { projectId: string }) {
76
+ const baseurl = window.location.host;
77
+
78
+ if (baseurl.includes('prep')) {
79
+ commit('setCollaboratorUri', callboratorUris.prep + projectId);
80
+ } else if (baseurl.includes('uat') || baseurl.includes('localhost')) {
81
+ commit('setCollaboratorUri', callboratorUris.dev + projectId);
82
+ } else {
83
+ commit('setCollaboratorUri', callboratorUris.prod + projectId);
84
+ }
85
+ },
86
+ },
87
+ };
@@ -9,6 +9,7 @@ import documentsStore from './modules/documentsStore';
9
9
  import consentStore from './modules/consentStore';
10
10
  import productsStore from './modules/productsStore';
11
11
  import trezorStore from './modules/trezorStore';
12
+ import timifyStore from './modules/timifyStore';
12
13
  import cloneDeep from 'lodash.clonedeep';
13
14
  import { State } from '@/stores/state';
14
15
  import { ActionContext } from 'vuex';
@@ -28,6 +29,7 @@ export default {
28
29
  consent: consentStore,
29
30
  products: productsStore,
30
31
  trezor: trezorStore,
32
+ timify: timifyStore,
31
33
  },
32
34
  mutations: {
33
35
  eventBusSendEvent(state: State, { code, payload }: { code: string; payload: any }) {
@@ -0,0 +1,15 @@
1
+ export interface TimifyState {
2
+ showServices: string[];
3
+ accountId: string;
4
+ collaboratorUri: string;
5
+ showClicRDV: boolean;
6
+ }
7
+
8
+ export interface TimifyServices {
9
+ id: string;
10
+ categoryId: string;
11
+ externalId: string;
12
+ globalId: string;
13
+ name: string;
14
+ isBookable: boolean;
15
+ }