@configuratorware/configurator-frontendgui 1.30.1 → 1.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/App/Modules/Designer/Components/ImageColorPicker/ImageColorPicker.js +1 -2
  2. package/App/Modules/Designer/Utils/Transformers.js +1 -1
  3. package/App/Reducers/Configurator/Actions.js +20 -81
  4. package/App/Screens/Configurator/ThemeProvider.js +1 -1
  5. package/App/{Screens/Configurator/Containers/DesignApproval.js → Shared/Components/AcceptPrivacy/index.js} +78 -71
  6. package/App/Shared/Components/AddToBasket/index.js +1 -1
  7. package/App/Shared/Components/AmountPrice/index.js +83 -49
  8. package/App/Shared/Components/PriceOverview/index.js +5 -3
  9. package/App/Shared/Components/ReceiveOfferForm/index.js +9 -10
  10. package/App/configuration.js +1 -1
  11. package/package.json +4 -4
  12. package/public/translations/de_DE.json +4 -1
  13. package/public/translations/en_GB.json +4 -1
  14. package/src/App/Modules/Designer/Components/ImageColorPicker/ImageColorPicker.js +1 -3
  15. package/src/App/Modules/Designer/Utils/Transformers.js +1 -1
  16. package/src/App/Reducers/Configurator/Actions.js +6 -37
  17. package/src/App/Screens/Configurator/ThemeProvider.js +2 -2
  18. package/src/App/Shared/Components/AcceptPrivacy/index.js +78 -0
  19. package/src/App/Shared/Components/AddToBasket/index.js +1 -1
  20. package/src/App/Shared/Components/AmountPrice/index.js +48 -3
  21. package/src/App/Shared/Components/PriceOverview/index.js +3 -0
  22. package/src/App/Shared/Components/ReceiveOfferForm/__snapshots__/index.test.jsx.snap +64 -64
  23. package/src/App/Shared/Components/ReceiveOfferForm/index.js +9 -10
  24. package/src/App/configuration.js +1 -1
  25. package/App/Screens/Configurator/Components/DesignApproval/index.js +0 -76
  26. package/App/Screens/Configurator/Components/DesignApproval/index.story.js +0 -27
  27. package/App/Screens/Configurator/Components/DesignApproval/index.test.js +0 -31
  28. package/src/App/Screens/Configurator/Components/DesignApproval/__snapshots__/index.test.jsx.snap +0 -91
  29. package/src/App/Screens/Configurator/Components/DesignApproval/index.js +0 -54
  30. package/src/App/Screens/Configurator/Components/DesignApproval/index.story.js +0 -12
  31. package/src/App/Screens/Configurator/Components/DesignApproval/index.test.jsx +0 -17
  32. package/src/App/Screens/Configurator/Containers/DesignApproval.js +0 -76
@@ -97,7 +97,8 @@ var PriceOverview = /*#__PURE__*/function (_React$Component) {
97
97
  receiveOfferFormComponent = _this$props.receiveOfferFormComponent,
98
98
  showReceiveOfferForm = _this$props.showReceiveOfferForm,
99
99
  amount = _this$props.amount,
100
- acceptDesignComponent = _this$props.acceptDesignComponent;
100
+ acceptDesignComponent = _this$props.acceptDesignComponent,
101
+ acceptDataPrivacyComponent = _this$props.acceptDataPrivacyComponent;
101
102
  return /*#__PURE__*/_react["default"].createElement(_Grid["default"], {
102
103
  item: true,
103
104
  xs: 12,
@@ -124,7 +125,7 @@ var PriceOverview = /*#__PURE__*/function (_React$Component) {
124
125
  }, /*#__PURE__*/_react["default"].createElement("b", null, contactData)), receiveOfferFormComponent), /*#__PURE__*/_react["default"].createElement(_Grid["default"], {
125
126
  item: true,
126
127
  xs: 12
127
- }, acceptDesignComponent, amount > 0 && /*#__PURE__*/_react["default"].createElement(_Divider["default"], null), priceListComponent), /*#__PURE__*/_react["default"].createElement(_Grid["default"], {
128
+ }, acceptDesignComponent, acceptDataPrivacyComponent, amount > 0 && /*#__PURE__*/_react["default"].createElement(_Divider["default"], null), priceListComponent), /*#__PURE__*/_react["default"].createElement(_Grid["default"], {
128
129
  item: true,
129
130
  xs: 12
130
131
  }, addToCartComponent && /*#__PURE__*/_react["default"].createElement(_Divider["default"], null), addToCartComponent)), !showReceiveOfferForm && /*#__PURE__*/_react["default"].createElement(_Grid["default"], {
@@ -167,7 +168,8 @@ _defineProperty(PriceOverview, "propTypes", {
167
168
  receiveOfferFormComponent: _propTypes["default"].element,
168
169
  showReceiveOfferForm: _propTypes["default"].bool,
169
170
  amount: _propTypes["default"].number,
170
- acceptDesignComponent: _propTypes["default"].element
171
+ acceptDesignComponent: _propTypes["default"].element,
172
+ acceptDataPrivacyComponent: _propTypes["default"].element
171
173
  });
172
174
 
173
175
  var _default = (0, _styles.withStyles)(styles, {
@@ -58,7 +58,7 @@ var styles = function styles(theme) {
58
58
  marginTop: 0
59
59
  },
60
60
  outlinedInput: _defineProperty({
61
- padding: 14,
61
+ padding: 10,
62
62
  fontSize: 15
63
63
  }, theme.breakpoints.down('xs'), {
64
64
  padding: 19
@@ -143,7 +143,6 @@ var ReceiveOfferForm = /*#__PURE__*/function (_React$Component) {
143
143
  _this.handleChange = _this.handleChange.bind(_assertThisInitialized(_this));
144
144
  _this.handleBlur = _this.handleBlur.bind(_assertThisInitialized(_this));
145
145
  _this.setInputRef = _this.setInputRef.bind(_assertThisInitialized(_this));
146
- _this.designApprovalRef = /*#__PURE__*/_react["default"].createRef();
147
146
  return _this;
148
147
  }
149
148
 
@@ -231,7 +230,7 @@ var ReceiveOfferForm = /*#__PURE__*/function (_React$Component) {
231
230
  onChange: this.handleChange,
232
231
  onBlur: this.handleBlur,
233
232
  label: (0, _i18n.t)('receiveOfferForm.email'),
234
- margin: "normal",
233
+ margin: "dense",
235
234
  variant: "outlined",
236
235
  fullWidth: true,
237
236
  error: !!email.error,
@@ -256,7 +255,7 @@ var ReceiveOfferForm = /*#__PURE__*/function (_React$Component) {
256
255
  onChange: this.handleChange,
257
256
  onBlur: this.handleBlur,
258
257
  label: (0, _i18n.t)('receiveOfferForm.name'),
259
- margin: "normal",
258
+ margin: "dense",
260
259
  variant: "outlined",
261
260
  fullWidth: true,
262
261
  error: !!name.error,
@@ -278,7 +277,7 @@ var ReceiveOfferForm = /*#__PURE__*/function (_React$Component) {
278
277
  onChange: this.handleChange,
279
278
  onBlur: this.handleBlur,
280
279
  label: (0, _i18n.t)('receiveOfferForm.company'),
281
- margin: "normal",
280
+ margin: "dense",
282
281
  variant: "outlined",
283
282
  fullWidth: true,
284
283
  error: !!company.error,
@@ -300,7 +299,7 @@ var ReceiveOfferForm = /*#__PURE__*/function (_React$Component) {
300
299
  onChange: this.handleChange,
301
300
  onBlur: this.handleBlur,
302
301
  label: (0, _i18n.t)('receiveOfferForm.phonenumber'),
303
- margin: "normal",
302
+ margin: "dense",
304
303
  variant: "outlined",
305
304
  fullWidth: true,
306
305
  error: !!phonenumber.error,
@@ -329,7 +328,7 @@ var ReceiveOfferForm = /*#__PURE__*/function (_React$Component) {
329
328
  onChange: this.handleChange,
330
329
  onBlur: this.handleBlur,
331
330
  label: (0, _i18n.t)('receiveOfferForm.zip'),
332
- margin: "normal",
331
+ margin: "dense",
333
332
  variant: "outlined",
334
333
  fullWidth: true,
335
334
  error: !!zip.error,
@@ -355,7 +354,7 @@ var ReceiveOfferForm = /*#__PURE__*/function (_React$Component) {
355
354
  onChange: this.handleChange,
356
355
  onBlur: this.handleBlur,
357
356
  label: (0, _i18n.t)('receiveOfferForm.city'),
358
- margin: "normal",
357
+ margin: "dense",
359
358
  variant: "outlined",
360
359
  fullWidth: true,
361
360
  error: !!city.error,
@@ -377,7 +376,7 @@ var ReceiveOfferForm = /*#__PURE__*/function (_React$Component) {
377
376
  onChange: this.handleChange,
378
377
  onBlur: this.handleBlur,
379
378
  label: (0, _i18n.t)('receiveOfferForm.street'),
380
- margin: "normal",
379
+ margin: "dense",
381
380
  variant: "outlined",
382
381
  fullWidth: true,
383
382
  error: !!street.error,
@@ -399,7 +398,7 @@ var ReceiveOfferForm = /*#__PURE__*/function (_React$Component) {
399
398
  onChange: this.handleChange,
400
399
  onBlur: this.handleBlur,
401
400
  label: (0, _i18n.t)('receiveOfferForm.country'),
402
- margin: "normal",
401
+ margin: "dense",
403
402
  variant: "outlined",
404
403
  fullWidth: true,
405
404
  error: !!country.error,
@@ -31,7 +31,7 @@ var DEVELOPMENT_HOST_INT = 'http://int.configuratorware.local'; // eslint-disabl
31
31
  var DEVELOPMENT_HOST_LOCAL = 'http://localhost:10030';
32
32
  var hostsByNodeEnv = {
33
33
  production: '',
34
- development: DEVELOPMENT_HOST_LOCAL,
34
+ development: DEVELOPMENT_HOST_INT,
35
35
  test: ''
36
36
  };
37
37
  var resourceUrlsByNodeEnv = {
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@configuratorware/configurator-frontendgui",
3
- "version": "1.30.1",
3
+ "version": "1.31.0",
4
4
  "license": "UNLICENSED",
5
5
  "private": false,
6
6
  "main": "./index.js",
7
7
  "dependencies": {
8
8
  "@babel/polyfill": "^7.12.1",
9
- "@configuratorware/scripts": "1.30.1",
9
+ "@configuratorware/scripts": "1.31.0",
10
10
  "@hot-loader/react-dom": "^17.0.1",
11
11
  "@material-ui/core": "^4.12.2",
12
12
  "@material-ui/icons": "^4.11.2",
@@ -39,8 +39,8 @@
39
39
  "react-router-dom": "^5.2.0",
40
40
  "react-swipeable": "^5.5.1",
41
41
  "react-zoom-pan-pinch": "^2.1.3",
42
- "redhotmagma-graphics-editor": "1.30.1",
43
- "redhotmagma-visualization": "1.30.1",
42
+ "redhotmagma-graphics-editor": "1.31.0",
43
+ "redhotmagma-visualization": "1.31.0",
44
44
  "redux": "^4.1.0",
45
45
  "redux-logger": "^3.0.6",
46
46
  "redux-persist": "^5.10.0",
@@ -158,7 +158,10 @@
158
158
  "checkInputsInForm": "Bitte Eingaben im Formular prüfen",
159
159
  "sentOk": "Anfrage wurde erfolgreich versandt.",
160
160
  "sentError": "Fehler beim Senden der Anfrage.",
161
- "sendButton": "Angebot anfordern"
161
+ "sendButton": "Angebot anfordern",
162
+ "privacyNotice": "Ich willige darin ein, dass die von mir überreichten Informationen und Kontaktdaten dazu verwendet werden, um mit mir anlässlich meiner Kontaktaufnahme in Verbindung zu treten, hierüber zu kommunizieren und meine Anfrage abzuwickeln. Dies gilt insbesondere für die Verwendung der E-Mail-Adresse zum vorgenannten Zweck. Die Einwilligung kann jederzeit mit Wirkung für die Zukunft per E-Mail widerrufen werden. Die Datenschutzerklärung kann %{privacyLink} eingesehen werden.",
163
+ "privacyLinkLabel": "hier",
164
+ "selectionError": "Checkbox nicht bestätigt"
162
165
  },
163
166
  "acceptDesignScreen": {
164
167
  "selectionError": "Checkbox nicht bestätigt",
@@ -159,7 +159,10 @@
159
159
  "checkInputsInForm": "Please check the form inputs below",
160
160
  "sentOk": "Request was successfully sent.",
161
161
  "sentError": "Error sending the request.",
162
- "sendButton": "Request a quote"
162
+ "sendButton": "Request a quote",
163
+ "privacyNotice": "I consent to the information and contact details I have provided being used to contact me, to communicate about and to process my request. This applies in particular to the use of the e-mail address for the aforementioned purpose. The consent can be revoked at any time with effect for the future by e-mail. The privacy policy can be viewed %{privacyLink}.",
164
+ "privacyLinkLabel": "here",
165
+ "selectionError": "No consent given"
163
166
  },
164
167
  "acceptDesignScreen": {
165
168
  "checkedSelectionActive": "I have checked all provided data and the design and I approve the configuration",
@@ -210,9 +210,7 @@ export class ImageColorPicker extends React.Component {
210
210
  const { width: pw, height: ph } = container.getBoundingClientRect();
211
211
  const { width: ow, height: oh } = img;
212
212
 
213
- const oa = ow / oh;
214
-
215
- if (oa <= 1) {
213
+ if (ow / oh <= pw / ph) {
216
214
  const height = ph;
217
215
  const width = height * (ow / oh);
218
216
 
@@ -20,7 +20,7 @@ export const fixSrcURL = src => {
20
20
  export const getRasterURL = imageURL => ('' + imageURL).replace(/svg$/, 'png');
21
21
 
22
22
  export const isOriginalVector = imageData =>
23
- /^(eps|ept|pdf|ai|svg)$/i.test(get(imageData, 'original.format', ''));
23
+ /^(eps|ept|ps|pdf|ai|svg)$/i.test(get(imageData, 'original.format', ''));
24
24
 
25
25
  export const noCache = src => `${src}?${Math.random()}`;
26
26
 
@@ -480,14 +480,14 @@ export const fetchOptions = (itemidentifier, optionclassification, configuration
480
480
  );
481
481
  };
482
482
 
483
- export const switchOptionsBasic = (configuration, switchedoptions, noCheck = false) => {
483
+ export const switchOptionsBasic = (configuration, switchedOptions, noCheck = false) => {
484
484
  const config = {};
485
485
  if (noCheck) {
486
486
  config.params = { nocheck: 1 };
487
487
  }
488
488
  return apiActions.postData(
489
489
  'configuration/switchoption',
490
- { configuration, switchedoptions },
490
+ { configuration, switchedOptions },
491
491
  data => ({
492
492
  // dummy receiver
493
493
  type: 'RECEIVE_SWITCHOPTIONSRESULT_BASIC',
@@ -497,37 +497,6 @@ export const switchOptionsBasic = (configuration, switchedoptions, noCheck = fal
497
497
  );
498
498
  };
499
499
 
500
- export const switchOptionArrays = (configuration, switchOptionData, noCheck = false) => dispatch => {
501
- const switchedoptions = {};
502
- const afterSwitch = [];
503
-
504
- for (const componentIdentifier in switchOptionData) {
505
- if (isArray(switchOptionData[componentIdentifier])) {
506
- const [firstOption, ...otherOptions] = switchOptionData[componentIdentifier];
507
-
508
- switchedoptions[componentIdentifier] = firstOption;
509
-
510
- if (otherOptions.length > 0) {
511
- for (let optionData of otherOptions) {
512
- afterSwitch.push({
513
- [componentIdentifier]: optionData,
514
- });
515
- }
516
- }
517
- } else {
518
- switchedoptions[componentIdentifier] = switchOptionData[componentIdentifier];
519
- }
520
- }
521
-
522
- let p = dispatch(switchOptionsBasic(configuration, switchedoptions, noCheck));
523
- for (let switchOption of afterSwitch) {
524
- p = p.then(action => {
525
- return dispatch(switchOptionsBasic(action.data, switchOption, noCheck));
526
- });
527
- }
528
- return p;
529
- };
530
-
531
500
  export const switchOptions = (
532
501
  configuration,
533
502
  switchOptionData,
@@ -535,7 +504,7 @@ export const switchOptions = (
535
504
  refreshOptions = false,
536
505
  setChecked = false
537
506
  ) => dispatch => {
538
- return dispatch(switchOptionArrays(configuration, switchOptionData, noCheck)).then(action => {
507
+ return dispatch(switchOptionsBasic(configuration, switchOptionData, noCheck)).then(action => {
539
508
  const extraData = { switchOptionData, noCheck, refreshOptions, setChecked };
540
509
  return dispatch(receiveSwitchoptionsresult(action.data, extraData));
541
510
  });
@@ -701,10 +670,10 @@ export const resolveConflicts = () => (dispatch, getState) => {
701
670
  if (switchOptionsData) {
702
671
  if (p) {
703
672
  p = p.then(action => {
704
- return dispatch(switchOptionArrays(action.data, switchOptionsData, true));
673
+ return dispatch(switchOptionsBasic(action.data, switchOptionsData, true));
705
674
  });
706
675
  } else {
707
- p = dispatch(switchOptionArrays(configuration, switchOptionsData, true));
676
+ p = dispatch(switchOptionsBasic(configuration, switchOptionsData, true));
708
677
  }
709
678
  }
710
679
  }
@@ -781,7 +750,7 @@ export const selectMultipleOptions = optionsList => (dispatch, getState) => {
781
750
  for (const component of optionsList) {
782
751
  switchOptionData[component.identifier] = component.selectedoptions.map(({ identifier, amount }) => ({
783
752
  identifier,
784
- amount: amount || 1,
753
+ amount: typeof amount === 'undefined' ? 1 : amount,
785
754
  check_results: null,
786
755
  }));
787
756
  }
@@ -1,7 +1,7 @@
1
1
  import React, { useMemo } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { connect } from 'react-redux';
4
- import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles';
4
+ import { MuiThemeProvider, createTheme } from '@material-ui/core/styles';
5
5
  import { grey } from '@material-ui/core/colors';
6
6
  import merge from 'lodash/merge';
7
7
  import cloneDeep from 'lodash/cloneDeep';
@@ -245,7 +245,7 @@ const mapStateToProps = state => ({
245
245
 
246
246
  export const ThemeMixer = ({ client, customTheme, withTheme, children }) => {
247
247
  const themeMix = useMemo(() => {
248
- const theme = createMuiTheme(
248
+ const theme = createTheme(
249
249
  createThemeFromClientTheme(client && client.theme ? client.theme : {}, customTheme || {})
250
250
  );
251
251
  if (typeof withTheme === 'function') {
@@ -0,0 +1,78 @@
1
+ import React from 'react';
2
+ import { withStyles } from '@material-ui/core/styles';
3
+ import { t } from 'Framework/i18n';
4
+ import withWidth from '@material-ui/core/withWidth/withWidth';
5
+ import Grid from '@material-ui/core/Grid/Grid';
6
+ import FormControlLabel from '@material-ui/core/FormControlLabel';
7
+ import Checkbox from '@material-ui/core/Checkbox';
8
+ import FormHelperText from '@material-ui/core/FormHelperText';
9
+ import PropTypes from 'prop-types';
10
+
11
+ const styles = theme => ({
12
+ checkboxLabel: {
13
+ fontSize: 15,
14
+ paddingLeft: 15,
15
+ paddingBottom: 12,
16
+ [theme.breakpoints.down('xs')]: {
17
+ paddingLeft: 12,
18
+ },
19
+ },
20
+ checkbox: {
21
+ alignSelf: 'flex-start',
22
+ top: -10,
23
+ },
24
+ formHelperText: {
25
+ marginLeft: 45,
26
+ marginBottom: 15,
27
+ },
28
+ });
29
+
30
+ class AcceptPrivacy extends React.Component {
31
+ static propTypes = {
32
+ classes: PropTypes.object,
33
+ width: PropTypes.string,
34
+ handleChangeCheckboxApproval: PropTypes.func,
35
+ approval: PropTypes.object,
36
+ dataPrivacyLink: PropTypes.string,
37
+ };
38
+ render() {
39
+ const { classes, handleChangeCheckboxApproval, approval, dataPrivacyLink } = this.props;
40
+
41
+ const privacyLink = `<a href="${dataPrivacyLink}"
42
+ target="_blank">${t('receiveOfferForm.privacyLinkLabel')}</a>`;
43
+ const privacyNotice = t('receiveOfferForm.privacyNotice', { privacyLink });
44
+
45
+ return (
46
+ <Grid container>
47
+ <Grid item xs={12}>
48
+ <FormControlLabel
49
+ className={classes.checkboxLabel}
50
+ control={
51
+ <Checkbox
52
+ className={classes.checkbox}
53
+ name="dataPrivacyAccepted"
54
+ checked={approval.value}
55
+ onChange={handleChangeCheckboxApproval}
56
+ color="primary"
57
+ />
58
+ }
59
+ label={
60
+ <span
61
+ dangerouslySetInnerHTML={{
62
+ __html: privacyNotice,
63
+ }}
64
+ />
65
+ }
66
+ />
67
+ {approval.error && (
68
+ <FormHelperText error={true} className={classes.formHelperText}>
69
+ {t('receiveOfferForm.selectionError')}
70
+ </FormHelperText>
71
+ )}
72
+ </Grid>
73
+ </Grid>
74
+ );
75
+ }
76
+ }
77
+
78
+ export default withWidth()(withStyles(styles, { name: 'AcceptPrivacy' })(AcceptPrivacy));
@@ -35,7 +35,7 @@ const styles = theme => ({
35
35
  bottom: 90,
36
36
  fontSize: 15,
37
37
  right: 200,
38
- color: '#ED1C29',
38
+ color: theme.palette.primary.main,
39
39
  [theme.breakpoints.down('xs')]: {
40
40
  left: 15,
41
41
  whiteSpace: 'nowrap',
@@ -30,6 +30,7 @@ import ReceiveOfferForm from '../ReceiveOfferForm';
30
30
  import AcceptDesign from '../AcceptDesign';
31
31
  import LoadingOverlay from '../../../../Framework/Components/LoadingOverlay';
32
32
  import { debounce } from '@material-ui/core';
33
+ import AcceptPrivacy from '../AcceptPrivacy';
33
34
  const styles = theme => ({
34
35
  contentPositioning: {
35
36
  paddingLeft: 32,
@@ -280,6 +281,7 @@ class AmountPrice extends React.Component {
280
281
  AddToCartComponent: PropTypes.elementType,
281
282
  renderPriceBox: PropTypes.func,
282
283
  userComment: PropTypes.string,
284
+ AcceptPrivacyComponent: PropTypes.elementType,
283
285
  };
284
286
 
285
287
  static defaultProps = {
@@ -296,6 +298,7 @@ class AmountPrice extends React.Component {
296
298
  NotificationComponent: Notification,
297
299
  PriceListComponent: PriceList,
298
300
  AddToCartComponent: AddToCart,
301
+ AcceptPrivacyComponent: AcceptPrivacy,
299
302
  };
300
303
 
301
304
  state = {
@@ -309,6 +312,7 @@ class AmountPrice extends React.Component {
309
312
  },
310
313
  inView: true,
311
314
  showErrors: false,
315
+ dataPrivacyAccepted: false,
312
316
  };
313
317
 
314
318
  componentDidUpdate(prevProps, prevState) {
@@ -348,6 +352,7 @@ class AmountPrice extends React.Component {
348
352
  verifyRequestErrors = () => {
349
353
  const { bulkNameErrors, displayAcceptDesign } = this.props;
350
354
  const designApproved = this.state.approval.value;
355
+
351
356
  if (bulkNameErrors && bulkNameErrors.length > 0) {
352
357
  this.setState({ showErrors: true });
353
358
  this.setState({ bulkNameErrors });
@@ -361,12 +366,24 @@ class AmountPrice extends React.Component {
361
366
  },
362
367
  });
363
368
  }
369
+ if (!this.dataPrivacyApproved()) {
370
+ this.setState({
371
+ dataPrivacyAccepted: {
372
+ value: false,
373
+ error: true,
374
+ },
375
+ });
376
+ }
364
377
  };
365
378
 
366
379
  requestHasErrors = () => {
367
380
  const { bulkNameErrors, displayAcceptDesign } = this.props;
368
381
  const designApproved = this.state.approval.value;
369
- if ((bulkNameErrors && bulkNameErrors.length > 0) || (displayAcceptDesign && !designApproved)) {
382
+ if (
383
+ (bulkNameErrors && bulkNameErrors.length > 0) ||
384
+ (displayAcceptDesign && !designApproved) ||
385
+ !this.dataPrivacyApproved()
386
+ ) {
370
387
  return true;
371
388
  }
372
389
  return false;
@@ -381,6 +398,13 @@ class AmountPrice extends React.Component {
381
398
  }
382
399
  };
383
400
 
401
+ dataPrivacyApproved = () => {
402
+ const { showReceiveOfferForm, clientTexts } = this.props;
403
+ const { dataPrivacyLink } = clientTexts;
404
+ const dataPrivacyApproved = this.state.dataPrivacyAccepted.value;
405
+ return showReceiveOfferForm && dataPrivacyApproved && dataPrivacyLink;
406
+ };
407
+
384
408
  handleTouchMove = (evt => {
385
409
  const dialogContent = this.dialogContentRef.current;
386
410
  evt.preventDefault();
@@ -459,7 +483,15 @@ class AmountPrice extends React.Component {
459
483
  };
460
484
 
461
485
  renderPriceOverview() {
462
- const { notice, showPriceOverview, approval, inView, showErrors, bulkNameErrors } = this.state;
486
+ const {
487
+ notice,
488
+ showPriceOverview,
489
+ approval,
490
+ inView,
491
+ showErrors,
492
+ bulkNameErrors,
493
+ dataPrivacyAccepted,
494
+ } = this.state;
463
495
  const {
464
496
  amount,
465
497
  priceList,
@@ -484,9 +516,10 @@ class AmountPrice extends React.Component {
484
516
  NotificationComponent,
485
517
  PriceListComponent,
486
518
  AddToCartComponent,
519
+ AcceptPrivacyComponent,
487
520
  } = this.props;
488
521
 
489
- const { termsAndConditionsLink } = clientTexts;
522
+ const { termsAndConditionsLink, dataPrivacyLink } = clientTexts;
490
523
  const mergedNotifications = [...notifications] || [];
491
524
 
492
525
  if (showErrors && bulkNameErrors && bulkNameErrors.length > 0) {
@@ -553,6 +586,18 @@ class AmountPrice extends React.Component {
553
586
  />
554
587
  ) : null
555
588
  }
589
+ acceptDataPrivacyComponent={
590
+ showReceiveOfferForm && dataPrivacyLink ? (
591
+ <AcceptPrivacyComponent
592
+ dataPrivacyLink={dataPrivacyLink}
593
+ displayAcceptDesign={true}
594
+ handleChangeCheckboxApproval={this.handleChange}
595
+ approval={dataPrivacyAccepted}
596
+ closeProductOverviewDialog={this.handleClose}
597
+ displayNote={false}
598
+ />
599
+ ) : null
600
+ }
556
601
  notificationComponent={mergedNotifications.map(
557
602
  ({ message, level, color }, key) => {
558
603
  return (
@@ -48,6 +48,7 @@ class PriceOverview extends React.Component {
48
48
  showReceiveOfferForm: PropTypes.bool,
49
49
  amount: PropTypes.number,
50
50
  acceptDesignComponent: PropTypes.element,
51
+ acceptDataPrivacyComponent: PropTypes.element,
51
52
  };
52
53
  render() {
53
54
  const {
@@ -63,6 +64,7 @@ class PriceOverview extends React.Component {
63
64
  showReceiveOfferForm,
64
65
  amount,
65
66
  acceptDesignComponent,
67
+ acceptDataPrivacyComponent,
66
68
  } = this.props;
67
69
 
68
70
  return (
@@ -87,6 +89,7 @@ class PriceOverview extends React.Component {
87
89
  </Grid>
88
90
  <Grid item xs={12}>
89
91
  {acceptDesignComponent}
92
+ {acceptDataPrivacyComponent}
90
93
  {amount > 0 && <Divider />}
91
94
  {priceListComponent}
92
95
  </Grid>