project-booster-vue 9.48.0 → 9.49.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/landing/PbProjectsLanding.vue +1 -1
- package/src/components/rework/products/MPbProducts.stories.mdx +48 -0
- package/src/components/rework/products/MPbProducts.vue +231 -0
- package/src/components/rework/products/default-payload.json +21 -0
- package/src/components/rework/services/navigateScenario.ts +0 -0
- package/src/components/rework/styles/global.scss +15 -0
- package/src/components/rework/types/genericPayload.ts +8 -0
- package/src/components/scenario/PbScenario.vue +2 -0
package/package.json
CHANGED
|
@@ -451,7 +451,7 @@ export default defineComponent({
|
|
|
451
451
|
{
|
|
452
452
|
title: 'Découvrir les offres de financement',
|
|
453
453
|
image: 'https://storage.googleapis.com/project-booster-media/landing-projet/aide-financement.png',
|
|
454
|
-
href: '/
|
|
454
|
+
href: '/services/service-client/financement.html',
|
|
455
455
|
},
|
|
456
456
|
],
|
|
457
457
|
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { nestedAppDecorator } from '../../../../.storybook/nested-app-decorator';
|
|
2
|
+
import { ArgsTable, Canvas, Meta, Source, Story } from '@storybook/addon-docs';
|
|
3
|
+
import cloneDeep from 'lodash.clonedeep';
|
|
4
|
+
import MPbProducts from './MPbProducts';
|
|
5
|
+
import productsStore from '../../../stores/modules/productsStore';
|
|
6
|
+
import metaDataStore from '../../../stores/modules/metaDataStore';
|
|
7
|
+
import DEFAULT_PAYLOAD from './default-payload.json';
|
|
8
|
+
|
|
9
|
+
<Meta
|
|
10
|
+
title="Project Booster/Rework/Products/MPbProducts 🦠"
|
|
11
|
+
component={MPbProducts}
|
|
12
|
+
decorators={[
|
|
13
|
+
nestedAppDecorator(
|
|
14
|
+
{
|
|
15
|
+
modules: {
|
|
16
|
+
products: productsStore,
|
|
17
|
+
metaData: metaDataStore,
|
|
18
|
+
},
|
|
19
|
+
mutations: {},
|
|
20
|
+
actions: {},
|
|
21
|
+
},
|
|
22
|
+
[],
|
|
23
|
+
),
|
|
24
|
+
]}
|
|
25
|
+
parameters={{ layout: 'fullscreen' }}
|
|
26
|
+
/>
|
|
27
|
+
|
|
28
|
+
# `MPbProducts` - Component
|
|
29
|
+
|
|
30
|
+
export const TemplateSandbox = (args, { argTypes }) => ({
|
|
31
|
+
props: Object.keys(argTypes),
|
|
32
|
+
components: { MPbProducts },
|
|
33
|
+
setup() {
|
|
34
|
+
return { args };
|
|
35
|
+
},
|
|
36
|
+
template: `<m-pb-products
|
|
37
|
+
:payload="args.payload"
|
|
38
|
+
:show-back-button="args.showBackButton"
|
|
39
|
+
:completed-event-name="args.completedEventName"
|
|
40
|
+
@step-completed="args.onStepCompleted"
|
|
41
|
+
/>`,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
<Canvas>
|
|
45
|
+
<Story name="101 Sandbox" args={{ payload: DEFAULT_PAYLOAD }}>
|
|
46
|
+
{TemplateSandbox.bind({})}
|
|
47
|
+
</Story>
|
|
48
|
+
</Canvas>
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="pb-products">
|
|
3
|
+
<div class="pb-products__back-button-container">
|
|
4
|
+
<m-link
|
|
5
|
+
icon="ArrowArrowLeft48"
|
|
6
|
+
:class="{
|
|
7
|
+
'pb-products__back-button': true,
|
|
8
|
+
}"
|
|
9
|
+
@click.once="emit('go-back')"
|
|
10
|
+
>
|
|
11
|
+
{{ payload.viewModel.backLabel }}
|
|
12
|
+
</m-link>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<div class="pb-products__body row-flex column" v-if="product">
|
|
16
|
+
<div class="pb-products__title">
|
|
17
|
+
{{ payload.viewModel.label }}
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<div class="pb-products__body__item" v-if="product">
|
|
21
|
+
<div class="pb-products__body__item__thumbnail">
|
|
22
|
+
<img :src="product.photo" alt="" />
|
|
23
|
+
</div>
|
|
24
|
+
<div class="pb-products__body__item__title">{{ product.designation }}</div>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<div class="pb-products__container--button">
|
|
28
|
+
<m-button
|
|
29
|
+
:theme="action.bordered ? 'bordered' : 'solid'"
|
|
30
|
+
class="pb-products__container--button__ok"
|
|
31
|
+
:type="action.type"
|
|
32
|
+
:label="action.label"
|
|
33
|
+
icon-position="right"
|
|
34
|
+
size="m"
|
|
35
|
+
:href="action.href"
|
|
36
|
+
v-for="action in payload.callToActions"
|
|
37
|
+
:key="action.label"
|
|
38
|
+
@click="callAction(action.action)"
|
|
39
|
+
/>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
</template>
|
|
44
|
+
|
|
45
|
+
<script lang="ts" setup>
|
|
46
|
+
import { useStore } from 'vuex';
|
|
47
|
+
import { MButton, MLink } from '@mozaic-ds/vue-3';
|
|
48
|
+
import { ScenarioStepAnswer } from '@/types/pb/Scenario';
|
|
49
|
+
import { defineProps, PropType, onMounted, ref } from 'vue';
|
|
50
|
+
import { PayloadAction } from '../types/genericPayload';
|
|
51
|
+
|
|
52
|
+
const emit = defineEmits(['go-back', 'step-completed']);
|
|
53
|
+
|
|
54
|
+
const store = useStore();
|
|
55
|
+
const metadata = store.getters['metaData/metaData'];
|
|
56
|
+
const refProduct = store.getters['products/getRefProduct'];
|
|
57
|
+
const product = ref({});
|
|
58
|
+
|
|
59
|
+
const props = defineProps({
|
|
60
|
+
/**
|
|
61
|
+
* The component view model and business data as an object. The provided prop
|
|
62
|
+
* is merged with the default payload value so only overriden values will change
|
|
63
|
+
* from the default ones.
|
|
64
|
+
*/
|
|
65
|
+
payload: {
|
|
66
|
+
type: Object,
|
|
67
|
+
default: () => ({}),
|
|
68
|
+
},
|
|
69
|
+
/**
|
|
70
|
+
* The options provided at runtime to customize component behaviour
|
|
71
|
+
*/
|
|
72
|
+
runtimeOptions: {
|
|
73
|
+
type: Object,
|
|
74
|
+
default: () => ({}),
|
|
75
|
+
},
|
|
76
|
+
/**
|
|
77
|
+
* Indicates whether the back button should be displayed
|
|
78
|
+
*/
|
|
79
|
+
showBackButton: {
|
|
80
|
+
type: Boolean,
|
|
81
|
+
default: true,
|
|
82
|
+
},
|
|
83
|
+
/**
|
|
84
|
+
* Name for the event to send when the step is questio is answered
|
|
85
|
+
*/
|
|
86
|
+
completedEventName: {
|
|
87
|
+
type: String,
|
|
88
|
+
default: 'step-completed',
|
|
89
|
+
},
|
|
90
|
+
/**
|
|
91
|
+
* The previous answers to inject
|
|
92
|
+
*/
|
|
93
|
+
answers: {
|
|
94
|
+
type: Object as PropType<Map<string, ScenarioStepAnswer[]>>,
|
|
95
|
+
default: () => new Map<string, ScenarioStepAnswer[]>(),
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* onMounted load product and load this
|
|
101
|
+
*/
|
|
102
|
+
onMounted(() => {
|
|
103
|
+
store.dispatch('products/loadProduct', {
|
|
104
|
+
payload: props.payload.viewModel.defaultProduct,
|
|
105
|
+
storeId: metadata && metadata.storeId ? metadata.storeId : '',
|
|
106
|
+
});
|
|
107
|
+
product.value = store.getters['products/getCurrentProduct'];
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Send action to completed step
|
|
112
|
+
* @param action
|
|
113
|
+
*/
|
|
114
|
+
const callAction = (action: PayloadAction) => {
|
|
115
|
+
if (action.type === 'STEP') {
|
|
116
|
+
if (action.code === '__BACK__') {
|
|
117
|
+
emit('go-back');
|
|
118
|
+
} else {
|
|
119
|
+
let productToSend = null;
|
|
120
|
+
|
|
121
|
+
if (refProduct) {
|
|
122
|
+
productToSend = product;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
emit('step-completed', {
|
|
126
|
+
answers: [
|
|
127
|
+
{
|
|
128
|
+
product: productToSend,
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
nextStep: action,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
</script>
|
|
137
|
+
|
|
138
|
+
<style lang="scss" scoped>
|
|
139
|
+
@import 'pb-variables';
|
|
140
|
+
@import 'settings-tools/all-settings';
|
|
141
|
+
@import 'typography/_t.bodys';
|
|
142
|
+
@import '../styles/global.scss';
|
|
143
|
+
|
|
144
|
+
$small-responsive-breakpoint: 's-large';
|
|
145
|
+
$responsive-breakpoint: 'm';
|
|
146
|
+
|
|
147
|
+
.pb-products {
|
|
148
|
+
@include set-font-face('regular');
|
|
149
|
+
|
|
150
|
+
flex-grow: 1;
|
|
151
|
+
margin: 0 auto;
|
|
152
|
+
padding: 0 $mu100;
|
|
153
|
+
width: calc(100% - #{$mu100} - #{$mu100});
|
|
154
|
+
|
|
155
|
+
@include set-from-screen($responsive-breakpoint) {
|
|
156
|
+
width: calc(100% - #{$mu200} - #{$mu200});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
&__back-button-container {
|
|
160
|
+
align-self: flex-start;
|
|
161
|
+
}
|
|
162
|
+
&__back-button {
|
|
163
|
+
opacity: 1;
|
|
164
|
+
padding: $mu100 0 $mu100 $mu025;
|
|
165
|
+
transition: opacity 0.15s 0.5s;
|
|
166
|
+
&--hidden {
|
|
167
|
+
opacity: 0;
|
|
168
|
+
pointer-events: none;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
&__title {
|
|
173
|
+
@include set-font-face('semi-bold');
|
|
174
|
+
@include set-font-scale('08', 'm');
|
|
175
|
+
|
|
176
|
+
color: $color-grey-999;
|
|
177
|
+
max-width: 100%;
|
|
178
|
+
padding: 0;
|
|
179
|
+
text-align: left;
|
|
180
|
+
margin-top: $mu150;
|
|
181
|
+
|
|
182
|
+
&::after {
|
|
183
|
+
display: block;
|
|
184
|
+
width: 72px;
|
|
185
|
+
height: 4px;
|
|
186
|
+
content: '';
|
|
187
|
+
margin: $mu100 0 $mu150 0;
|
|
188
|
+
background: $color-primary-01-500;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
@include set-from-screen($responsive-breakpoint) {
|
|
192
|
+
@include set-font-scale('08', 'm');
|
|
193
|
+
|
|
194
|
+
width: auto;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
&__body {
|
|
199
|
+
margin: auto;
|
|
200
|
+
|
|
201
|
+
@include set-from-screen($responsive-breakpoint) {
|
|
202
|
+
width: 591px;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
&__item {
|
|
206
|
+
&__thumbnail {
|
|
207
|
+
margin-bottom: $mu150;
|
|
208
|
+
|
|
209
|
+
img {
|
|
210
|
+
width: 230px;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
&__title {
|
|
215
|
+
@include set-font-face('semi-bold');
|
|
216
|
+
@include set-font-scale('07', 's');
|
|
217
|
+
|
|
218
|
+
color: $color-grey-800;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
&__container--button {
|
|
224
|
+
margin-top: $mu100;
|
|
225
|
+
|
|
226
|
+
&__ok {
|
|
227
|
+
margin-bottom: $mu100;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
</style>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"viewModel": {
|
|
3
|
+
"backLabel": "Question précédente",
|
|
4
|
+
"label": "Estimer vos aides pour votre projet",
|
|
5
|
+
"defaultProduct": {
|
|
6
|
+
"designation": "Installation d'une chaudière à",
|
|
7
|
+
"photo": "https://storage.googleapis.com/project-booster-media/energyrenovation/default_heat_pump.jpg"
|
|
8
|
+
}
|
|
9
|
+
},
|
|
10
|
+
"callToActions": [
|
|
11
|
+
{
|
|
12
|
+
"type": "button",
|
|
13
|
+
"label": "Commencer la simulation",
|
|
14
|
+
"action": {
|
|
15
|
+
"type": "STEP",
|
|
16
|
+
"code": "__END__"
|
|
17
|
+
},
|
|
18
|
+
"bordered": false
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
File without changes
|
|
@@ -107,6 +107,7 @@ import PbCitySearch from '../question/city-search/PbCitySearch.vue';
|
|
|
107
107
|
import PbWarningMessage from '../warning-message/PbWarningMessage.vue';
|
|
108
108
|
import PbProducts from '../products/PbProducts.vue';
|
|
109
109
|
import PbTrezor from '../trezor/PbTrezor.vue';
|
|
110
|
+
import MPbProductsVue from '../rework/products/MPbProducts.vue';
|
|
110
111
|
import PbIncrementalAmountInput from '../question/incremental-amount-input/PbIncrementalAmountInput.vue';
|
|
111
112
|
import { areConditionsValid } from '../../services/scenarioConditionals';
|
|
112
113
|
import {
|
|
@@ -148,6 +149,7 @@ export default defineComponent({
|
|
|
148
149
|
PbIncrementalAmountInput,
|
|
149
150
|
PbProducts,
|
|
150
151
|
PbTrezor,
|
|
152
|
+
MPbProductsVue,
|
|
151
153
|
},
|
|
152
154
|
|
|
153
155
|
props: {
|