@bytebrand/fe-ui-core 4.8.111 → 4.8.112

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 (198) hide show
  1. package/.husky/pre-push +4 -0
  2. package/.storybook/addons.js +4 -0
  3. package/.storybook/config.js +64 -0
  4. package/.storybook/postcss.config.js +6 -0
  5. package/.storybook/preview-head.html +10 -0
  6. package/.storybook/webpack.config.js +130 -0
  7. package/__tests__/components/Checkout/OrderOverviewItem/OrderOverviewItem.test.tsx +42 -0
  8. package/__tests__/components/Checkout/PaymentTypeCard/PaymentTypeCard.test.tsx +50 -0
  9. package/__tests__/components/Checkout/RadioGroup.test.tsx +95 -0
  10. package/__tests__/components/Checkout/ServiceCardWrapper.test.tsx +53 -0
  11. package/__tests__/components/Checkout/Switcher.test.tsx +43 -0
  12. package/__tests__/components/UserDasboardPage/sections/CheckoutSection/CheckoutSection.test.tsx +613 -0
  13. package/__tests__/components/UserDasboardPage/sections/FavoriteSection/FavoriteSection.test.tsx +335 -0
  14. package/__tests__/components/UserDasboardPage/sections/OrderStatusSection/AdditionalOrderInfo.test.tsx +127 -0
  15. package/__tests__/components/UserDasboardPage/sections/OrderStatusSection/OrderStatusCar.test.tsx +58 -0
  16. package/__tests__/components/UserDasboardPage/sections/OrderStatusSection/OrderStatusCard.test.tsx +74 -0
  17. package/__tests__/components/UserDasboardPage/sections/OrderStatusSection/OrderStatusSection.test.tsx +62 -0
  18. package/__tests__/components/UserDasboardPage/sections/RequestedCarsSection/RequestedCarsSection.test.tsx +117 -0
  19. package/__tests__/components/Vehicle/VehicleFormattedPrice/VehicleFormattedPrice.test.tsx +58 -0
  20. package/__tests__/components/VehicleSmallCard/VehicleInfo.test.tsx +88 -0
  21. package/__tests__/components/VehicleSmallCard/VehicleTitle.test.tsx +91 -0
  22. package/__tests__/components/_common/Badge/Badge.test.tsx +15 -0
  23. package/__tests__/components/_common/IconSVG/IconSVG.test.tsx +23 -0
  24. package/__tests__/components/_common/Image/Image.test.tsx +82 -0
  25. package/__tests__/components/_common/MaterialAutocomplete/MaterialAutocomplete.test.tsx +49 -0
  26. package/__tests__/components/_common/MaterialDatePicker/MaterialDatePicker.test.tsx +54 -0
  27. package/__tests__/components/_common/MaterialField/MaterialField.test.tsx +58 -0
  28. package/__tests__/components/_common/StarButton/StarButton.test.tsx +46 -0
  29. package/__tests__/mockedData/financingConfig.js +202 -0
  30. package/__tests__/mockedData/mockedPendingRequestedCar.js +69 -0
  31. package/__tests__/utils/CommonUtils/addPrefixToKeys.test.ts +18 -0
  32. package/__tests__/utils/CommonUtils/arrToObj.test.js +32 -0
  33. package/__tests__/utils/CommonUtils/checkRangeValuesOnEqual.test.ts +17 -0
  34. package/__tests__/utils/CommonUtils/fixNumber.test.ts +20 -0
  35. package/__tests__/utils/CommonUtils/formatMileage.test.ts +8 -0
  36. package/__tests__/utils/CommonUtils/getChipFilterValue.test.ts +22 -0
  37. package/__tests__/utils/CommonUtils/getFormattedNumber.test.ts +19 -0
  38. package/__tests__/utils/CommonUtils/getFormattedPrice.test.ts +19 -0
  39. package/__tests__/utils/CommonUtils/getGroupValuesForQuery.test.ts +51 -0
  40. package/__tests__/utils/CommonUtils/getOfferSliders.test.ts +64 -0
  41. package/__tests__/utils/CommonUtils/getPriceRating.test.ts +26 -0
  42. package/__tests__/utils/CommonUtils/getPriceRatingConfig.test.ts +33 -0
  43. package/__tests__/utils/CommonUtils/preloadNearbyImages.test.ts +9 -0
  44. package/__tests__/utils/CommonUtils/sliceLessThan.test.ts +23 -0
  45. package/__tests__/utils/CommonUtils/sliceMoreThan.test.ts +23 -0
  46. package/media/locales/de/promoSlider.json +1 -0
  47. package/media/locales/en/promoSlider.json +1 -0
  48. package/package.json +118 -120
  49. package/source/components/AccordionWidget/AccordionWidget.styl +13 -1
  50. package/source/components/AccordionWidget/AccordionWidget.tsx +49 -8
  51. package/source/components/AdvantageItem/AdvantageItem.story.js +23 -0
  52. package/source/components/Alternative/Dealer.story.js +32 -0
  53. package/source/components/Alternative/Dealer.story.styl +3 -0
  54. package/source/components/Breadcrumbs/Breadcrumbs.story.js +40 -0
  55. package/source/components/Breadcrumbs/FirstInfoBlock/FirstInfoBlock.story.js +45 -0
  56. package/source/components/Checkout/OrderOverviewItem/OrderOverviewItem.story.js +243 -0
  57. package/source/components/Checkout/OrderOverviewItem/OrderOverviewItem.story.styl +21 -0
  58. package/source/components/Checkout/RadioCards/RadioGroupCheckout.story.js +105 -0
  59. package/source/components/Checkout/RadioCards/RadioGroupCheckout.story.styl +37 -0
  60. package/source/components/Checkout/Switcher/Switcher.story.js +41 -0
  61. package/source/components/Checkout/Switcher/Switcher.story.styl +2 -0
  62. package/source/components/CompactSearchWidget/CompactSearchWidget.story.js +187 -0
  63. package/source/components/ContactForm/ContactForm.story.js +94 -0
  64. package/source/components/ContactForm/ContactForm.story.styl +0 -0
  65. package/source/components/ContactInfo/ContactInfo.story.js +58 -0
  66. package/source/components/CustomerQuote/CustomerQuote.story.js +41 -0
  67. package/source/components/CustomerQuotesSlider/CustomerQuotesSlider.story.js +73 -0
  68. package/source/components/CustomerQuotesSlider/CustomerQuotesSlider.story.styl +5 -0
  69. package/source/components/FormattedNumber/FormattedNumber.story.js +114 -0
  70. package/source/components/InfoBlocks/InfoBlockWrapper.story.js +101 -0
  71. package/source/components/InfoBlocks/InfoBlockWrapper.story.styl +46 -0
  72. package/source/components/OfferPanel/AboAccordion/AboFaq/AboFaq.story.js +97 -0
  73. package/source/components/OfferPanel/OfferCheckboxGroup/CheckboxContainer.tsx +2 -2
  74. package/source/components/OfferPanel/OfferCheckboxGroup/OfferCheckboxGroup.styl +24 -0
  75. package/source/components/OfferPanel/OfferCheckboxGroup/OfferCheckboxGroup.tsx +1 -2
  76. package/source/components/OfferPanel/OfferPanel.story.js +139 -0
  77. package/source/components/OfferPanel/OfferPanel.tsx +1 -1
  78. package/source/components/OfferPanel/RangeGroup/RangeGroup.story.js +35 -0
  79. package/source/components/OfferPanel/RangeGroup/RangeGroup.story.styl +3 -0
  80. package/source/components/PriceRating/PriceRating.story.js +39 -0
  81. package/source/components/PriceRating/PriceRating.story.styl +2 -0
  82. package/source/components/PriceRatingDetailed/PriceRatingDetailed.story.js +78 -0
  83. package/source/components/PriceRatingDetailed/PriceRatingDetailed.story.styl +11 -0
  84. package/source/components/RateSearchValue/RateSearchValue.story.js +78 -0
  85. package/source/components/RateSearchValue/RateSearchValue.story.styl +2 -0
  86. package/source/components/RateSearchWidget/RateSearchWidget.story.js +57 -0
  87. package/source/components/RateSearchWidget/RateSearchWidget.story.styl +12 -0
  88. package/source/components/SearchFilters/FiltersFactory.story.js +273 -0
  89. package/source/components/SearchPage/Filters/MakeModel/MakeModel.story.js +12 -0
  90. package/source/components/SearchWidget/BasicDataWidget/BasicDataWidget.story.js +834 -0
  91. package/source/components/SearchWidget/BasicDataWidget/BasicDataWidget.story.styl +40 -0
  92. package/source/components/SearchWidget/SearchWidget.story.js +191 -0
  93. package/source/components/SearchWidget/SearchWidget.story.styl +6 -0
  94. package/source/components/Stepper/Stepper.story.js +119 -0
  95. package/source/components/Stepper/Stepper.story.styl +41 -0
  96. package/source/components/Theme.story.js +36 -0
  97. package/source/components/Theme.story.styl +85 -0
  98. package/source/components/TickerText/TickerText.story.js +17 -0
  99. package/source/components/UserDashboardPage/sections/OrderStatusSection/OrderStatusSection.story.js +95 -0
  100. package/source/components/UserDashboardPage/sections/RequestedCarsSection/RequestedCarsSection.story.js +97 -0
  101. package/source/components/Vehicle/VehicleConsumption/VehicleConsumption.story.js +31 -0
  102. package/source/components/Vehicle/VehicleFormattedPrice/VehicleFormattedPrice.story.js +247 -0
  103. package/source/components/VehicleCompared/CompareGeneral/CompareGeneral.story.js +30 -0
  104. package/source/components/VehicleCompared/ComparePrice/ComparePrice.story.js +18 -0
  105. package/source/components/VehicleCompared/CompareTitle/CompareTitle.story.js +19 -0
  106. package/source/components/VehicleDetailedSidebar/VehicleDetailedSidebar.story.js +44 -0
  107. package/source/components/VehicleDetailedSidebar/VehicleDetailedSidebar.tsx +23 -11
  108. package/source/components/VehicleDetailedSidebar/partials/Properties.styl +5 -0
  109. package/source/components/VehicleDetailedSidebar/partials/Properties.tsx +56 -18
  110. package/source/components/VehicleDetailedSlider/VehicleDetailedSlider.story.js +120 -0
  111. package/source/components/VehicleDetailedSlider/VehicleDetailedSlider.tsx +2 -6
  112. package/source/components/VehiclePromoSlider/VehiclePromoInfo/VehiclePromoInfo.story.js +42 -0
  113. package/source/components/VehiclePromoSlider/VehiclePromoSlide/VehiclePromoSlide.story.js +62 -0
  114. package/source/components/VehiclePromoSlider/VehiclePromoSlider.story.js +42 -0
  115. package/source/components/VehicleSmallCard/VehicleData/VechiclePriceItem/VechiclePriceItem.styl +42 -0
  116. package/source/components/VehicleSmallCard/VehicleData/VechiclePriceItem/VechiclePriceItem.tsx +23 -11
  117. package/source/components/VehicleSmallCard/VehicleData/VehicleInfo/VehicleInfo.styl +60 -5
  118. package/source/components/VehicleSmallCard/VehicleData/VehicleInfo/VehicleInfo.tsx +36 -12
  119. package/source/components/VehicleSmallCard/VehicleData/VehiclePrice/VehiclePrice.styl +3 -2
  120. package/source/components/VehicleSmallCard/VehicleData/VehiclePrice/VehiclePrice.tsx +18 -7
  121. package/source/components/VehicleSmallCard/VehicleData/VehicleProperty/VehicleProperty.styl +4 -1
  122. package/source/components/VehicleSmallCard/VehicleData/VehicleProperty/VehicleProperty.tsx +3 -2
  123. package/source/components/VehicleSmallCard/VehicleData/VehicleTitle/VehicleTitle.tsx +1 -1
  124. package/source/components/VehicleSmallCard/VehicleSmallCard.story.js +412 -0
  125. package/source/components/VehicleSmallCard/VehicleSmallCard.story.styl +56 -0
  126. package/source/components/VehicleSmallCard/VehicleSmallCard.styl +67 -2
  127. package/source/components/VehicleSmallCard/VehicleSmallCard.tsx +49 -3
  128. package/source/components/VehicleSmallCardForDealerships/VehicleSmallCardForDealerships.story.js +199 -0
  129. package/source/components/VehicleSmallCardForDealerships/VehicleSmallCardForDealerships.story.styl +40 -0
  130. package/source/components/_common/Accordion/Accordion.story.js +36 -0
  131. package/source/components/_common/Badge/Badge.story.js +27 -0
  132. package/source/components/_common/Badge/Badge.story.styl +5 -0
  133. package/source/components/_common/Bubble/Bubble.story.js +52 -0
  134. package/source/components/_common/Button/Button.story.js +52 -0
  135. package/source/components/_common/Button/Button.story.styl +5 -0
  136. package/source/components/_common/ButtonOld/Button.story.js +54 -0
  137. package/source/components/_common/ButtonOld/Button.story.styl +5 -0
  138. package/source/components/_common/Checkbox/Checkbox.story.js +85 -0
  139. package/source/components/_common/Checkbox/Checkbox.story.styl +14 -0
  140. package/source/components/_common/CheckboxMaterial/CheckboxMaterial.story.js +126 -0
  141. package/source/components/_common/CheckboxMaterial/CheckboxMaterial.story.styl +14 -0
  142. package/source/components/_common/Chip/Chip.story.js +43 -0
  143. package/source/components/_common/ChipList/ChipList.story.js +36 -0
  144. package/source/components/_common/DropDown/DropDown.story.js +35 -0
  145. package/source/components/_common/ExpandablePanel/ExpandablePanel.story.js +41 -0
  146. package/source/components/_common/Histogram/Histogram.story.js +51 -0
  147. package/source/components/_common/IconSVG/IconSVG.story.js +21 -0
  148. package/source/components/_common/IconSVG/IconSVG.story.styl +25 -0
  149. package/source/components/_common/Image/Image.story.js +142 -0
  150. package/source/components/_common/Image/Image.story.styl +18 -0
  151. package/source/components/_common/ImagesSet/ImagesSet.story.js +34 -0
  152. package/source/components/_common/ImagesSet/ImagesSet.story.styl +4 -0
  153. package/source/components/_common/Loader/Loader.story.js +21 -0
  154. package/source/components/_common/MaterialAccordionGroup/MaterialAccordionGroup.story.js +49 -0
  155. package/source/components/_common/MaterialAccordionGroup/MaterialAccordionGroup.styled.tsx +4 -1
  156. package/source/components/_common/MaterialDatePicker/MaterialDatePicker.story.js +45 -0
  157. package/source/components/_common/MaterialDatePicker/MaterialDatePicker.story.styl +6 -0
  158. package/source/components/_common/MaterialField/MaterialField.story.js +87 -0
  159. package/source/components/_common/MaterialField/MaterialField.story.styl +34 -0
  160. package/source/components/_common/MaterialSelect/MaterialSelect.story.js +52 -0
  161. package/source/components/_common/MaterialSelect/MaterialSelect.story.styl +6 -0
  162. package/source/components/_common/MaterialStepButton/MaterialStepButton.story.js +47 -0
  163. package/source/components/_common/MaterialStepButton/MaterialStepButton.story.styl +6 -0
  164. package/source/components/_common/MaterialSwitch/MaterialSwitch.story.js +17 -0
  165. package/source/components/_common/MaterialTooltip/MaterialTooltip.story.js +10 -0
  166. package/source/components/_common/MaterialTooltip/MaterialTooltip.tsx +4 -3
  167. package/source/components/_common/Modal/Modal.story.js +37 -0
  168. package/source/components/_common/MuiGroupedSelect/MuiGroupedSelect.story.js +21 -0
  169. package/source/components/_common/PropertySelector/PSGroup.story.js +93 -0
  170. package/source/components/_common/PropertySelector/PSGroup.story.styl +25 -0
  171. package/source/components/_common/PropertySelector/ProperySelector.story.js +83 -0
  172. package/source/components/_common/Radio/FormRadioGroup.story.js +28 -0
  173. package/source/components/_common/Radio/FormRadioGroup.story.styl +2 -0
  174. package/source/components/_common/Radio/Radio.story.js +54 -0
  175. package/source/components/_common/Radio/RadioGroup.story.js +90 -0
  176. package/source/components/_common/Radio/RadioGroup.story.styl +39 -0
  177. package/source/components/_common/Range/Range.story.js +46 -0
  178. package/source/components/_common/Range/Range.story.styl +5 -0
  179. package/source/components/_common/SliderArrow/SliderArrow.story.js +18 -0
  180. package/source/components/_common/Tabs/Tabs.story.js +56 -0
  181. package/source/components/_common/TimePicker/TimePicker.story.js +37 -0
  182. package/source/components/_common/Tooltip/Tooltip.story.js +28 -0
  183. package/source/components/_common/UserMenu/MaterialMenu.story.js +73 -0
  184. package/source/components/_common/VehicleSlider/VehicleSlider.story.js +99 -0
  185. package/source/components/_common/VehicleSlider/VehicleSlider.story.styl +0 -0
  186. package/source/components/_common/withLabel/withLabel.story.js +62 -0
  187. package/source/components/_common/withPopover/withPopover.story.js +48 -0
  188. package/source/components/_common/withPopover/withPopover.story.styl +54 -0
  189. package/source/components/_common/withStats/withStats.story.js +75 -0
  190. package/source/components/_common/withStats/withStats.styl +10 -0
  191. package/source/framework/DataTransformers.ts +2 -0
  192. package/source/framework/constants/common.ts +8 -4
  193. package/source/framework/types/types.ts +1 -0
  194. package/source/framework/vehiclesProps/decoratedLightProps.tsx +109 -18
  195. package/source/framework/vehiclesProps/decoratedProps.tsx +68 -9
  196. package/source/framework/vehiclesProps/vehicleDetails.ts +3 -1
  197. package/source/locales/data.ts +13 -3
  198. package/bytebrand-fe-ui-core-4.8.110.tgz +0 -0
@@ -0,0 +1,120 @@
1
+ import React from 'react';
2
+ import i18next from 'i18next';
3
+ import { Resizable } from 're-resizable';
4
+ import { withNamespaces } from 'react-i18next';
5
+ import { storiesOf } from '@storybook/react';
6
+ import { action } from '@storybook/addon-actions';
7
+ import VehicleDetailedSlider from './VehicleDetailedSlider.tsx';
8
+
9
+ i18next.addResourceBundle('de', 'VehicleDetailsPage', {
10
+ "slider": {
11
+ "topPrices": "Top-Preise",
12
+ "comingSoon": "Demnächst",
13
+ "firstPicture": "Erstes Bild",
14
+ "currentSlide": "von",
15
+ "fullScreen": "Vollbild",
16
+ "exterior": "Außen",
17
+ "interior": "Innen",
18
+ "comparableCars": "Vergleichbare Autos",
19
+ "comparableCarsMobile": "Vergleichbare Autos",
20
+ "othersLooked": "Andere haben ebenso angeschaut",
21
+ "saveCarAsFavorites": "{{ count }} Favoriten",
22
+ "customersLookingTheCar": "{{ count}} Ansichten",
23
+ "checked": "geprüft",
24
+ "easy": "einfach",
25
+ "safe": "sicher",
26
+ "toBuy": "kaufen",
27
+ "callForFree": "kostenfrei anrufen",
28
+ "save": "sparen",
29
+ "new": "neu"
30
+ },
31
+ });
32
+
33
+ const wrapperProps = {
34
+ border: '1px solid rgba(0,0,0,0.1)',
35
+ borderRadius: '2px',
36
+ backgroundColor: '#fff'
37
+ };
38
+
39
+ const resizableProps = {
40
+ minWidth: 595,
41
+ defaultSize: { width: 724, height: 'auto' }
42
+ };
43
+
44
+ const IMAGE_URL = 'https://picsum.photos/400/300/?random';
45
+ const images = [];
46
+ for (let i = 0; i <= 10; i++) {
47
+ images.push({
48
+ imageUrlSmall: `${IMAGE_URL}&tag=${Math.random()}`,
49
+ imageUrlLarge: `${IMAGE_URL}&tag=${Math.random()}`
50
+ });
51
+ }
52
+
53
+
54
+ const VehicleDetailedSliderStory = () => {
55
+ const sliderProps = {
56
+ showModal: action('showModal(id: string, props?: any)'),
57
+ hideModal: action('hideModal(id: string)'),
58
+ price: {
59
+ monthlyInstallment: 29,
60
+ oldMonthlyInstallment: 49,
61
+ isStrikeShown: true,
62
+ currency: "EUR",
63
+ currentSalesPrice: 16160,
64
+ historyPriceDifference: 5629.6,
65
+ historyPriceDifferencePerCent: 26,
66
+ mlCurrentSalesPriceCategory: null,
67
+ mlCurrentSalesPriceDiffPercent: null,
68
+ mlCurrentSalesPricePredicted: 100,
69
+ totalCurrent: 50,
70
+ originalSalesPrice: 13467,
71
+ priceDate: null,
72
+ priceId: null,
73
+ recomendedRetailPrice: null,
74
+ retailToCurrentPriceDifference: 0,
75
+ vatDeductible: null,
76
+ vatRate: 7,
77
+ wasPrice: 10000,
78
+ leasing: {
79
+ monthlyInstallment: 49,
80
+ oldMonthlyInstallment: 69,
81
+ isActive: true
82
+ },
83
+ buy: {
84
+ currentSalesPriceExtra: 16110,
85
+ highestPriceExtra: 19349
86
+ }
87
+ },
88
+ modificationDate: 1535760000,
89
+ mainImageUrl: 'http://placehold.jp/400x300.png?text=mainImage',
90
+ mainImageBlur: true,
91
+ showNewLabel: true,
92
+ photos: images,
93
+ exteriorPhotos: 'http://placehold.jp/400x300.png?text=mainImage',
94
+ interiorPhoto: 'http://placehold.jp/400x300.png?text=mainImage',
95
+ statsData: {
96
+ totalCarImpCount: 10,
97
+ totalFavCount: 20,
98
+ },
99
+ make: 'Audi',
100
+ model: 'A4',
101
+ subModel: 'Shooting Brake',
102
+ powerKW: 35,
103
+ powerPS: 120,
104
+ isFavorite: false,
105
+ onCarFavorite: action('onCarFavorite(event, id)')
106
+ };
107
+
108
+ return (
109
+ <>
110
+ <p>Main image on CDP with MagnifyGlass</p>
111
+ <div style={wrapperProps}>
112
+ <Resizable {...resizableProps}>
113
+ <VehicleDetailedSlider {...sliderProps} />
114
+ </Resizable>
115
+ </div>
116
+ </>
117
+ );
118
+ };
119
+
120
+ storiesOf('VehicleDetailedSlider', module).add('VehicleDetailedSlider', () => <VehicleDetailedSliderStory />);
@@ -46,8 +46,6 @@ interface IProps {
46
46
  showDownPayment: boolean;
47
47
  financingFirstInstallment?: number | null;
48
48
  leasingFirstInstallment?: number | null;
49
- sliderFinancingFirstInstallment?: number | null;
50
- sliderLeasingFirstInstallment?: number | null;
51
49
  handleSentryInit?: () => void;
52
50
  }
53
51
 
@@ -314,12 +312,11 @@ class VehicleDetailedSlider extends Component<IProps, IState> {
314
312
  showDownPayment,
315
313
  financingFirstInstallment,
316
314
  leasingFirstInstallment,
317
- sliderFinancingFirstInstallment,
318
- sliderLeasingFirstInstallment,
319
315
  subModel,
320
316
  powerKW,
321
317
  powerPS,
322
318
  activeTab,
319
+ financingConfig,
323
320
  onCarFavorite
324
321
  } = this.props;
325
322
  const { activeSlide } = this.state;
@@ -341,12 +338,11 @@ class VehicleDetailedSlider extends Component<IProps, IState> {
341
338
 
342
339
  const priceProps = {
343
340
  t,
341
+ financingConfig,
344
342
  showNewLabel,
345
343
  showDownPayment,
346
344
  financingFirstInstallment,
347
345
  leasingFirstInstallment,
348
- sliderFinancingFirstInstallment,
349
- sliderLeasingFirstInstallment,
350
346
  historyPriceDifference: price ? price.historyPriceDifference : 0,
351
347
  historyPriceDifferencePerCent: price ? price.historyPriceDifferencePerCent : 0,
352
348
  activeTab
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ import { storiesOf } from '@storybook/react';
3
+ import { action } from '@storybook/addon-actions';
4
+
5
+ import VehiclePromoInfo from './VehiclePromoInfo';
6
+
7
+ // Stateful container for testing interaction
8
+ class VehiclePromoInfoContainer extends React.Component {
9
+ render() {
10
+ const { t } = this.props;
11
+
12
+ const props = {
13
+ t: key => key,
14
+ price: {
15
+ wasPrice: 18660,
16
+ currentSalesPrice: 18440,
17
+ historyPriceDifferencePerCent: 2,
18
+ purchasePrice: 0,
19
+ vatRate: 19
20
+ },
21
+ consumption: { consumptionCombined: 6.1 },
22
+ environmentEmissions: { co2: 159 },
23
+ monthlyInstallment: 269.8,
24
+ oldMonthlyInstallment: 259.8,
25
+ onButtonClick: action('offer button click'),
26
+ onFinancingDetailsClick: action('financing button click')
27
+ };
28
+
29
+ return (
30
+ <div style={{ marginTop: 100 }}>
31
+ <VehiclePromoInfo {...props} />
32
+ </div>
33
+ );
34
+ }
35
+ }
36
+
37
+ storiesOf('VehiclePromoInfo', module)
38
+ .add('Default', () => (
39
+ <div>
40
+ <VehiclePromoInfoContainer />
41
+ </div>
42
+ ));
@@ -0,0 +1,62 @@
1
+ import React from 'react';
2
+ import { storiesOf } from '@storybook/react';
3
+ import { action } from '@storybook/addon-actions';
4
+
5
+ import VehiclePromoSlide from './VehiclePromoSlide';
6
+
7
+ // Stateful container for testing interaction
8
+ class VehiclePromoSlideContainer extends React.Component {
9
+ render() {
10
+ const { t } = this.props;
11
+
12
+ const props = {
13
+ t: key => key,
14
+ _id: 'e18efa30-a4d2-48d7-b0d7-d1701731af2a',
15
+ title: 'BMW 114',
16
+ showNewLabel: true,
17
+ vehicleLink:
18
+ '',
19
+ src:
20
+ 'https://images.auto.de/carimage/858c5bae-12d2-4180-ad01-6576c2160dc0/WF-8oH7LX-iw/medium-transparent',
21
+ environmentEmissions:
22
+ { energyEfficiencyClass: 'energyEff',
23
+ co2: 115,
24
+ emissionClass: 'emissionClass',
25
+ emissionSticker: 'emissionSticker' },
26
+ consumption:
27
+ { consumptionUnit: 'unit',
28
+ fuel: 'petrol',
29
+ consumptionCombined: 4.9 },
30
+ price:
31
+ { currency: 'EUR',
32
+ wasPrice: 14789,
33
+ currentSalesPrice: 100000,
34
+ vatRate: 19,
35
+ recomendedRetailPrice: 120000,
36
+ retailToCurrentPriceDifference: -20000,
37
+ historyPriceDifferencePerCent: 17,
38
+ historyPriceDifference: 20000,
39
+ mlCurrentSalesPricePredicted: 98000,
40
+ mlCurrentSalesPriceDiffPercent: 2.0408163265306145 },
41
+ monthlyInstallment: 714.69,
42
+ oldMonthlyInstallment: 1082.29,
43
+ bubblesColor: '#fd5a1c',
44
+ bubbleContent: 'Super Angebot!',
45
+ onButtonClick: action('offer button click'),
46
+ onFinancingDetailsClick: action('financing button click')
47
+ };
48
+
49
+ return (
50
+ <div style={{ marginTop: 100 }}>
51
+ <VehiclePromoSlide {...props} />
52
+ </div>
53
+ );
54
+ }
55
+ }
56
+
57
+ storiesOf('VehiclePromoSlide', module)
58
+ .add('Default', () => (
59
+ <div>
60
+ <VehiclePromoSlideContainer />
61
+ </div>
62
+ ));
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ import { storiesOf } from '@storybook/react';
3
+ import { action } from '@storybook/addon-actions';
4
+
5
+ import cars from './cars'; // fake data from top api request
6
+
7
+ import VehiclePromoSlider from './VehiclePromoSlider';
8
+
9
+ const defaultSliderStateProps = {
10
+ t: key => key,
11
+ cars
12
+ };
13
+
14
+ const withHandlersSliderStateProps = {
15
+ t: key => key,
16
+ cars,
17
+ onButtonClick: action('offer button click'),
18
+ onFinancingDetailsClick: action('financing button click')
19
+ };
20
+
21
+ // Stateful container for testing interaction
22
+ class VehiclePromoSliderContainer extends React.Component {
23
+ render() {
24
+ return (
25
+ <div style={{ marginTop: 100 }}>
26
+ <VehiclePromoSlider {...this.props} />
27
+ </div>
28
+ );
29
+ }
30
+ }
31
+
32
+ storiesOf('VehiclePromoSlider', module)
33
+ .add('Default', () => (
34
+ <div style={{ width: '90vw', height: '75vh' }}>
35
+ <VehiclePromoSliderContainer {...defaultSliderStateProps} />
36
+ </div>
37
+ ))
38
+ .add('With Handlers', () => (
39
+ <div style={{ width: '90vw', height: '75vh' }}>
40
+ <VehiclePromoSliderContainer {...withHandlersSliderStateProps} />
41
+ </div>
42
+ ));
@@ -70,6 +70,11 @@
70
70
  +media-tablet-landscape-up()
71
71
  font-size: 9px;
72
72
 
73
+ &.priceItemCategoryLanding,
74
+ &.priceItemCategoryMain
75
+ +media-tablet-landscape-up()
76
+ font-size: 10px;
77
+
73
78
  & > span:hover
74
79
  background: rgba(196, 196, 196, 0.6);
75
80
 
@@ -122,6 +127,43 @@
122
127
  &.priceMtlActive
123
128
  transform: translateX(6px);
124
129
 
130
+ // ADV-70: monthly label rendered before the rate (small, top-left of the number).
131
+ .priceCurrentWrap
132
+ display: inline-flex
133
+ align-items: flex-start
134
+
135
+ .priceMtlPrefix
136
+ font-size: 10px
137
+ line-height: 1.2
138
+ margin-right: 3px
139
+ color: rgba(76, 78, 100, 0.6)
140
+ align-self: flex-start
141
+ white-space: nowrap
142
+
143
+ // ADV-88 (Marco): the monthly "mtl."/"mth." label sits INLINE to the LEFT of the rate (top-
144
+ // aligned), not stacked above. NOTE: on the narrowest 4-up landing/main card (~256px) the
145
+ // inline label can graze the card edge at full font; the wide comparable/CDP card fits with
146
+ // room. (Marco asked to keep the rate/category fonts untouched — only the label moved.)
147
+ .priceItemComparable
148
+ .priceCurrentWrap
149
+ flex-direction: row
150
+ align-items: flex-start
151
+ .priceMtlPrefix
152
+ font-size: 8px
153
+ line-height: 1
154
+ margin-right: 2px
155
+ align-self: flex-start
156
+
157
+ // landing (/angebot): on desktop the cards are a narrow 4-up grid where the inline label would
158
+ // overflow the price column — stack "mtl."/"mth." above the rate there (mobile stays inline above).
159
+ .priceItemLanding
160
+ +media-tablet-landscape-up()
161
+ .priceCurrentWrap
162
+ flex-direction: column
163
+ align-items: flex-end
164
+ .priceMtlPrefix
165
+ margin-right: 0
166
+
125
167
  .priceNewBlock
126
168
  flex-shrink: 0;
127
169
  width: 18px
@@ -39,7 +39,10 @@ export interface IVehiclePriceItemProps {
39
39
  isMarge?: boolean;
40
40
  }
41
41
  class VehiclePriceItem extends React.Component<IVehiclePriceItemProps> {
42
- routeToActiveTab = () => {}
42
+ routeToActiveTab = () => {
43
+ const { priceTitle } = this.props;
44
+ localStorage.setItem('activeTabCDP', priceTitle);
45
+ }
43
46
 
44
47
  render(): React.ReactNode {
45
48
  const {
@@ -78,6 +81,9 @@ class VehiclePriceItem extends React.Component<IVehiclePriceItemProps> {
78
81
  { [styles.priceItemSearch]: vehicleComponentName === 'search' },
79
82
  { [styles.priceItemRecently]: vehicleComponentName === 'recently' },
80
83
  { [styles.priceItemComparable]: vehicleComponentName === 'comparable' || vehicleComponentName === 'landing' || vehicleComponentName === 'main' },
84
+ // landing (/angebot) cards are a narrow 4-up grid on desktop where the inline monthly
85
+ // label would overflow — keep it stacked there, inline only on the wide single-column mobile.
86
+ { [styles.priceItemLanding]: vehicleComponentName === 'landing' },
81
87
  { [styles.priceItemDisable]: isPriceDisable },
82
88
  { [styles.priceItemBuy]: isTotal }
83
89
  );
@@ -85,7 +91,9 @@ class VehiclePriceItem extends React.Component<IVehiclePriceItemProps> {
85
91
  const priceItemCategoryClassName = classnames(
86
92
  styles.priceItemCategory,
87
93
  { [styles.priceItemCategorySearch]: vehicleComponentName === 'search' || vehicleComponentName === 'myVehicles' },
88
- { [styles.priceItemCategoryComparable]: vehicleComponentName === 'comparable' || vehicleComponentName === 'landing' || vehicleComponentName === 'main' }
94
+ { [styles.priceItemCategoryComparable]: vehicleComponentName === 'comparable' },
95
+ { [styles.priceItemCategoryLanding]: vehicleComponentName === 'landing' },
96
+ { [styles.priceItemCategoryMain]: vehicleComponentName === 'main' }
89
97
  );
90
98
 
91
99
  return (
@@ -134,15 +142,19 @@ class VehiclePriceItem extends React.Component<IVehiclePriceItemProps> {
134
142
  )}
135
143
 
136
144
  {perMonthCurrent && (
137
- <VehicleFormattedPrice
138
- numbersAfterDot={0}
139
- price={perMonthCurrent}
140
- postfix={postfix}
141
- className={classnames(styles.priceMtl, { [styles.priceMtlActive]: !!priceSub })}
142
- isNew={isStrikeShown}
143
- size='semimedium'
144
- sub={priceSub}
145
- />
145
+ <span className={styles.priceCurrentWrap}>
146
+ {/* ADV-70 (design): monthly label ("mtl."/"mth.") now sits BEFORE the rate
147
+ instead of as a "/mtl." suffix after it. */}
148
+ {priceSub && <span className={styles.priceMtlPrefix}>{priceSub.replace(/^\//, '')}</span>}
149
+ <VehicleFormattedPrice
150
+ numbersAfterDot={0}
151
+ price={perMonthCurrent}
152
+ postfix={postfix}
153
+ className={styles.priceMtl}
154
+ isNew={isStrikeShown}
155
+ size='semimedium'
156
+ />
157
+ </span>
146
158
  )}
147
159
  </>
148
160
  ) : (
@@ -12,7 +12,23 @@
12
12
  grid-area: info;
13
13
 
14
14
  & > .consumptionCombined
15
- font-size: 10px
15
+ font-size: 9px
16
+
17
+ // ADV-88: new plug-in hybrid consumption line — full-width row at the very bottom of the
18
+ // card on every breakpoint. `order` pushes it past the price-rating strip so the long text
19
+ // never overlaps it; overrides the per-variant desktop reset to grid-column/grid-row: auto.
20
+ & > .pluginFullWidth
21
+ grid-column: 1 / -1 !important
22
+ grid-row: auto !important
23
+ order: 99
24
+ height: auto !important
25
+ align-items: flex-start
26
+ white-space: normal
27
+ border-bottom: none
28
+ padding-top: 4px
29
+ span
30
+ font-size: 9px
31
+ line-height: 1.35
16
32
 
17
33
  +media-tablet-landscape-down()
18
34
  padding: 0 10px;
@@ -27,7 +43,7 @@
27
43
  background-color rgba(76, 78, 100, 0.12);
28
44
 
29
45
  &.vehiclePropertiesLanding
30
- grid-auto-rows: 44px;
46
+ grid-auto-rows: minmax(44px, auto);
31
47
  grid-template-columns: 1fr 1fr;
32
48
  padding: 0 3px;
33
49
 
@@ -41,7 +57,7 @@
41
57
 
42
58
  +media-tablet-landscape-up()
43
59
  padding-top: 2px;
44
- grid-auto-rows: 38px;
60
+ grid-auto-rows: minmax(38px, auto);
45
61
  grid-template-columns: 100%;
46
62
 
47
63
  span
@@ -63,7 +79,7 @@
63
79
  margin-bottom: 2px;
64
80
 
65
81
  &.vehiclePropertiesMain
66
- grid-auto-rows: 44px;
82
+ grid-auto-rows: minmax(44px, auto);
67
83
  grid-template-columns: 100%;
68
84
  padding: 0 6px;
69
85
 
@@ -71,8 +87,14 @@
71
87
  white-space: pre-line;
72
88
  grid-row: 4;
73
89
 
90
+ // mobile (home top-offer / CDP comparable): vertically centre the "good price" block.
91
+ +media-tablet-landscape-down()
92
+ & > .priceRating
93
+ align-self: center
94
+ margin: auto 0
95
+
74
96
  +media-tablet-landscape-up()
75
- grid-auto-rows: 38px;
97
+ grid-auto-rows: minmax(38px, auto);
76
98
 
77
99
  span
78
100
  font-size: 11px;
@@ -130,6 +152,16 @@
130
152
  grid-template-columns: 1fr 1fr;
131
153
  grid-auto-rows: 44px;
132
154
 
155
+ // ADV-70: underline the price-rating ("GUTER PREIS") cell like the spec rows above it —
156
+ // stretch it to fill the grid cell so the border sits at the same baseline.
157
+ & > .priceRating
158
+ margin: 0
159
+ align-self: stretch
160
+ display: flex
161
+ flex-direction: column
162
+ justify-content: center
163
+ border-bottom: 1px solid rgba(76, 78, 100, 0.12)
164
+
133
165
  & > .consumptionCombined
134
166
  white-space: pre-line;
135
167
  grid-column: 1 / span 2;
@@ -216,3 +248,26 @@
216
248
  .priceRating
217
249
  margin: auto;
218
250
  box-sizing: border-box;
251
+
252
+ // ADV-88: SRL DESKTOP — hide the availability ("Sofort"/"from {date}") cell ONLY for NEW plug-in
253
+ // hybrids (engineData.hybridPlugin + mainData.condition selector_condition_new) so the price-rating
254
+ // flows up into its place. All other cards keep availability; mobile keeps it for everyone.
255
+ .vehiclePropertiesSearch.searchPluginInfo
256
+ +media-tablet-landscape-up()
257
+ & > .offerAvailability
258
+ display: none
259
+
260
+ // SRL MOBILE — centre the "good price" cell (horizontally + vertically) on ALL search cards.
261
+ .vehicleInfo.vehiclePropertiesSearch
262
+ +media-tablet-landscape-down()
263
+ & > .priceRating
264
+ align-items: center
265
+ justify-content: center
266
+
267
+ // SRL MOBILE — drop the "good price" underline ONLY for NEW plug-in hybrids (engineData.hybridPlugin
268
+ // + mainData.condition selector_condition_new). The extra .searchPluginInfo makes this (0,4,0) so it
269
+ // beats the base (0,3,0) border-bottom; non-plug-in cards keep the underline.
270
+ .vehicleInfo.vehiclePropertiesSearch.searchPluginInfo
271
+ +media-tablet-landscape-down()
272
+ & > .priceRating
273
+ border-bottom: none
@@ -1,6 +1,7 @@
1
1
  /* tslint:disable */
2
2
  import * as React from 'react';
3
3
  import classnames from 'classnames';
4
+ import _get from 'lodash/get';
4
5
  import styles from './VehicleInfo.styl';
5
6
  import PriceRating from '../../../PriceRating/PriceRating';
6
7
  import { Visible, Hidden } from 'react-grid-system';
@@ -43,8 +44,10 @@ const VehicleInfo: React.FC<IVehicleInfoProps> = (props) => {
43
44
  consumption,
44
45
  location,
45
46
  offer,
46
- engineData
47
- } = props;
47
+ engineData,
48
+ leasing,
49
+ suppressConsumption
50
+ } = props as (typeof props & { suppressConsumption?: boolean });
48
51
  const firstRegistrationDate = regDate && regDate !== 0 ? regDate : 'N/A';
49
52
 
50
53
  const dataDecoratedProps = {
@@ -65,7 +68,8 @@ const VehicleInfo: React.FC<IVehicleInfoProps> = (props) => {
65
68
  },
66
69
  environmentEmissions: {
67
70
  co2: environmentEmissions.co2,
68
- wltpCo2: environmentEmissions.wltpCo2
71
+ wltpCo2: environmentEmissions.wltpCo2,
72
+ wltpEnergyEfficiencyClass: environmentEmissions.wltpEnergyEfficiencyClass
69
73
  },
70
74
  consumption: {
71
75
  fuel: consumption.fuel,
@@ -78,16 +82,29 @@ const VehicleInfo: React.FC<IVehicleInfoProps> = (props) => {
78
82
  },
79
83
  };
80
84
 
85
+ // ADV-88: ANY plug-in hybrid (new or used) carries the long weighted+discharged consumption/CO2
86
+ // line — render it full-width. Gated on hybridPlugin only, no condition check.
87
+ // ADV-88: "is a hybrid car" is determined by fuel type (hybrid electric + diesel/petrol), not hybridPlugin.
88
+ const isPluginHybrid = consumption.fuel === 'selector_fuel_hybridElectricalDiesel'
89
+ || consumption.fuel === 'selector_fuel_hybridElectricalPetrol';
81
90
  const decoratedProps = getDecoratedProps(dataDecoratedProps, t, language);
82
91
  const renderProperty = (renderProperties: any, vehicleComponentName?: any) => {
83
- const mainPropertiesList = renderProperties(dataDecoratedProps.consumption.fuel, combineRefAlternative).map((prop: string) => ({
84
- icon: decoratedProps[prop].icon,
85
- description: decoratedProps[prop].value,
86
- className: styles[decoratedProps[prop].name],
87
- classNameIcon: (vehicleComponentName === 'search' || 'myVehicles' || 'favorite' || 'recently') && styles.carIconSearch,
88
- smalltext: (decoratedProps[prop].name === 'consumptionCombined') && (vehicleComponentName !== 'search'),
89
- hybridPlugin: engineData.hybridPlugin && decoratedProps[prop].name === 'consumptionCombined' && vehicleComponentName !== 'search'
90
- }));
92
+ const mainPropertiesList = renderProperties(dataDecoratedProps.consumption.fuel, combineRefAlternative)
93
+ // ADV-88: on landing/main the plug-in consumption line is rendered full-width by VehicleSmallCard.
94
+ .filter((prop: string) => !(suppressConsumption && decoratedProps[prop] && decoratedProps[prop].name === 'consumptionCombined'))
95
+ .map((prop: string) => {
96
+ const isConsumption = decoratedProps[prop].name === 'consumptionCombined';
97
+ // On non-SRL cards (and for the full-width plug-in line) drop the fuel-pump icon to free up space.
98
+ const hideConsumptionIcon = isConsumption && (vehicleComponentName !== 'search' || isPluginHybrid);
99
+ return {
100
+ icon: hideConsumptionIcon ? '' : decoratedProps[prop].icon,
101
+ description: decoratedProps[prop].value,
102
+ className: classnames(styles[decoratedProps[prop].name], { [styles.pluginFullWidth]: isConsumption && isPluginHybrid }),
103
+ classNameIcon: (vehicleComponentName === 'search' || 'myVehicles' || 'favorite' || 'recently') && styles.carIconSearch,
104
+ smalltext: isConsumption && (vehicleComponentName !== 'search'),
105
+ hybridPlugin: isPluginHybrid && isConsumption && vehicleComponentName !== 'search'
106
+ };
107
+ });
91
108
 
92
109
  return mainPropertiesList.map((property: any, index: number) => (
93
110
  <VehicleProperty {...property} key={index} />
@@ -100,6 +117,8 @@ const VehicleInfo: React.FC<IVehicleInfoProps> = (props) => {
100
117
  { [styles.vehiclePropertiesLanding]: vehicleComponentName === 'landing' },
101
118
  { [styles.vehiclePropertiesMain]: vehicleComponentName === 'main' },
102
119
  { [styles.vehiclePropertiesSearch]: vehicleComponentName === 'search' },
120
+ // ADV-88: mark a plug-in SRL card so its "good price" underline can be dropped on mobile.
121
+ { [styles.searchPluginInfo]: isPluginHybrid && vehicleComponentName === 'search' },
103
122
  { [styles.vehiclePropertiesFavorite]: vehicleComponentName === 'favorite' },
104
123
  { [styles.vehiclePropertiesMyVehicles]: vehicleComponentName === 'myVehicles' },
105
124
  { [styles.vehiclePropertiesRecently]: vehicleComponentName === 'recently' },
@@ -149,7 +168,12 @@ const VehicleInfo: React.FC<IVehicleInfoProps> = (props) => {
149
168
  ),
150
169
  ...routeObj,
151
170
  className: wrapClasses,
152
- onClick: () => localStorage.setItem('activeTabCDP', t('vehicleProps:title.financing')),
171
+ onClick: () => localStorage.setItem(
172
+ 'activeTabCDP',
173
+ _get(leasing, 'isActive', false)
174
+ ? t('vehicleProps:title.leasing')
175
+ : t('vehicleProps:title.financing')
176
+ ),
153
177
  href: url,
154
178
  target,
155
179
  rel
@@ -62,8 +62,9 @@
62
62
  font-size: 12px;
63
63
  height: 42px;
64
64
 
65
- &.vehiclePriceTitleLanding
66
- font-size: 11px;
65
+ &.vehiclePriceTitleLanding,
66
+ &.vehiclePriceTitleMain
67
+ font-size: 10px;
67
68
  height: 38px;
68
69
 
69
70
  .addOfferButton