@bytebrand/fe-ui-core-autobahn 1.0.1 → 1.0.2
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/assets/autode-logo.svg +6 -6
- package/cards/CarCard.tsx +174 -174
- package/cards/CarRow.tsx +186 -182
- package/cards/cardParts.tsx +529 -489
- package/cards/index.ts +37 -35
- package/cards/types.ts +122 -114
- package/chrome/Footer.tsx +189 -189
- package/chrome/TopBar.tsx +405 -405
- package/chrome/index.ts +20 -20
- package/chrome/svg.d.ts +11 -11
- package/compat/AccardionSection/AccardionSection.styl +45 -45
- package/compat/AccardionSection/AccardionSection.tsx +56 -56
- package/compat/AccordionWidget/AccordionWidget.styl +220 -220
- package/compat/AccordionWidget/AccordionWidget.tsx +257 -257
- package/compat/AccordionWrapper/AccordionItem/AccordionItem.styl +34 -34
- package/compat/AccordionWrapper/AccordionItem/AccordionItem.tsx +64 -64
- package/compat/AccordionWrapper/AccordionWrapper.tsx +34 -34
- package/compat/AdvantageItem/AdvantageItem.styl +47 -47
- package/compat/AdvantageItem/AdvantageItem.tsx +26 -26
- package/compat/Alternative/DealerInfo.styl +116 -116
- package/compat/Alternative/DealerInfo.tsx +171 -171
- package/compat/Badge/Badge.styl +44 -44
- package/compat/Badge/Badge.tsx +25 -25
- package/compat/BodyTypeIcons/Audi.tsx +9 -9
- package/compat/BodyTypeIcons/Bmw.tsx +860 -860
- package/compat/BodyTypeIcons/Ford.tsx +31 -31
- package/compat/BodyTypeIcons/IconsConfig.tsx +44 -44
- package/compat/BodyTypeIcons/IconsConfigCompact.tsx +30 -30
- package/compat/BodyTypeIcons/Mazda.tsx +44 -44
- package/compat/BodyTypeIcons/MercedesBenz.tsx +38 -38
- package/compat/BodyTypeIcons/Opel.tsx +19 -19
- package/compat/BodyTypeIcons/Search.tsx +19 -19
- package/compat/BodyTypeIcons/SelectorCategoryCombi.tsx +68 -68
- package/compat/BodyTypeIcons/SelectorCategoryCompact.tsx +20 -20
- package/compat/BodyTypeIcons/SelectorCategoryConvertible.tsx +68 -68
- package/compat/BodyTypeIcons/SelectorCategoryCoupe.tsx +60 -60
- package/compat/BodyTypeIcons/SelectorCategoryMinibus.tsx +64 -64
- package/compat/BodyTypeIcons/SelectorCategorySedan.tsx +69 -69
- package/compat/BodyTypeIcons/SelectorCategorySuv.tsx +77 -77
- package/compat/BodyTypeIcons/SelectorCategoryTransporter.tsx +68 -68
- package/compat/BodyTypeIcons/SelectorCategoryVan.tsx +72 -72
- package/compat/BodyTypeIcons/Volkswagen.tsx +330 -330
- package/compat/BodyTypeIcons/index.ts +17 -17
- package/compat/Button/Button.tsx +65 -65
- package/compat/ButtonOld/Button.styl +65 -65
- package/compat/ButtonOld/Button.tsx +84 -84
- package/compat/Checkbox/Checkbox.styl +119 -119
- package/compat/Checkbox/Checkbox.tsx +151 -151
- package/compat/Checkbox/FormCheckbox.styl +22 -22
- package/compat/Checkbox/FormCheckbox.tsx +86 -86
- package/compat/Co2Widget/CO2Efficiency.styl +219 -219
- package/compat/Co2Widget/CO2Efficiency.tsx +93 -93
- package/compat/ContactInfo/ContactInfo.styl +22 -22
- package/compat/ContactInfo/ContactInfo.tsx +161 -161
- package/compat/ContactInfo/TemporaryTranslation.ts +11 -11
- package/compat/CookieModal/CookieModal.tsx +49 -49
- package/compat/CookieModal/Modal.tsx +43 -43
- package/compat/CookieModal/ModalsConfig.tsx +23 -23
- package/compat/CookieModal/modals/ManageCookieModal/ManageCookieModal.styl +86 -86
- package/compat/CookieModal/modals/ManageCookieModal/ManageCookieModal.tsx +184 -184
- package/compat/CookieModal/modals/PreviewCookieModal/PreviewCookieModal.styl +66 -66
- package/compat/CookieModal/modals/PreviewCookieModal/PreviewCookieModal.tsx +51 -51
- package/compat/CookieModal/modals/TestModal.tsx +7 -7
- package/compat/CookieModal/useModal.ts +13 -13
- package/compat/CustomerQuote/CustomerQuote.styl +79 -79
- package/compat/CustomerQuote/CustomerQuote.tsx +68 -68
- package/compat/CustomerQuotesSlider/CustomerQuotesSlider.styl +46 -46
- package/compat/CustomerQuotesSlider/CustomerQuotesSlider.tsx +79 -79
- package/compat/CustomerQuotesSlider/SliderArrow.tsx +20 -20
- package/compat/CustomerQuotesSlider/slider.global.styl +2 -2
- package/compat/ExpansionPanel/ExpansionPanel.tsx +68 -68
- package/compat/FirstInfoBlock/FirstInfoBlock.styl +33 -33
- package/compat/FirstInfoBlock/FirstInfoBlock.tsx +49 -49
- package/compat/FirstInfoBlock/FirstInfoBlockItem/FirstInfoBlockItem.styl +66 -66
- package/compat/FirstInfoBlock/FirstInfoBlockItem/FirstInfoBlockItem.tsx +21 -21
- package/compat/FormattedNumber/FormattedNumber.styl +1 -1
- package/compat/FormattedNumber/FormattedNumber.tsx +90 -90
- package/compat/IconContainer/IconContainer.styl +23 -23
- package/compat/IconContainer/IconContainer.tsx +34 -34
- package/compat/Image/Image.styl +109 -109
- package/compat/Image/Image.tsx +302 -302
- package/compat/ImageSettings/EditableOptionsTable/CustomCheckbox/CustomCheckbox.styl +7 -7
- package/compat/ImageSettings/EditableOptionsTable/CustomCheckbox/CustomCheckbox.tsx +30 -30
- package/compat/ImageSettings/EditableOptionsTable/EditableOptionsTable.styl +122 -122
- package/compat/ImageSettings/EditableOptionsTable/EditableOptionsTable.tsx +199 -199
- package/compat/ImageSettings/EditableOptionsTable/ImageIcon/ImageIcon.styl +3 -3
- package/compat/ImageSettings/EditableOptionsTable/ImageIcon/ImageIcon.tsx +15 -15
- package/compat/ImageSettings/OptionsTable/OptionsTable.styl +47 -47
- package/compat/ImageSettings/OptionsTable/OptionsTable.tsx +122 -122
- package/compat/ImageSettings/PricePlan/PricePlan.styl +63 -63
- package/compat/ImageSettings/PricePlan/PricePlan.tsx +32 -32
- package/compat/ImageSettings/index.ts +42 -42
- package/compat/ImagesSet/ImagesSet.styl +27 -27
- package/compat/ImagesSet/ImagesSet.tsx +76 -76
- package/compat/InfoBlockWrapper/InfoBlockWrapper.styl +41 -41
- package/compat/InfoBlockWrapper/InfoBlockWrapper.tsx +46 -46
- package/compat/Loader/Loader.styl +39 -39
- package/compat/Loader/Loader.tsx +32 -32
- package/compat/MagnifyGlass/MagnifyGlass.styl +33 -33
- package/compat/MagnifyGlass/MagnifyGlass.tsx +213 -213
- package/compat/MdAccordionGroup/MdAccordionGroup.tsx +53 -53
- package/compat/MdCheckbox/MdCheckbox.tsx +69 -69
- package/compat/MdField/MdField.tsx +100 -100
- package/compat/MdSelect/MdSelect.tsx +103 -103
- package/compat/MdSwitch/MdSwitch.tsx +29 -29
- package/compat/MdTabs/MdTabs.tsx +47 -47
- package/compat/MdTooltip/MdTooltip.tsx +31 -31
- package/compat/OfferDetailedSection/OfferDetailedSection.styl +31 -31
- package/compat/OfferDetailedSection/OfferDetailedSection.tsx +100 -100
- package/compat/OfferDetailedSection/partials/PanelConfig.styl +131 -131
- package/compat/OfferDetailedSection/partials/PanelConfig.tsx +121 -121
- package/compat/OfferPanel/AboAccordion/AboAccordion.styl +24 -24
- package/compat/OfferPanel/AboAccordion/AboAccordion.tsx +128 -128
- package/compat/OfferPanel/AboAccordion/AboColorOptions/AboColorOptions.styl +11 -11
- package/compat/OfferPanel/AboAccordion/AboColorOptions/AboColorOptions.tsx +35 -35
- package/compat/OfferPanel/AboAccordion/AboFaq/AboFaq.styl +20 -20
- package/compat/OfferPanel/AboAccordion/AboFaq/AboFaq.tsx +25 -25
- package/compat/OfferPanel/AboAccordion/AboIncludedServices/AboIncludedServices.styl +13 -13
- package/compat/OfferPanel/AboAccordion/AboIncludedServices/AboIncludedServices.tsx +39 -39
- package/compat/OfferPanel/MuiOfferPeriod/MuiOfferPeriod.tsx +42 -42
- package/compat/OfferPanel/OfferCheckboxGroup/CheckboxContainer.tsx +140 -140
- package/compat/OfferPanel/OfferCheckboxGroup/OfferCheckboxGroup.styl +144 -144
- package/compat/OfferPanel/OfferCheckboxGroup/OfferCheckboxGroup.tsx +23 -23
- package/compat/OfferPanel/OfferPanel.styl +193 -193
- package/compat/OfferPanel/OfferPanel.tsx +81 -81
- package/compat/OfferPanel/OfferPeriod/OfferPeriod.styl +24 -24
- package/compat/OfferPanel/OfferPeriod/OfferPeriod.tsx +45 -45
- package/compat/OfferPanel/RangeGroup/RangeGroup.tsx +39 -39
- package/compat/OfferRequestButtonWrapper/OfferRequestButtonWrapper.styl +119 -119
- package/compat/OfferRequestButtonWrapper/OfferRequestButtonWrapper.styled.tsx +33 -33
- package/compat/OfferRequestButtonWrapper/OfferRequestButtonWrapper.tsx +122 -122
- package/compat/PriceRating/PriceRating.styl +47 -47
- package/compat/PriceRating/PriceRating.tsx +64 -64
- package/compat/PriceRatingDetailed/PriceRatingDetailed.styl +120 -120
- package/compat/PriceRatingDetailed/PriceRatingDetailed.tsx +191 -191
- package/compat/PricingToolBlock/PricingTool.styl +6 -6
- package/compat/PricingToolBlock/PricingTool.tsx +29 -29
- package/compat/Radio/Radio.styl +115 -115
- package/compat/Radio/Radio.tsx +141 -141
- package/compat/Radio/RadioGroup.styl +5 -5
- package/compat/Radio/RadioGroup.tsx +65 -65
- package/compat/Range/Range.tsx +79 -79
- package/compat/RateSearchValue/RateSearchValue.styl +22 -22
- package/compat/RateSearchValue/RateSearchValue.tsx +55 -55
- package/compat/RateSearchWidget/RateSearchWidget.styl +106 -106
- package/compat/RateSearchWidget/RateSearchWidget.tsx +163 -163
- package/compat/ServiceBlockItem/ServiceBlockItem.styl +47 -47
- package/compat/ServiceBlockItem/ServiceBlockItem.tsx +25 -25
- package/compat/SkeletonItem/SkeletonItem.styl +80 -80
- package/compat/SkeletonItem/SkeletonItem.tsx +80 -80
- package/compat/StarButton/StarButton.styl +39 -39
- package/compat/StarButton/StarButton.tsx +31 -31
- package/compat/TabPanel/TabPanel.tsx +28 -28
- package/compat/TimePicker/TimePicker.styl +22 -22
- package/compat/TimePicker/TimePicker.tsx +156 -156
- package/compat/Tooltip/Tooltip.styl +117 -117
- package/compat/Tooltip/Tooltip.tsx +63 -63
- package/compat/Usp/Usp.styl +78 -78
- package/compat/Usp/Usp.tsx +30 -30
- package/compat/Usp/uspTranslate.ts +12 -12
- package/compat/VehicleDetailedSidebar/VehicleDetailedSidebar.styl +36 -36
- package/compat/VehicleDetailedSidebar/VehicleDetailedSidebar.tsx +178 -178
- package/compat/VehicleDetailedSidebar/partials/Price.styl +27 -27
- package/compat/VehicleDetailedSidebar/partials/Price.tsx +41 -41
- package/compat/VehicleDetailedSidebar/partials/PriceContent.styl +123 -123
- package/compat/VehicleDetailedSidebar/partials/PriceContent.tsx +128 -128
- package/compat/VehicleDetailedSidebar/partials/Properties.styl +58 -58
- package/compat/VehicleDetailedSidebar/partials/Properties.tsx +155 -155
- package/compat/VehicleDetailedSidebar/partials/Title.styl +35 -35
- package/compat/VehicleDetailedSidebar/partials/Title.tsx +33 -33
- package/compat/VehicleDetailedSlider/VehicleDetailedSlider.styl +146 -146
- package/compat/VehicleDetailedSlider/VehicleDetailedSlider.tsx +382 -382
- package/compat/VehicleDetailedSlider/partials/MobileStast.tsx +61 -61
- package/compat/VehicleDetailedSlider/partials/MobileStats.styl +71 -71
- package/compat/VehicleDetailedSlider/partials/PriceData.styl +50 -50
- package/compat/VehicleDetailedSlider/partials/PriceData.tsx +67 -67
- package/compat/VehicleDetailedSlider/partials/Stats.styl +80 -80
- package/compat/VehicleDetailedSlider/partials/Stats.tsx +62 -62
- package/compat/VehicleDetailedSlider/partials/Title.styl +44 -44
- package/compat/VehicleDetailedSlider/partials/Title.tsx +36 -36
- package/compat/VehicleFormattedPrice/VehicleFormattedPrice.styl +148 -148
- package/compat/VehicleFormattedPrice/VehicleFormattedPrice.tsx +163 -163
- package/compat/VehicleSlider/VehicleSlider.styl +62 -62
- package/compat/VehicleSlider/VehicleSlider.tsx +125 -125
- package/compat/VehicleSlider/VehicleSliderForSRL.tsx +175 -175
- package/compat/VehicleSmallCard/SeoText/SeoText.styl +8 -8
- package/compat/VehicleSmallCard/SeoText/SeoText.tsx +16 -16
- package/compat/VehicleSmallCard/VehicleData/VechiclePriceItem/VechiclePriceItem.styl +204 -204
- package/compat/VehicleSmallCard/VehicleData/VechiclePriceItem/VechiclePriceItem.tsx +199 -199
- package/compat/VehicleSmallCard/VehicleData/VehicleInfo/VehicleInfo.styl +273 -273
- package/compat/VehicleSmallCard/VehicleData/VehicleInfo/VehicleInfo.tsx +179 -179
- package/compat/VehicleSmallCard/VehicleData/VehiclePrice/VehiclePrice.styl +165 -165
- package/compat/VehicleSmallCard/VehicleData/VehiclePrice/VehiclePrice.tsx +299 -299
- package/compat/VehicleSmallCard/VehicleData/VehicleProperty/VehicleProperty.styl +32 -32
- package/compat/VehicleSmallCard/VehicleData/VehicleProperty/VehicleProperty.tsx +35 -35
- package/compat/VehicleSmallCard/VehicleData/VehicleTitle/VehicleTitle.styl +135 -135
- package/compat/VehicleSmallCard/VehicleData/VehicleTitle/VehicleTitle.tsx +91 -91
- package/compat/VehicleSmallCard/VehicleSmallCard.styl +309 -309
- package/compat/VehicleSmallCard/VehicleSmallCard.tsx +448 -448
- package/compat/index.ts +77 -77
- package/compat/legacy-theme/mixins.styl +93 -93
- package/compat/legacy-theme/priceReviewColors.styl +12 -12
- package/compat/legacy-theme/slider.global.styl +5 -5
- package/compat/legacy-theme/theme.styl +136 -136
- package/compat/withLabel/withLabel.styl +33 -33
- package/compat/withLabel/withLabel.tsx +44 -44
- package/compat/withStats/withStats.styl +174 -174
- package/compat/withStats/withStats.tsx +238 -238
- package/constants/RateSearchWidget.ts +15 -15
- package/constants/Search.ts +290 -290
- package/constants/SearchWidget.ts +108 -108
- package/constants/app.ts +223 -223
- package/constants/common.ts +127 -127
- package/constants/core.ts +131 -131
- package/constants/highlights.ts +165 -165
- package/constants/price.ts +9 -9
- package/constants/selectors.ts +38 -38
- package/constants.ts +91 -91
- package/data/DataTransformers.ts +88 -88
- package/data/fieldMapping.ts +364 -342
- package/data/toAutobahnCar.ts +455 -442
- package/iconsvg/IconSVG.tsx +30 -30
- package/iconsvg/IconSVGConfig.tsx +768 -768
- package/iconsvg/SVG/AboPartner.tsx +16 -16
- package/iconsvg/SVG/ArrowQuotes.tsx +22 -22
- package/iconsvg/SVG/CloseIcon.tsx +17 -17
- package/iconsvg/SVG/CloseIconSelect.tsx +18 -18
- package/iconsvg/SVG/ClosedLockIcon.tsx +18 -18
- package/iconsvg/SVG/DealerCheckIcon.tsx +18 -18
- package/iconsvg/SVG/DealerPopoverMail.tsx +21 -21
- package/iconsvg/SVG/DealerPopoverPhone.tsx +21 -21
- package/iconsvg/SVG/GrayPhoneIcon.tsx +22 -22
- package/iconsvg/SVG/InternetIcon.tsx +18 -18
- package/iconsvg/SVG/WhiteEnvelopeIcon.tsx +21 -21
- package/iconsvg/SVG/bodyType/Cabrio.tsx +23 -23
- package/iconsvg/SVG/bodyType/Coupe.tsx +22 -22
- package/iconsvg/SVG/bodyType/Minibus.tsx +22 -22
- package/iconsvg/SVG/bodyType/Other.tsx +25 -25
- package/iconsvg/SVG/bodyType/Sedan.tsx +22 -22
- package/iconsvg/SVG/bodyType/SelectorCategoryCombi.tsx +68 -68
- package/iconsvg/SVG/bodyType/SelectorCategoryCompact.tsx +20 -20
- package/iconsvg/SVG/bodyType/SelectorCategoryConvertible.tsx +68 -68
- package/iconsvg/SVG/bodyType/SelectorCategoryCoupe.tsx +60 -60
- package/iconsvg/SVG/bodyType/SelectorCategoryMinibus.tsx +64 -64
- package/iconsvg/SVG/bodyType/SelectorCategoryOther.tsx +60 -60
- package/iconsvg/SVG/bodyType/SelectorCategorySedan.tsx +69 -69
- package/iconsvg/SVG/bodyType/SelectorCategorySuv.tsx +77 -77
- package/iconsvg/SVG/bodyType/SelectorCategoryTransporter.tsx +68 -68
- package/iconsvg/SVG/bodyType/SelectorCategoryVan.tsx +72 -72
- package/iconsvg/SVG/bodyType/Small.tsx +23 -23
- package/iconsvg/SVG/bodyType/Suv.tsx +23 -23
- package/iconsvg/SVG/bodyType/Van.tsx +23 -23
- package/iconsvg/SVG/bodyType/Wagon.tsx +23 -23
- package/iconsvg/SVG/common/AddIcon.tsx +16 -16
- package/iconsvg/SVG/common/AddPlus.tsx +16 -16
- package/iconsvg/SVG/common/AddressDashboard.tsx +29 -29
- package/iconsvg/SVG/common/AddressIcon.tsx +20 -20
- package/iconsvg/SVG/common/ArrowDetailedAccordionBlue.tsx +26 -26
- package/iconsvg/SVG/common/ArrowDownBlue.tsx +21 -21
- package/iconsvg/SVG/common/ArrowSelect.tsx +23 -23
- package/iconsvg/SVG/common/ArrowStepDown.tsx +18 -18
- package/iconsvg/SVG/common/Autocheck.tsx +19 -19
- package/iconsvg/SVG/common/AutodeLogo.tsx +36 -36
- package/iconsvg/SVG/common/Avatar.tsx +17 -17
- package/iconsvg/SVG/common/BellGray.tsx +19 -19
- package/iconsvg/SVG/common/BigInfoTransparent.tsx +13 -13
- package/iconsvg/SVG/common/Browse.tsx +20 -20
- package/iconsvg/SVG/common/Calendar.tsx +24 -24
- package/iconsvg/SVG/common/CallbackDashboard.tsx +30 -30
- package/iconsvg/SVG/common/Camera.tsx +17 -17
- package/iconsvg/SVG/common/Car.tsx +16 -16
- package/iconsvg/SVG/common/CarBody.tsx +19 -19
- package/iconsvg/SVG/common/CarFront.tsx +43 -43
- package/iconsvg/SVG/common/CarInspectionCheck.tsx +21 -21
- package/iconsvg/SVG/common/CarInspectionScheme0.tsx +32 -32
- package/iconsvg/SVG/common/CarInspectionScheme1.tsx +53 -53
- package/iconsvg/SVG/common/CarInspectionScheme2.tsx +52 -52
- package/iconsvg/SVG/common/CarInspectionScheme3.tsx +32 -32
- package/iconsvg/SVG/common/CarInspectionScheme4.tsx +32 -32
- package/iconsvg/SVG/common/CarInspectionScheme5.tsx +32 -32
- package/iconsvg/SVG/common/CarInspectionScheme6.tsx +32 -32
- package/iconsvg/SVG/common/CarInspectionSchemeGeneral copy.tsx +24 -24
- package/iconsvg/SVG/common/CarInspectionSchemeGeneral.tsx +24 -24
- package/iconsvg/SVG/common/CheckBlue.tsx +18 -18
- package/iconsvg/SVG/common/CheckGreen.tsx +22 -22
- package/iconsvg/SVG/common/CheckMark.tsx +16 -16
- package/iconsvg/SVG/common/CheckWhite.tsx +19 -19
- package/iconsvg/SVG/common/Chevron.tsx +17 -17
- package/iconsvg/SVG/common/CircledCheckmark.tsx +25 -25
- package/iconsvg/SVG/common/Clock.tsx +18 -18
- package/iconsvg/SVG/common/Close.tsx +19 -19
- package/iconsvg/SVG/common/CloseGrey.tsx +22 -22
- package/iconsvg/SVG/common/ContactEmail.tsx +21 -21
- package/iconsvg/SVG/common/ContactPhone.tsx +28 -28
- package/iconsvg/SVG/common/CopyIcon copy.tsx +22 -22
- package/iconsvg/SVG/common/CopyIcon.tsx +22 -22
- package/iconsvg/SVG/common/CopyIconForDealer.tsx +21 -21
- package/iconsvg/SVG/common/DashboardIcon.tsx +20 -20
- package/iconsvg/SVG/common/DashboardQuestionMark.tsx +20 -20
- package/iconsvg/SVG/common/DealersIcon.tsx +20 -20
- package/iconsvg/SVG/common/DeleteCircle.tsx +31 -31
- package/iconsvg/SVG/common/DeleteV1Icon.tsx +18 -18
- package/iconsvg/SVG/common/DeliveryDashboard.tsx +25 -25
- package/iconsvg/SVG/common/DeliveryMail.tsx +24 -24
- package/iconsvg/SVG/common/Discount100De.tsx +18 -18
- package/iconsvg/SVG/common/Discount100En.tsx +19 -19
- package/iconsvg/SVG/common/Discount66De.tsx +28 -28
- package/iconsvg/SVG/common/Discount66En.tsx +20 -20
- package/iconsvg/SVG/common/DoneIcon.tsx +18 -18
- package/iconsvg/SVG/common/EditCircle.tsx +32 -32
- package/iconsvg/SVG/common/EditPriceIcon.tsx +20 -20
- package/iconsvg/SVG/common/EuroCurrency.tsx +18 -18
- package/iconsvg/SVG/common/Export.tsx +20 -20
- package/iconsvg/SVG/common/Eye.tsx +17 -17
- package/iconsvg/SVG/common/EyeCatch.tsx +19 -19
- package/iconsvg/SVG/common/FavoritesIcon.tsx +20 -20
- package/iconsvg/SVG/common/FilterRange.tsx +16 -16
- package/iconsvg/SVG/common/FilterToolBlack.tsx +23 -23
- package/iconsvg/SVG/common/FlagDe.tsx +21 -21
- package/iconsvg/SVG/common/FlagEn.tsx +43 -43
- package/iconsvg/SVG/common/GrayEnvelopeIcon.tsx +19 -19
- package/iconsvg/SVG/common/HamburgerMenuIcon.tsx +18 -18
- package/iconsvg/SVG/common/HandingOverDashboard.tsx +32 -32
- package/iconsvg/SVG/common/ImageSettingsIcon.tsx +20 -20
- package/iconsvg/SVG/common/Info.tsx +16 -16
- package/iconsvg/SVG/common/InfoIcon.tsx +17 -17
- package/iconsvg/SVG/common/InfoTransparent.tsx +18 -18
- package/iconsvg/SVG/common/LogoutIcon.tsx +20 -20
- package/iconsvg/SVG/common/MagnifyingGlass.tsx +31 -31
- package/iconsvg/SVG/common/MenuArrow.tsx +16 -16
- package/iconsvg/SVG/common/MenuGrey.tsx +22 -22
- package/iconsvg/SVG/common/MobileDeLogo.tsx +108 -108
- package/iconsvg/SVG/common/MyOrderIcon.tsx +20 -20
- package/iconsvg/SVG/common/MyVehiclesIcon.tsx +20 -20
- package/iconsvg/SVG/common/NewFlagDe.tsx +25 -25
- package/iconsvg/SVG/common/NewFlagEn.tsx +34 -34
- package/iconsvg/SVG/common/OrderReceivedDashboard.tsx +27 -27
- package/iconsvg/SVG/common/Package.tsx +30 -30
- package/iconsvg/SVG/common/Phone.tsx +18 -18
- package/iconsvg/SVG/common/PhoneGrey.tsx +22 -22
- package/iconsvg/SVG/common/PickupDashboard.tsx +30 -30
- package/iconsvg/SVG/common/Picture.tsx +24 -24
- package/iconsvg/SVG/common/Pictures.tsx +32 -32
- package/iconsvg/SVG/common/Plus.tsx +16 -16
- package/iconsvg/SVG/common/PlusNew.tsx +16 -16
- package/iconsvg/SVG/common/PreparationDashboard.tsx +29 -29
- package/iconsvg/SVG/common/ProfileDashboard.tsx +24 -24
- package/iconsvg/SVG/common/ProfileIcon.tsx +17 -17
- package/iconsvg/SVG/common/Question.tsx +19 -19
- package/iconsvg/SVG/common/QuestionBold.tsx +25 -25
- package/iconsvg/SVG/common/RegistrationDashboard.tsx +31 -31
- package/iconsvg/SVG/common/SavedSearchsIcon.tsx +20 -20
- package/iconsvg/SVG/common/Search.tsx +19 -19
- package/iconsvg/SVG/common/SearchGrey.tsx +22 -22
- package/iconsvg/SVG/common/SettingPenIcon.tsx +20 -20
- package/iconsvg/SVG/common/Share.tsx +16 -16
- package/iconsvg/SVG/common/ShoppingCart.tsx +18 -18
- package/iconsvg/SVG/common/SliderArrow.tsx +21 -21
- package/iconsvg/SVG/common/SliderEye.tsx +17 -17
- package/iconsvg/SVG/common/SortUpDownArrows.tsx +18 -18
- package/iconsvg/SVG/common/Speedometer.tsx +23 -23
- package/iconsvg/SVG/common/Star.tsx +20 -20
- package/iconsvg/SVG/common/StarNew.tsx +16 -16
- package/iconsvg/SVG/common/StarOutline.tsx +20 -20
- package/iconsvg/SVG/common/StarRoundedCorners.tsx +18 -18
- package/iconsvg/SVG/common/Stats.tsx +17 -17
- package/iconsvg/SVG/common/Step1.tsx +21 -21
- package/iconsvg/SVG/common/Step2.tsx +20 -20
- package/iconsvg/SVG/common/Step3.tsx +21 -21
- package/iconsvg/SVG/common/SupportCallbackIcon.tsx +20 -20
- package/iconsvg/SVG/common/Telephone.tsx +22 -22
- package/iconsvg/SVG/common/Time.tsx +17 -17
- package/iconsvg/SVG/common/Timetable.tsx +18 -18
- package/iconsvg/SVG/common/Trash.tsx +22 -22
- package/iconsvg/SVG/common/TrashRed.tsx +23 -23
- package/iconsvg/SVG/common/Upload.tsx +17 -17
- package/iconsvg/SVG/common/UserGrey.tsx +22 -22
- package/iconsvg/SVG/common/UserProfileIcon.tsx +20 -20
- package/iconsvg/SVG/common/ValidateFailure.tsx +21 -21
- package/iconsvg/SVG/common/ValidateSuccess.tsx +21 -21
- package/iconsvg/SVG/common/WarningTriangle.tsx +20 -20
- package/iconsvg/SVG/common/WhiteArrowUp.tsx +21 -21
- package/iconsvg/SVG/common/WhiteKey.tsx +21 -21
- package/iconsvg/SVG/common/WhitePeople.tsx +23 -23
- package/iconsvg/SVG/common/WhiteTick.tsx +19 -19
- package/iconsvg/SVG/flags/AT.tsx +19 -19
- package/iconsvg/SVG/flags/BE.tsx +20 -20
- package/iconsvg/SVG/flags/BG.tsx +20 -20
- package/iconsvg/SVG/flags/CH.tsx +22 -22
- package/iconsvg/SVG/flags/CZ.tsx +18 -18
- package/iconsvg/SVG/flags/DE.tsx +18 -18
- package/iconsvg/SVG/flags/DK.tsx +18 -18
- package/iconsvg/SVG/flags/ES.tsx +2585 -2585
- package/iconsvg/SVG/flags/FI.tsx +18 -18
- package/iconsvg/SVG/flags/FR.tsx +20 -20
- package/iconsvg/SVG/flags/GB.tsx +26 -26
- package/iconsvg/SVG/flags/HR.tsx +135 -135
- package/iconsvg/SVG/flags/HU.tsx +20 -20
- package/iconsvg/SVG/flags/IT.tsx +20 -20
- package/iconsvg/SVG/flags/LI.tsx +106 -106
- package/iconsvg/SVG/flags/LU.tsx +18 -18
- package/iconsvg/SVG/flags/NL.tsx +18 -18
- package/iconsvg/SVG/flags/NO.tsx +20 -20
- package/iconsvg/SVG/flags/PL.tsx +19 -19
- package/iconsvg/SVG/flags/RO.tsx +20 -20
- package/iconsvg/SVG/flags/RU.tsx +20 -20
- package/iconsvg/SVG/flags/SE.tsx +20 -20
- package/iconsvg/SVG/flags/SI.tsx +54 -54
- package/iconsvg/SVG/flags/SK.tsx +34 -34
- package/iconsvg/SVG/flags/UA.tsx +19 -19
- package/iconsvg/SVG/infoBlocks/14DaysReturnPolicy.tsx +18 -18
- package/iconsvg/SVG/infoBlocks/AlertInfo.tsx +19 -19
- package/iconsvg/SVG/infoBlocks/Autocheck.tsx +19 -19
- package/iconsvg/SVG/infoBlocks/CheckTheStory.tsx +22 -22
- package/iconsvg/SVG/infoBlocks/CustomerServiceWhite.tsx +16 -16
- package/iconsvg/SVG/infoBlocks/Guarantee.tsx +16 -16
- package/iconsvg/SVG/infoBlocks/OrderWhite.tsx +13 -13
- package/iconsvg/SVG/infoBlocks/PriceGuarantee.tsx +19 -19
- package/iconsvg/SVG/infoBlocks/PriceGuaranteeWhite.tsx +17 -17
- package/iconsvg/SVG/infoBlocks/TransportAndDelivery.tsx +21 -21
- package/iconsvg/SVG/infoBlocks/Warranty.tsx +23 -23
- package/iconsvg/SVG/popower/Mail.tsx +18 -18
- package/iconsvg/SVG/popower/Phone.tsx +19 -19
- package/iconsvg/SVG/popower/Schedule.tsx +18 -18
- package/iconsvg/SVG/searchWidgets/drive/AAllWheelDrive.tsx +26 -26
- package/iconsvg/SVG/searchWidgets/drive/AllWheelDrive.tsx +26 -26
- package/iconsvg/SVG/searchWidgets/drive/FrontWheelDrive.tsx +25 -25
- package/iconsvg/SVG/searchWidgets/drive/OtherWheelDrive.tsx +26 -26
- package/iconsvg/SVG/searchWidgets/drive/RearWheelDrive.tsx +25 -25
- package/iconsvg/SVG/searchWidgets/fuel/FuelDiesel.tsx +18 -18
- package/iconsvg/SVG/searchWidgets/fuel/FuelElectrical.tsx +19 -19
- package/iconsvg/SVG/searchWidgets/fuel/FuelElectricalDiesel.tsx +34 -34
- package/iconsvg/SVG/searchWidgets/fuel/FuelElectricalPetrol.tsx +20 -20
- package/iconsvg/SVG/searchWidgets/fuel/FuelEthanol.tsx +53 -53
- package/iconsvg/SVG/searchWidgets/fuel/FuelHydrogen.tsx +24 -24
- package/iconsvg/SVG/searchWidgets/fuel/FuelLpg.tsx +24 -24
- package/iconsvg/SVG/searchWidgets/fuel/FuelNaturalGas.tsx +23 -23
- package/iconsvg/SVG/searchWidgets/fuel/FuelOther.tsx +28 -28
- package/iconsvg/SVG/searchWidgets/fuel/FuelPetrol.tsx +18 -18
- package/iconsvg/SVG/settings/Account.tsx +17 -17
- package/iconsvg/SVG/settings/DataUsage.tsx +17 -17
- package/iconsvg/SVG/settings/MarketResearch.tsx +17 -17
- package/iconsvg/SVG/settings/Newsletter.tsx +17 -17
- package/iconsvg/SVG/settings/RemoveEye.tsx +17 -17
- package/iconsvg/SVG/settings/RemoveEyeOff.tsx +17 -17
- package/iconsvg/SVG/settings/Security.tsx +17 -17
- package/iconsvg/SVG/settings/Warning.tsx +17 -17
- package/iconsvg/SVG/slider/360.tsx +23 -23
- package/iconsvg/SVG/slider/360New.tsx +20 -20
- package/iconsvg/SVG/slider/Checked.tsx +19 -19
- package/iconsvg/SVG/slider/DiscountRibbon.tsx +51 -51
- package/iconsvg/SVG/slider/DiscountRibbonMobile.tsx +47 -47
- package/iconsvg/SVG/slider/DiscountRibbonNew.tsx +29 -29
- package/iconsvg/SVG/slider/Easy.tsx +19 -19
- package/iconsvg/SVG/slider/Fullscreen.tsx +16 -16
- package/iconsvg/SVG/slider/FullscreenWindow.tsx +23 -23
- package/iconsvg/SVG/slider/Safe.tsx +19 -19
- package/iconsvg/SVG/slider/ToBuy.tsx +19 -19
- package/iconsvg/SVG/slider/YoutubeButton.tsx +26 -26
- package/iconsvg/SVG/slider/ZoomIn.tsx +21 -21
- package/iconsvg/SVG/slider/ZoomOut.tsx +21 -21
- package/iconsvg/SVG/social/AndroidLogo.tsx +18 -18
- package/iconsvg/SVG/social/Apple.tsx +19 -19
- package/iconsvg/SVG/social/FacebookF.tsx +19 -19
- package/iconsvg/SVG/social/GooglePlusG.tsx +19 -19
- package/iconsvg/SVG/social/Instagram.tsx +17 -17
- package/iconsvg/SVG/social/Pinterest.tsx +19 -19
- package/iconsvg/SVG/social/SharingInterface.tsx +21 -21
- package/iconsvg/SVG/social/Twitter.tsx +19 -19
- package/iconsvg/SVG/social/Youtube.tsx +19 -19
- package/iconsvg/SVG/vehicle/AboIcon.tsx +11 -11
- package/iconsvg/SVG/vehicle/Abs.tsx +24 -24
- package/iconsvg/SVG/vehicle/AirCond.tsx +34 -34
- package/iconsvg/SVG/vehicle/Airbag.tsx +21 -21
- package/iconsvg/SVG/vehicle/AuxiliaryHeating.tsx +23 -23
- package/iconsvg/SVG/vehicle/Bluetooth.tsx +22 -22
- package/iconsvg/SVG/vehicle/BuyIcon.tsx +15 -15
- package/iconsvg/SVG/vehicle/CarAvailability.tsx +22 -22
- package/iconsvg/SVG/vehicle/CarInspectionCheck.tsx +21 -21
- package/iconsvg/SVG/vehicle/CarInspectionCross.tsx +21 -21
- package/iconsvg/SVG/vehicle/CheckoutChecked.tsx +15 -15
- package/iconsvg/SVG/vehicle/Co2.tsx +24 -24
- package/iconsvg/SVG/vehicle/CruiseControl.tsx +25 -25
- package/iconsvg/SVG/vehicle/Date.tsx +21 -21
- package/iconsvg/SVG/vehicle/Delivery.tsx +12 -12
- package/iconsvg/SVG/vehicle/Diesel.tsx +28 -28
- package/iconsvg/SVG/vehicle/Display.tsx +25 -25
- package/iconsvg/SVG/vehicle/Done.tsx +11 -11
- package/iconsvg/SVG/vehicle/Door.tsx +19 -19
- package/iconsvg/SVG/vehicle/DoubleDone.tsx +18 -18
- package/iconsvg/SVG/vehicle/EditIcon.tsx +11 -11
- package/iconsvg/SVG/vehicle/EmergencyBrakeAssistant.tsx +27 -27
- package/iconsvg/SVG/vehicle/Eps.tsx +24 -24
- package/iconsvg/SVG/vehicle/Esp.tsx +24 -24
- package/iconsvg/SVG/vehicle/FinancingIcon.tsx +20 -20
- package/iconsvg/SVG/vehicle/FuelConsumption.tsx +20 -20
- package/iconsvg/SVG/vehicle/Fueling.tsx +22 -22
- package/iconsvg/SVG/vehicle/FullDrive.tsx +24 -24
- package/iconsvg/SVG/vehicle/GasElectric.tsx +28 -28
- package/iconsvg/SVG/vehicle/HandsFreePhoneSystem.tsx +24 -24
- package/iconsvg/SVG/vehicle/Kw.tsx +23 -23
- package/iconsvg/SVG/vehicle/LastCrawledAt.tsx +22 -22
- package/iconsvg/SVG/vehicle/LeasingIcon.tsx +14 -14
- package/iconsvg/SVG/vehicle/Led.tsx +24 -24
- package/iconsvg/SVG/vehicle/LightSensor.tsx +22 -22
- package/iconsvg/SVG/vehicle/LinkAlternative.tsx +15 -15
- package/iconsvg/SVG/vehicle/Location.tsx +17 -17
- package/iconsvg/SVG/vehicle/MinusIcon.tsx +11 -11
- package/iconsvg/SVG/vehicle/Mirror.tsx +19 -19
- package/iconsvg/SVG/vehicle/Navigation.tsx +27 -27
- package/iconsvg/SVG/vehicle/NewCar.tsx +21 -21
- package/iconsvg/SVG/vehicle/NoImage.tsx +17 -17
- package/iconsvg/SVG/vehicle/Owner.tsx +18 -18
- package/iconsvg/SVG/vehicle/PanoramicRoof.tsx +23 -23
- package/iconsvg/SVG/vehicle/ParkingAssistants.tsx +24 -24
- package/iconsvg/SVG/vehicle/PickYourself.tsx +18 -18
- package/iconsvg/SVG/vehicle/PlusIcon.tsx +11 -11
- package/iconsvg/SVG/vehicle/Power.tsx +21 -21
- package/iconsvg/SVG/vehicle/Ps.tsx +19 -19
- package/iconsvg/SVG/vehicle/Question.tsx +24 -24
- package/iconsvg/SVG/vehicle/Seats.tsx +21 -21
- package/iconsvg/SVG/vehicle/SeatsHeating.tsx +26 -26
- package/iconsvg/SVG/vehicle/SelectorGearboxAutomatic.tsx +24 -24
- package/iconsvg/SVG/vehicle/SelectorGearboxManualShift.tsx +19 -19
- package/iconsvg/SVG/vehicle/SelectorGearboxOther.tsx +24 -24
- package/iconsvg/SVG/vehicle/SelectorGearboxSemiAutomatic.tsx +30 -30
- package/iconsvg/SVG/vehicle/SelectorInteriorTypeAlcantara.tsx +225 -225
- package/iconsvg/SVG/vehicle/SelectorInteriorTypeFabric.tsx +29 -29
- package/iconsvg/SVG/vehicle/SelectorInteriorTypeFullLeather.tsx +29 -29
- package/iconsvg/SVG/vehicle/SelectorInteriorTypeOther.tsx +26 -26
- package/iconsvg/SVG/vehicle/SelectorInteriorTypePartLeather.tsx +142 -142
- package/iconsvg/SVG/vehicle/SelectorInteriorTypeSyntheticLeather.tsx +27 -27
- package/iconsvg/SVG/vehicle/SelectorInteriorTypeVelours.tsx +39 -39
- package/iconsvg/SVG/vehicle/Shield.tsx +39 -39
- package/iconsvg/SVG/vehicle/Speedometer.tsx +17 -17
- package/iconsvg/SVG/vehicle/StartStopSystem.tsx +30 -30
- package/iconsvg/SVG/vehicle/Stop.tsx +25 -25
- package/iconsvg/SVG/vehicle/TickMark.tsx +21 -21
- package/iconsvg/SVG/vehicle/TrafficSignRecognition.tsx +29 -29
- package/iconsvg/SVG/vehicle/TrailerCoupling.tsx +24 -24
- package/iconsvg/SVG/vehicle/Transmission.tsx +27 -27
- package/iconsvg/SVG/vehicle/Wheel.tsx +43 -43
- package/iconsvg/SVG/vehicle/Wipers.tsx +22 -22
- package/iconsvg/SVG/vehicle/Wrench.tsx +17 -17
- package/iconsvg/index.ts +7 -7
- package/index.ts +18 -18
- package/locales/de/autobahn.json +676 -671
- package/locales/en/autobahn.json +676 -671
- package/locales/legacy/SearchDetailedPage.ts +205 -205
- package/locales/legacy/cbd.ts +719 -719
- package/locales/legacy/common.ts +109 -109
- package/locales/legacy/data.ts +1118 -1118
- package/locales/legacy/priceRating.ts +10 -10
- package/locales/legacy/sortingOptions.ts +21 -21
- package/media/images/raiting-stars-min.svg +7 -7
- package/media/images/refresh-button.svg +49 -49
- package/media/images/user-icon.svg +16 -16
- package/media/svg/infoBlocks/whyAutodeIconSet-F.svg +9 -9
- package/media/svg/infoBlocks/whyAutodeIconSet-G.svg +8 -8
- package/media/svg/infoBlocks/whyAutodeIconSet-Q.svg +6 -6
- package/media/svg/infoBlocks/whyAutodeIconSet-R.svg +9 -9
- package/media/svg/usp/icon1.svg +16 -16
- package/media/svg/usp/icon2.svg +13 -13
- package/media/svg/usp/icon3.svg +10 -10
- package/media/svg/usp/icon4.svg +14 -14
- package/package.json +30 -30
- package/schemes/AggregationScheme.ts +73 -73
- package/searchFilters/filterOptions.ts +119 -119
- package/searchFilters/filterProps.ts +35 -35
- package/searchFilters/index.ts +15 -15
- package/theme/autobahn.css +25 -25
- package/theme/colors_and_type.css +113 -113
- package/theme/md3.css +2045 -2034
- package/types/types.ts +373 -373
- package/types.ts +8 -8
- package/ui/Accordion.tsx +134 -134
- package/ui/Button.tsx +62 -62
- package/ui/CardCarousel.tsx +133 -133
- package/ui/Chip.tsx +29 -29
- package/ui/DatePicker.tsx +145 -145
- package/ui/Dropdown.tsx +205 -205
- package/ui/FileUpload.tsx +154 -154
- package/ui/FormCheckbox.tsx +79 -79
- package/ui/FormDropdown.tsx +327 -327
- package/ui/FormField.tsx +88 -88
- package/ui/FormRadio.tsx +93 -93
- package/ui/FormRadioGroup.tsx +106 -106
- package/ui/Icon.tsx +391 -391
- package/ui/IconButton.tsx +44 -44
- package/ui/Modal.tsx +187 -187
- package/ui/Pagination.tsx +140 -140
- package/ui/Price.tsx +25 -25
- package/ui/PriceEvalBar.tsx +48 -48
- package/ui/SaveChip.tsx +34 -34
- package/ui/Segmented.tsx +48 -48
- package/ui/Skeleton.tsx +75 -75
- package/ui/Spec.tsx +24 -24
- package/ui/Stars.tsx +29 -29
- package/ui/StatChip.tsx +21 -21
- package/ui/Stepper.tsx +106 -106
- package/ui/Switch.tsx +65 -65
- package/ui/Table.tsx +156 -156
- package/ui/Textarea.tsx +58 -58
- package/ui/index.ts +88 -88
- package/utils/CommonUtils.ts +648 -648
- package/utils/DateUtils.ts +101 -101
- package/utils/index.ts +74 -74
- package/utils/power.ts +11 -11
- package/utils/query.ts +21 -21
- package/vdp/FinanceCalculator.tsx +465 -465
- package/vdp/VdpModules.tsx +1490 -1490
- package/vdp/VdpViewer.tsx +209 -209
- package/vdp/index.ts +75 -75
- package/vdp/types.ts +197 -197
- package/vehiclesProps/cbdSelectors.ts +117 -117
- package/vehiclesProps/decoratedLightProps.tsx +572 -572
- package/vehiclesProps/decoratedProps.tsx +1746 -1746
- package/vehiclesProps/equipment.ts +129 -129
- package/vehiclesProps/vehicleDetails.ts +428 -428
- package/widgets/SearchBox.tsx +256 -256
- package/widgets/index.ts +5 -5
package/utils/CommonUtils.ts
CHANGED
|
@@ -1,649 +1,649 @@
|
|
|
1
|
-
import qs from 'qs';
|
|
2
|
-
import _get from 'lodash/get';
|
|
3
|
-
import { formatLocale as d3formatLocale } from 'd3-format';
|
|
4
|
-
import Cookies from 'js-cookie';
|
|
5
|
-
import {
|
|
6
|
-
FIRST_REGISTRATION, MANUFACTURER, MILEAGE, MODEL, BODY_TYPE, PRICE, RATE,
|
|
7
|
-
DROP_DOWN_GROUP, RATE_DEFAULT, MMS_GROUPS_KEY, MMS_GROUP_FIELDS
|
|
8
|
-
} from '../constants/SearchWidget';
|
|
9
|
-
import { priceRatings, priceRatingConfig } from '../constants/price';
|
|
10
|
-
import { HUNDRED } from '../constants/common';
|
|
11
|
-
import { offers, PREDICTABLE_PRICE_INDEX } from '../constants/core';
|
|
12
|
-
import { FILTERS_IN_TITLE, MANUFACTURER_KEY, MAX_FILTERS_IN_TITLE, MODEL_KEY } from '../constants/Search';
|
|
13
|
-
import { isArray } from 'lodash';
|
|
14
|
-
|
|
15
|
-
const PRICE_DEFAULT = DROP_DOWN_GROUP[PRICE].defaultValue;
|
|
16
|
-
|
|
17
|
-
declare global {
|
|
18
|
-
// tslint:disable-next-line:interface-name
|
|
19
|
-
interface Window {
|
|
20
|
-
grantCookieConsentSentry?: () => void;
|
|
21
|
-
grantCookieConsent?: (disabledCookies: string[]) => void;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export const formatMileage = (millage: number | string) => {
|
|
26
|
-
return millage.toLocaleString('en-US').replace(/,/g, '.');
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
export const getFormattedNumber = (num: number) => Number.isFinite(num) ? num.toLocaleString('de-DE') : null;
|
|
30
|
-
|
|
31
|
-
export const numberWithDot = (value: number | string) => {
|
|
32
|
-
switch (value) {
|
|
33
|
-
case 'any':
|
|
34
|
-
return value;
|
|
35
|
-
case 'beliebig':
|
|
36
|
-
return value;
|
|
37
|
-
default: return getFormattedNumber(+value);
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export const arrToObj = (arr: string[]): { [key: string]: boolean } => {
|
|
42
|
-
if (!Array.isArray(arr)) return {};
|
|
43
|
-
return arr.reduce(
|
|
44
|
-
(obj: { [key: string]: boolean }, el: string) => { obj[el] = true; return obj; }, {}
|
|
45
|
-
);
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
export const addPrefixToKeys = (obj: { [key: string]: any }, prefix: string) => {
|
|
49
|
-
const result: { [key: string]: any } = {};
|
|
50
|
-
Object.keys(obj).reduce((_, key) => {
|
|
51
|
-
result[`${prefix}_${key}`] = obj[key];
|
|
52
|
-
return result;
|
|
53
|
-
}, result); // tslint:disable-line:align
|
|
54
|
-
return result;
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
// function return list of filter for inject in title
|
|
58
|
-
export const filtersInTitle = (filters: any) => {
|
|
59
|
-
const result: any[] = [];
|
|
60
|
-
const pushInResult = (value: any) => {
|
|
61
|
-
if (result.length < MAX_FILTERS_IN_TITLE && value) {
|
|
62
|
-
result.push(value);
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
FILTERS_IN_TITLE.forEach((filter: string) => {
|
|
67
|
-
if (filter === MMS_GROUPS_KEY) {
|
|
68
|
-
filters.get(filter).forEach((MmsObject: any) => {
|
|
69
|
-
pushInResult(MmsObject[MANUFACTURER_KEY].value);
|
|
70
|
-
pushInResult(MmsObject[MODEL_KEY].value);
|
|
71
|
-
});
|
|
72
|
-
} else {
|
|
73
|
-
filters.get(filter).value.forEach((value: string) => {
|
|
74
|
-
pushInResult(value);
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
return result;
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
export const changeLocation = (path: string) =>
|
|
82
|
-
window.location.href = `${window.location.origin}/${path}`;
|
|
83
|
-
|
|
84
|
-
export const checkRangeValuesOnEqual = (defaultValues: any, filterValues: any) => {
|
|
85
|
-
const keys = Object.keys(defaultValues);
|
|
86
|
-
let valuesIsEqual = true;
|
|
87
|
-
for (let i = 0; i < keys.length; i += 1) {
|
|
88
|
-
const period = keys[i];
|
|
89
|
-
|
|
90
|
-
if (filterValues[period] !== defaultValues[period]) {
|
|
91
|
-
valuesIsEqual = false;
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return valuesIsEqual;
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
export interface ICarImage {
|
|
100
|
-
url?: string;
|
|
101
|
-
imageUrlSmall?: string;
|
|
102
|
-
imageUrlMedium?: string;
|
|
103
|
-
imageUrlLarge?: string;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export const preloadNearbyImages = (images: ICarImage[], activeIndex: number, imageUrlSize: 'imageUrlSmall' | 'imageUrlMedium' | 'imageUrlLarge') => {
|
|
107
|
-
const imagesCount = Array.isArray(images) ? images.length : 0;
|
|
108
|
-
const imageSize = imageUrlSize;
|
|
109
|
-
|
|
110
|
-
const inMemoryPrevImage = new Image();
|
|
111
|
-
const inMemoryNextImage = new Image();
|
|
112
|
-
|
|
113
|
-
if (!!imagesCount) {
|
|
114
|
-
const prevIndex = (activeIndex - 1 % imagesCount + imagesCount) % imagesCount;
|
|
115
|
-
const nextIndex = (activeIndex + 1 % imagesCount + imagesCount) % imagesCount;
|
|
116
|
-
|
|
117
|
-
inMemoryPrevImage.src = images[prevIndex][imageSize];
|
|
118
|
-
inMemoryNextImage.src = images[nextIndex][imageSize];
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
export const getGroupValuesForQuery = (groups: any) => {
|
|
123
|
-
const arr: any = [];
|
|
124
|
-
groups.map((group: any) => {
|
|
125
|
-
const groupObj: any = {};
|
|
126
|
-
|
|
127
|
-
Object.keys(group).forEach((key: string) => {
|
|
128
|
-
const item = group[key];
|
|
129
|
-
if (item.value) {
|
|
130
|
-
groupObj[key] = item.value;
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
if (Object.keys(groupObj).length) {
|
|
134
|
-
arr.push(groupObj);
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
return arr;
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
export const buildBodyForRequest = (state: any) => {
|
|
141
|
-
const query: any = {
|
|
142
|
-
filters: {
|
|
143
|
-
absolutValues: {
|
|
144
|
-
mmsGroup0: {}
|
|
145
|
-
},
|
|
146
|
-
noAbsolutValues: {},
|
|
147
|
-
rangeValues: {}
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
Object.keys(state).sort().forEach((key: string) => {
|
|
152
|
-
const value = state[key];
|
|
153
|
-
|
|
154
|
-
if (!value) return;
|
|
155
|
-
|
|
156
|
-
if (key === MANUFACTURER && value.value) {
|
|
157
|
-
query.filters.absolutValues.mmsGroup0.mainData_make = value.value;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
if (key === MODEL && value.value) {
|
|
161
|
-
if (value.isSeries) {
|
|
162
|
-
query.filters.absolutValues.mmsGroup0.mainData_series = value.value;
|
|
163
|
-
} else {
|
|
164
|
-
query.filters.absolutValues.mmsGroup0.mainData_model = value.value;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
if (key === BODY_TYPE && value.length) {
|
|
169
|
-
query.filters.noAbsolutValues[BODY_TYPE] = value;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if (key === FIRST_REGISTRATION && value.value) {
|
|
173
|
-
query.filters.rangeValues['mainData_firstRegistrationYear'] = { from: value.value };
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
if (key === MILEAGE && value.value) {
|
|
177
|
-
query.filters.rangeValues['mainData_mileage'] = { to: value.value };
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
if (key === PRICE) {
|
|
181
|
-
const valueIsEqual = checkRangeValuesOnEqual(PRICE_DEFAULT, value);
|
|
182
|
-
|
|
183
|
-
if (!valueIsEqual) {
|
|
184
|
-
// check value in from / to. If we have - add it
|
|
185
|
-
Object.keys(value).map((key: string) => {
|
|
186
|
-
if (value[key]) {
|
|
187
|
-
if (!query.filters.rangeValues['price_currentSalesPrice']) {
|
|
188
|
-
query.filters.rangeValues['price_currentSalesPrice'] = {};
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
query.filters.rangeValues['price_currentSalesPrice'][key] = value[key];
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
if (key === RATE) {
|
|
198
|
-
const isRateDefault = checkRangeValuesOnEqual(RATE_DEFAULT, value);
|
|
199
|
-
|
|
200
|
-
if (!isRateDefault) {
|
|
201
|
-
query.filters.rangeValues['price_currentSalesPrice'] = { from: 1000, to: 2000 };
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
return query;
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
export const buildQueryForSearch = (filters: any) => {
|
|
210
|
-
const query: { [key: string]: any } = {};
|
|
211
|
-
const MMS_GROUP: any = {};
|
|
212
|
-
|
|
213
|
-
Object.keys(filters).forEach((filter: string) => {
|
|
214
|
-
const filterValue = filters[filter];
|
|
215
|
-
|
|
216
|
-
if (filterValue && filterValue.value) {
|
|
217
|
-
if (MMS_GROUP_FIELDS.indexOf(filter) !== -1) {
|
|
218
|
-
|
|
219
|
-
if (filterValue.isSeries) {
|
|
220
|
-
MMS_GROUP.SERIES = filterValue.value;
|
|
221
|
-
} else {
|
|
222
|
-
MMS_GROUP[filter] = filterValue.value;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
if (filterValue === PRICE) {
|
|
228
|
-
const defaultValue = DROP_DOWN_GROUP[filter].defaultValue;
|
|
229
|
-
const valueIsDefault = filter === PRICE ? checkRangeValuesOnEqual(defaultValue, filterValue) : filterValue === defaultValue;
|
|
230
|
-
|
|
231
|
-
if (!valueIsDefault) {// check value in from / to. If we have - add it
|
|
232
|
-
Object.keys(filterValue).map((key: string) => {
|
|
233
|
-
if (filterValue[key]) {
|
|
234
|
-
if (!query.filters.rangeValues['price_currentSalesPrice']) {
|
|
235
|
-
query.filters.rangeValues['price_currentSalesPrice'] = {};
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
query.filters.rangeValues['price_currentSalesPrice'][key] = filterValue[key];
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
if (filter === PRICE) {
|
|
245
|
-
const valueIsDefault = checkRangeValuesOnEqual(PRICE_DEFAULT, filterValue);
|
|
246
|
-
|
|
247
|
-
if (!valueIsDefault) {
|
|
248
|
-
query[PRICE] = { from: '', to: '' };
|
|
249
|
-
query[PRICE].from = _get(filterValue, 'from', '');
|
|
250
|
-
query[PRICE].to = _get(filterValue, 'to', '');
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
if (filter === RATE) {
|
|
255
|
-
const isRateDefault = checkRangeValuesOnEqual(RATE_DEFAULT, filterValue);
|
|
256
|
-
|
|
257
|
-
if (!isRateDefault) {
|
|
258
|
-
query[RATE] = filterValue;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
if (filter === MILEAGE) {
|
|
263
|
-
const defaultValue = DROP_DOWN_GROUP[filter].defaultValue;
|
|
264
|
-
if (filterValue !== defaultValue) {
|
|
265
|
-
query[MILEAGE] = { from: '', to: '' };
|
|
266
|
-
query[MILEAGE].from = _get(filterValue, 'from', '');
|
|
267
|
-
query[MILEAGE].to = _get(filterValue, 'to', '') || _get(filterValue, 'value', '');
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
if (filter === FIRST_REGISTRATION) {
|
|
272
|
-
const defaultValue = DROP_DOWN_GROUP[filter].defaultValue;
|
|
273
|
-
if (filterValue !== defaultValue) {
|
|
274
|
-
query[FIRST_REGISTRATION] = { from: '', to: '' };
|
|
275
|
-
query[FIRST_REGISTRATION].from = _get(filterValue, 'from', '') || _get(filterValue, 'value', '');
|
|
276
|
-
query[FIRST_REGISTRATION].to = _get(filterValue, 'to', '');
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
if (filter === BODY_TYPE) {
|
|
281
|
-
const defaultValue = DROP_DOWN_GROUP[filter].defaultValue;
|
|
282
|
-
|
|
283
|
-
if (filterValue.length && filterValue !== defaultValue) {
|
|
284
|
-
query[BODY_TYPE] = [];
|
|
285
|
-
|
|
286
|
-
filterValue.map((bodyTypeSelector: string) => {
|
|
287
|
-
query[BODY_TYPE].push(bodyTypeSelector);
|
|
288
|
-
});
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
if (Object.keys(MMS_GROUP).length) {
|
|
294
|
-
query[MMS_GROUPS_KEY] = [];
|
|
295
|
-
query[MMS_GROUPS_KEY].push(MMS_GROUP);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
return qs.stringify(query, { encode: false });
|
|
299
|
-
};
|
|
300
|
-
|
|
301
|
-
export const sliceLessThan = (array: number[], to: any): number[] => {
|
|
302
|
-
const value = Number(to);
|
|
303
|
-
return value && Number.isFinite(value)
|
|
304
|
-
? array.filter((val: number) => val <= value)
|
|
305
|
-
: array;
|
|
306
|
-
};
|
|
307
|
-
|
|
308
|
-
export const sliceMoreThan = (array: number[], from: any): number[] => {
|
|
309
|
-
const value = Number(from);
|
|
310
|
-
return value && Number.isFinite(value)
|
|
311
|
-
? array.filter((val: number) => val >= value)
|
|
312
|
-
: array;
|
|
313
|
-
};
|
|
314
|
-
|
|
315
|
-
export const getFormattedPrice = (price: number, format = '$,.0f', currency = '', currencyPrefix = ''): string => {
|
|
316
|
-
if (!Number.isFinite(price)) return '-';
|
|
317
|
-
const groupingNum = 3;
|
|
318
|
-
return d3formatLocale({
|
|
319
|
-
decimal: ',',
|
|
320
|
-
thousands: '.',
|
|
321
|
-
currency: [currencyPrefix, currency],
|
|
322
|
-
grouping: [groupingNum]
|
|
323
|
-
}).format(format)(price);
|
|
324
|
-
};
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
export const getPriceRatingConfig = (currentPrice: number, pricePredicted: number) => { // tslint:disable-line
|
|
328
|
-
const round = (value: number) => {
|
|
329
|
-
return Number.isFinite(pricePredicted)
|
|
330
|
-
? Math.round((pricePredicted * (1 + (value / 100))) / 100) * 100 // tslint:disable-line
|
|
331
|
-
: '???';
|
|
332
|
-
};
|
|
333
|
-
|
|
334
|
-
if (currentPrice === 0) {
|
|
335
|
-
console.log('Empty current price');
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
return Object.keys(priceRatingConfig).reduce((acc: any, key: any) => {
|
|
339
|
-
const { min, max } = priceRatingConfig[key];
|
|
340
|
-
return { ...acc, [key]: { min: round(min), max: round(max) } };
|
|
341
|
-
}, {}); // tslint:disable-line
|
|
342
|
-
};
|
|
343
|
-
|
|
344
|
-
export const getPredictablePrice = (currentSalesPrice: number, predictablePrice: number) => {
|
|
345
|
-
if (Number.isFinite(Number.parseFloat(`${predictablePrice}`))) {
|
|
346
|
-
return predictablePrice;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
return currentSalesPrice * PREDICTABLE_PRICE_INDEX;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
export const getPriceRating = (currentSalesPrice: number, predictablePrice: number) => {
|
|
353
|
-
const isCorrectCurrentSalesPrice = Number.isFinite(Number.parseFloat(`${currentSalesPrice}`));
|
|
354
|
-
// const isCorrectPredictablePrice = Number.isFinite(Number.parseFloat(`${predictablePrice}`));
|
|
355
|
-
|
|
356
|
-
if (!isCorrectCurrentSalesPrice) return 0;
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
const validatedPredictablePrice = getPredictablePrice(currentSalesPrice, predictablePrice);
|
|
360
|
-
|
|
361
|
-
const ratingConfig = getPriceRatingConfig(currentSalesPrice, validatedPredictablePrice);
|
|
362
|
-
|
|
363
|
-
for (const key of Object.keys(ratingConfig)) {
|
|
364
|
-
const { min, max } = ratingConfig[key];
|
|
365
|
-
const TOP_PRICE = 5;
|
|
366
|
-
if (key === 'highPrice' && currentSalesPrice === max) return 1;
|
|
367
|
-
if (key === 'topPrice' && currentSalesPrice <= min) return TOP_PRICE;
|
|
368
|
-
if (currentSalesPrice >= min && currentSalesPrice < max) return priceRatings.indexOf(key);
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
return 0;
|
|
372
|
-
};
|
|
373
|
-
|
|
374
|
-
export const fixNumber = (num: number | string) => {
|
|
375
|
-
const isNum = typeof num === 'number' ? num : parseFloat(num);
|
|
376
|
-
return Math.round(isNum * HUNDRED) / HUNDRED;
|
|
377
|
-
};
|
|
378
|
-
|
|
379
|
-
export const getOfferSliders = (financingConfig: any, t: (key: string, options?: object) => string, priceTabIndex: null | number, componentType: string) => {
|
|
380
|
-
const offerObj = offers[+priceTabIndex];
|
|
381
|
-
const offerConfig = financingConfig[offerObj.name];
|
|
382
|
-
const currentSalesPrice =
|
|
383
|
-
financingConfig.common ?
|
|
384
|
-
financingConfig.common.currentSalesPrice :
|
|
385
|
-
financingConfig.currentSalesPrice; // TODO: fix deprecated. Correct is "financingConfig.common.currentSalesPrice"
|
|
386
|
-
if (isArray(offerObj.sliders)) {
|
|
387
|
-
const sliders: any = offerObj.sliders;
|
|
388
|
-
return sliders
|
|
389
|
-
.map((slider: any, index: number) => {
|
|
390
|
-
if (componentType === 'checkout' && index === 1 && priceTabIndex === 0) return; // remove checkout annual mileage for financing
|
|
391
|
-
if (slider.name === 'firstInstallment') slider.max = offerConfig.firstInstallmentMax || currentSalesPrice;
|
|
392
|
-
slider.value = offerConfig[slider.name];
|
|
393
|
-
slider.unitName = t(`modals:financing.${slider.unit}`);
|
|
394
|
-
slider.caption = t(`modals:financing.${slider.name}`);
|
|
395
|
-
return slider;
|
|
396
|
-
}).filter(Boolean);
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
};
|
|
400
|
-
|
|
401
|
-
export const checkWebpFeature = async () => {
|
|
402
|
-
// If the browser doesn't has the method createImageBitmap, you can't display webp format
|
|
403
|
-
if (!self.createImageBitmap) return false;
|
|
404
|
-
|
|
405
|
-
// Base64 representation of a white point image
|
|
406
|
-
const webpData = 'data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoCAAEAAQAcJaQAA3AA/v3AgAA=';
|
|
407
|
-
|
|
408
|
-
// Retrieve the Image in Blob Format
|
|
409
|
-
const blob = await fetch(webpData).then(r => r.blob());
|
|
410
|
-
|
|
411
|
-
// If the createImageBitmap method succeeds, return true, otherwise false
|
|
412
|
-
return createImageBitmap(blob).then(() => true, () => false);
|
|
413
|
-
};
|
|
414
|
-
|
|
415
|
-
export const getSupportedImageFormat = (IMAGE_URL: string, vehicleID: string, imageIdentifier: string, size: 'small' | 'medium' | 'large', webpFeature: boolean) => {
|
|
416
|
-
if (!imageIdentifier) return null;
|
|
417
|
-
|
|
418
|
-
const vehicleImageURL = `${IMAGE_URL}/${vehicleID}/${imageIdentifier}`;
|
|
419
|
-
|
|
420
|
-
return webpFeature ? `${vehicleImageURL}/${size}-cached.webp` : `${vehicleImageURL}/${size}-cached.jpeg`;
|
|
421
|
-
};
|
|
422
|
-
|
|
423
|
-
export function getChipFilterValue(
|
|
424
|
-
chip: any,
|
|
425
|
-
// Fallback keeps the function usable without an i18n instance: it returns the
|
|
426
|
-
// raw key. (The former fe-ui-core German-dictionary fallback was dropped when
|
|
427
|
-
// this module moved to @bytebrand/fe-ui-core-autobahn so the locale tree could
|
|
428
|
-
// stay behind — every real call site passes `t` explicitly.)
|
|
429
|
-
t: (key: string, options?: object) => string = (phrase: string, _?: object) => phrase,
|
|
430
|
-
language: string = 'de'
|
|
431
|
-
) {
|
|
432
|
-
let filterValue: string;
|
|
433
|
-
let title: string;
|
|
434
|
-
let from: string;
|
|
435
|
-
let to: string;
|
|
436
|
-
const chipFilterKey = chip.filterKey || chip.key; // we may have different key naming for landing or main
|
|
437
|
-
const chipFilterValue = chip.filterValue || chip.value; // we may have different key naming for landing or main
|
|
438
|
-
switch (chipFilterKey) {
|
|
439
|
-
case 'MANUFACTURER':
|
|
440
|
-
case 'MODEL':
|
|
441
|
-
case 'SUB_MODEL':
|
|
442
|
-
case 'SERIES':
|
|
443
|
-
filterValue = chipFilterValue;
|
|
444
|
-
break;
|
|
445
|
-
|
|
446
|
-
case 'MANUFACTURER_EXCLUDE':
|
|
447
|
-
case 'MODEL_EXCLUDE':
|
|
448
|
-
title = t(`SearchPage:filters.${chipFilterKey.toLocaleLowerCase()}`);
|
|
449
|
-
filterValue = `${title} ${chipFilterValue}`;
|
|
450
|
-
break;
|
|
451
|
-
|
|
452
|
-
case 'FIRST_REGISTRATION':
|
|
453
|
-
title = t(`SearchPage:filters.${chipFilterKey.toLocaleLowerCase()}`);
|
|
454
|
-
from = chipFilterValue.from ? `${t('SearchPage:filters.from')} ${chipFilterValue.from} ` : '';
|
|
455
|
-
to = chipFilterValue.to ? `${t('SearchPage:filters.to')} ${chipFilterValue.to}` : '';
|
|
456
|
-
filterValue = `${title} ${from} ${to}`;
|
|
457
|
-
break;
|
|
458
|
-
|
|
459
|
-
case 'PRICE':
|
|
460
|
-
case 'PRICE_DIFFERENCE':
|
|
461
|
-
case 'MILEAGE':
|
|
462
|
-
case 'EMISSION_CO2':
|
|
463
|
-
case 'POWER':
|
|
464
|
-
case 'IMAGES_COUNT':
|
|
465
|
-
title = t(`SearchPage:filters.${chipFilterKey.toLocaleLowerCase()}`);
|
|
466
|
-
from = chipFilterValue.from ? `${t('SearchPage:filters.from')} ${getFormattedPrice(+chipFilterValue.from)} ` : '';
|
|
467
|
-
to = chipFilterValue.to ? `${t('SearchPage:filters.to')} ${getFormattedPrice(+chipFilterValue.to)}` : '';
|
|
468
|
-
const type = chipFilterValue.type ? ` ${chipFilterValue.type}` : '';
|
|
469
|
-
filterValue = `${title} ${from} ${to}${type}`;
|
|
470
|
-
break;
|
|
471
|
-
|
|
472
|
-
case 'DOORS':
|
|
473
|
-
case 'OWNERS':
|
|
474
|
-
filterValue = t(`SearchPage:filters.${chipFilterValue}`);
|
|
475
|
-
break;
|
|
476
|
-
|
|
477
|
-
case 'SEATS':
|
|
478
|
-
case 'CUBIC_CAPACITY':
|
|
479
|
-
title = t(`SearchPage:filters.${chipFilterKey.toLocaleLowerCase()}`);
|
|
480
|
-
from = !!chipFilterValue.from ? `${t('SearchPage:filters.from')} ${chipFilterValue.from}` : '';
|
|
481
|
-
to = !!chipFilterValue.to ? `${t('SearchPage:filters.to')} ${chipFilterValue.to}` : '';
|
|
482
|
-
const fromTo = (from && to) ? `${chipFilterValue.from} - ${chipFilterValue.to}` : `${from || to}`;
|
|
483
|
-
filterValue = `${title} ${fromTo}`;
|
|
484
|
-
break;
|
|
485
|
-
|
|
486
|
-
case 'CONSUMPTION':
|
|
487
|
-
const fromValue = Number(chipFilterValue.from).toLocaleString(language);
|
|
488
|
-
const toValue = Number(chipFilterValue.to).toLocaleString(language);
|
|
489
|
-
const newFromValue: any = (fromValue === 'NaN') ? '1' : fromValue;
|
|
490
|
-
const newToValue: any = (toValue === 'NaN') ? '18' : toValue;
|
|
491
|
-
const fromToWithInfo = `${newFromValue} - ${newToValue}`;
|
|
492
|
-
filterValue = t(`SearchPage:filtersChips.${chipFilterKey.toLocaleLowerCase()}`, { value: fromToWithInfo });
|
|
493
|
-
break;
|
|
494
|
-
|
|
495
|
-
case 'ONLINE_SINCE':
|
|
496
|
-
filterValue = t(`SearchPage:filters.${chipFilterValue}`);
|
|
497
|
-
break;
|
|
498
|
-
|
|
499
|
-
case 'GENERAL_INSPECTION':
|
|
500
|
-
filterValue = t(`SearchPage:filtersChips.generalInspection`, { month: t(`SearchPage:filters.${chipFilterValue}`) });
|
|
501
|
-
break;
|
|
502
|
-
|
|
503
|
-
case 'RATE':
|
|
504
|
-
const { monthlyInstallmentFrom, monthlyInstallmentTo, firstInstallment, paybackPeriod } = chipFilterValue;
|
|
505
|
-
const rowValues: any = { monthlyInstallmentFrom, monthlyInstallmentTo, firstInstallment, paybackPeriod };
|
|
506
|
-
const values: string[][] = [
|
|
507
|
-
['monthlyInstallmentFrom', 'monthlyInstallmentTo'],
|
|
508
|
-
['firstInstallment', 'paybackPeriod']
|
|
509
|
-
].map((fields: string[]) => fields
|
|
510
|
-
.map((field: string) => {
|
|
511
|
-
const rowValue = rowValues[field];
|
|
512
|
-
const value = Number.isFinite(+rowValue) ? getFormattedPrice(+rowValue) : rowValue;
|
|
513
|
-
return +rowValue ? t(`SearchPage:filtersChips.${field}Chip`, { value }) : null;
|
|
514
|
-
})
|
|
515
|
-
.filter((item: any) => !!item)
|
|
516
|
-
);
|
|
517
|
-
const rateValue = `${t('SearchPage:filtersChips.rateChip')} ${values[0].length ? values[0].join(' ') : t('SearchPage:filtersChips.any')}`;
|
|
518
|
-
filterValue = `${rateValue}, ${values[1].join(', ')}`;
|
|
519
|
-
break;
|
|
520
|
-
|
|
521
|
-
default:
|
|
522
|
-
filterValue = t(`cbd:${chipFilterValue}`);
|
|
523
|
-
}
|
|
524
|
-
return filterValue;
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
function getUtmQueryParameter() {
|
|
528
|
-
const query = window.location.search;
|
|
529
|
-
|
|
530
|
-
if (!query) { return; }
|
|
531
|
-
|
|
532
|
-
const queryString = /^[?]/.test(query) ? query.slice(1) : query;
|
|
533
|
-
|
|
534
|
-
const result = queryString.split('&').reduce(
|
|
535
|
-
(params: any, param: string) => {
|
|
536
|
-
const [key, value] = param.split('=');
|
|
537
|
-
|
|
538
|
-
if (!/^source|^campaign|^medium|^content|^term|^reference|^gclid|^adgroupid|^rtbh_pld|^cto_pld|^rtbhc|^keyword/.test(key)) { return params; }
|
|
539
|
-
|
|
540
|
-
params[key] = value ? decodeURIComponent(value.replace(/\+/g, ' ')) : '';
|
|
541
|
-
|
|
542
|
-
return params;
|
|
543
|
-
},
|
|
544
|
-
{}
|
|
545
|
-
); // eslint-disable-line indent,@typescript-eslint/indent
|
|
546
|
-
|
|
547
|
-
return result;
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
export function setUtmParameters() {
|
|
551
|
-
const marketing = getUtmQueryParameter();
|
|
552
|
-
|
|
553
|
-
if (!marketing) return;
|
|
554
|
-
|
|
555
|
-
if (!Object.keys(marketing).length) { return; }
|
|
556
|
-
|
|
557
|
-
const expiresDate = new Date();
|
|
558
|
-
expiresDate.setDate(expiresDate.getDate() + 1);
|
|
559
|
-
|
|
560
|
-
const parsedUrl = new URL(window.location.href);
|
|
561
|
-
const domain = parsedUrl.hostname.split('.').slice(-2).join('.');
|
|
562
|
-
|
|
563
|
-
document.cookie = `marketing=${JSON.stringify(marketing)};expires=${expiresDate};domain=.${domain};path=/`;
|
|
564
|
-
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
export const updateCookieList = (handleSentryInit: () => void) => {
|
|
568
|
-
const cookieConfig = JSON.parse(localStorage.getItem('cookieConfig')) || {};
|
|
569
|
-
let isSentryGranted = true; // Sentry
|
|
570
|
-
let disabledCookies: any[] = [];
|
|
571
|
-
const parsedUrl = new URL(window.location.href);
|
|
572
|
-
const domain = parsedUrl.hostname.split('.').slice(-2).join('.');
|
|
573
|
-
|
|
574
|
-
Object.keys(cookieConfig).forEach((group: string) => {
|
|
575
|
-
cookieConfig[group].forEach((cookie: string) => {
|
|
576
|
-
Cookies.remove(cookie, { domain, path: '/' }); // manually remove selected cookies
|
|
577
|
-
if (cookie === 'sentry') {
|
|
578
|
-
isSentryGranted = false;
|
|
579
|
-
}
|
|
580
|
-
disabledCookies.push(cookie);
|
|
581
|
-
});
|
|
582
|
-
});
|
|
583
|
-
|
|
584
|
-
// grant google cookies
|
|
585
|
-
if (typeof window.grantCookieConsent === 'function') {
|
|
586
|
-
window.grantCookieConsent(disabledCookies);
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
// grant Sentry cookies
|
|
590
|
-
if (isSentryGranted) {
|
|
591
|
-
handleSentryInit();
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
};
|
|
595
|
-
|
|
596
|
-
// function returns decimal part of number with 2 digits
|
|
597
|
-
export const getCents = (value: number, prefix?: string, postfix?: string): string => {
|
|
598
|
-
if (!Number.isFinite(value)) return '';
|
|
599
|
-
const roundedValue = Math.floor(value);
|
|
600
|
-
const result = value.toFixed(2).toString().replace(`${roundedValue}.`, '');
|
|
601
|
-
return `${prefix}${result}${postfix}`;
|
|
602
|
-
};
|
|
603
|
-
|
|
604
|
-
/**
|
|
605
|
-
* Generates a timestamp (Unix time) after 14 days from the current date.
|
|
606
|
-
* @returns {number} Timestamp (Unix time) after 14 days.
|
|
607
|
-
*/
|
|
608
|
-
export const getUnixTimestampAfterTwoWeeks = () => {
|
|
609
|
-
const currentDate = new Date();
|
|
610
|
-
const futureDate = new Date();
|
|
611
|
-
|
|
612
|
-
futureDate.setDate(currentDate.getDate() + 14);
|
|
613
|
-
|
|
614
|
-
const unixTimestamp = Math.floor(futureDate.getTime() / 1000);
|
|
615
|
-
return unixTimestamp;
|
|
616
|
-
};
|
|
617
|
-
|
|
618
|
-
/**
|
|
619
|
-
* Converts a Unix timestamp to the day of the month.
|
|
620
|
-
* @param {number} unixTimestamp - The Unix timestamp to convert.
|
|
621
|
-
* @returns {number} Return the number of days as the result
|
|
622
|
-
*/
|
|
623
|
-
export const convertUnixTimestampToDays = (unixTimestamp: number) => {
|
|
624
|
-
const milliseconds = Number(unixTimestamp * 1000);
|
|
625
|
-
const date = new Date(milliseconds);
|
|
626
|
-
const currentDate = new Date();
|
|
627
|
-
|
|
628
|
-
// Calculate the difference between the current date and the obtained date
|
|
629
|
-
const timeDifference = currentDate.getTime() - date.getTime();
|
|
630
|
-
const daysDifference = -Math.floor(timeDifference / (1000 * 3600 * 24));
|
|
631
|
-
return daysDifference;
|
|
632
|
-
};
|
|
633
|
-
|
|
634
|
-
export const priceParse = (value: any) => {
|
|
635
|
-
return !!value ? Number.parseFloat(value) : null;
|
|
636
|
-
};
|
|
637
|
-
|
|
638
|
-
// iPad on iOS 13 detection
|
|
639
|
-
export const iOS = () => {
|
|
640
|
-
return [
|
|
641
|
-
'iPad Simulator',
|
|
642
|
-
'iPhone Simulator',
|
|
643
|
-
'iPod Simulator',
|
|
644
|
-
'iPad',
|
|
645
|
-
'iPhone',
|
|
646
|
-
'iPod'
|
|
647
|
-
].includes(navigator.platform)
|
|
648
|
-
|| (navigator.userAgent.includes("Mac") && "ontouchend" in document)
|
|
1
|
+
import qs from 'qs';
|
|
2
|
+
import _get from 'lodash/get';
|
|
3
|
+
import { formatLocale as d3formatLocale } from 'd3-format';
|
|
4
|
+
import Cookies from 'js-cookie';
|
|
5
|
+
import {
|
|
6
|
+
FIRST_REGISTRATION, MANUFACTURER, MILEAGE, MODEL, BODY_TYPE, PRICE, RATE,
|
|
7
|
+
DROP_DOWN_GROUP, RATE_DEFAULT, MMS_GROUPS_KEY, MMS_GROUP_FIELDS
|
|
8
|
+
} from '../constants/SearchWidget';
|
|
9
|
+
import { priceRatings, priceRatingConfig } from '../constants/price';
|
|
10
|
+
import { HUNDRED } from '../constants/common';
|
|
11
|
+
import { offers, PREDICTABLE_PRICE_INDEX } from '../constants/core';
|
|
12
|
+
import { FILTERS_IN_TITLE, MANUFACTURER_KEY, MAX_FILTERS_IN_TITLE, MODEL_KEY } from '../constants/Search';
|
|
13
|
+
import { isArray } from 'lodash';
|
|
14
|
+
|
|
15
|
+
const PRICE_DEFAULT = DROP_DOWN_GROUP[PRICE].defaultValue;
|
|
16
|
+
|
|
17
|
+
declare global {
|
|
18
|
+
// tslint:disable-next-line:interface-name
|
|
19
|
+
interface Window {
|
|
20
|
+
grantCookieConsentSentry?: () => void;
|
|
21
|
+
grantCookieConsent?: (disabledCookies: string[]) => void;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const formatMileage = (millage: number | string) => {
|
|
26
|
+
return millage.toLocaleString('en-US').replace(/,/g, '.');
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const getFormattedNumber = (num: number) => Number.isFinite(num) ? num.toLocaleString('de-DE') : null;
|
|
30
|
+
|
|
31
|
+
export const numberWithDot = (value: number | string) => {
|
|
32
|
+
switch (value) {
|
|
33
|
+
case 'any':
|
|
34
|
+
return value;
|
|
35
|
+
case 'beliebig':
|
|
36
|
+
return value;
|
|
37
|
+
default: return getFormattedNumber(+value);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const arrToObj = (arr: string[]): { [key: string]: boolean } => {
|
|
42
|
+
if (!Array.isArray(arr)) return {};
|
|
43
|
+
return arr.reduce(
|
|
44
|
+
(obj: { [key: string]: boolean }, el: string) => { obj[el] = true; return obj; }, {}
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const addPrefixToKeys = (obj: { [key: string]: any }, prefix: string) => {
|
|
49
|
+
const result: { [key: string]: any } = {};
|
|
50
|
+
Object.keys(obj).reduce((_, key) => {
|
|
51
|
+
result[`${prefix}_${key}`] = obj[key];
|
|
52
|
+
return result;
|
|
53
|
+
}, result); // tslint:disable-line:align
|
|
54
|
+
return result;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// function return list of filter for inject in title
|
|
58
|
+
export const filtersInTitle = (filters: any) => {
|
|
59
|
+
const result: any[] = [];
|
|
60
|
+
const pushInResult = (value: any) => {
|
|
61
|
+
if (result.length < MAX_FILTERS_IN_TITLE && value) {
|
|
62
|
+
result.push(value);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
FILTERS_IN_TITLE.forEach((filter: string) => {
|
|
67
|
+
if (filter === MMS_GROUPS_KEY) {
|
|
68
|
+
filters.get(filter).forEach((MmsObject: any) => {
|
|
69
|
+
pushInResult(MmsObject[MANUFACTURER_KEY].value);
|
|
70
|
+
pushInResult(MmsObject[MODEL_KEY].value);
|
|
71
|
+
});
|
|
72
|
+
} else {
|
|
73
|
+
filters.get(filter).value.forEach((value: string) => {
|
|
74
|
+
pushInResult(value);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
return result;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export const changeLocation = (path: string) =>
|
|
82
|
+
window.location.href = `${window.location.origin}/${path}`;
|
|
83
|
+
|
|
84
|
+
export const checkRangeValuesOnEqual = (defaultValues: any, filterValues: any) => {
|
|
85
|
+
const keys = Object.keys(defaultValues);
|
|
86
|
+
let valuesIsEqual = true;
|
|
87
|
+
for (let i = 0; i < keys.length; i += 1) {
|
|
88
|
+
const period = keys[i];
|
|
89
|
+
|
|
90
|
+
if (filterValues[period] !== defaultValues[period]) {
|
|
91
|
+
valuesIsEqual = false;
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return valuesIsEqual;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export interface ICarImage {
|
|
100
|
+
url?: string;
|
|
101
|
+
imageUrlSmall?: string;
|
|
102
|
+
imageUrlMedium?: string;
|
|
103
|
+
imageUrlLarge?: string;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export const preloadNearbyImages = (images: ICarImage[], activeIndex: number, imageUrlSize: 'imageUrlSmall' | 'imageUrlMedium' | 'imageUrlLarge') => {
|
|
107
|
+
const imagesCount = Array.isArray(images) ? images.length : 0;
|
|
108
|
+
const imageSize = imageUrlSize;
|
|
109
|
+
|
|
110
|
+
const inMemoryPrevImage = new Image();
|
|
111
|
+
const inMemoryNextImage = new Image();
|
|
112
|
+
|
|
113
|
+
if (!!imagesCount) {
|
|
114
|
+
const prevIndex = (activeIndex - 1 % imagesCount + imagesCount) % imagesCount;
|
|
115
|
+
const nextIndex = (activeIndex + 1 % imagesCount + imagesCount) % imagesCount;
|
|
116
|
+
|
|
117
|
+
inMemoryPrevImage.src = images[prevIndex][imageSize];
|
|
118
|
+
inMemoryNextImage.src = images[nextIndex][imageSize];
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export const getGroupValuesForQuery = (groups: any) => {
|
|
123
|
+
const arr: any = [];
|
|
124
|
+
groups.map((group: any) => {
|
|
125
|
+
const groupObj: any = {};
|
|
126
|
+
|
|
127
|
+
Object.keys(group).forEach((key: string) => {
|
|
128
|
+
const item = group[key];
|
|
129
|
+
if (item.value) {
|
|
130
|
+
groupObj[key] = item.value;
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
if (Object.keys(groupObj).length) {
|
|
134
|
+
arr.push(groupObj);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
return arr;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export const buildBodyForRequest = (state: any) => {
|
|
141
|
+
const query: any = {
|
|
142
|
+
filters: {
|
|
143
|
+
absolutValues: {
|
|
144
|
+
mmsGroup0: {}
|
|
145
|
+
},
|
|
146
|
+
noAbsolutValues: {},
|
|
147
|
+
rangeValues: {}
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
Object.keys(state).sort().forEach((key: string) => {
|
|
152
|
+
const value = state[key];
|
|
153
|
+
|
|
154
|
+
if (!value) return;
|
|
155
|
+
|
|
156
|
+
if (key === MANUFACTURER && value.value) {
|
|
157
|
+
query.filters.absolutValues.mmsGroup0.mainData_make = value.value;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (key === MODEL && value.value) {
|
|
161
|
+
if (value.isSeries) {
|
|
162
|
+
query.filters.absolutValues.mmsGroup0.mainData_series = value.value;
|
|
163
|
+
} else {
|
|
164
|
+
query.filters.absolutValues.mmsGroup0.mainData_model = value.value;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (key === BODY_TYPE && value.length) {
|
|
169
|
+
query.filters.noAbsolutValues[BODY_TYPE] = value;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (key === FIRST_REGISTRATION && value.value) {
|
|
173
|
+
query.filters.rangeValues['mainData_firstRegistrationYear'] = { from: value.value };
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (key === MILEAGE && value.value) {
|
|
177
|
+
query.filters.rangeValues['mainData_mileage'] = { to: value.value };
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (key === PRICE) {
|
|
181
|
+
const valueIsEqual = checkRangeValuesOnEqual(PRICE_DEFAULT, value);
|
|
182
|
+
|
|
183
|
+
if (!valueIsEqual) {
|
|
184
|
+
// check value in from / to. If we have - add it
|
|
185
|
+
Object.keys(value).map((key: string) => {
|
|
186
|
+
if (value[key]) {
|
|
187
|
+
if (!query.filters.rangeValues['price_currentSalesPrice']) {
|
|
188
|
+
query.filters.rangeValues['price_currentSalesPrice'] = {};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
query.filters.rangeValues['price_currentSalesPrice'][key] = value[key];
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (key === RATE) {
|
|
198
|
+
const isRateDefault = checkRangeValuesOnEqual(RATE_DEFAULT, value);
|
|
199
|
+
|
|
200
|
+
if (!isRateDefault) {
|
|
201
|
+
query.filters.rangeValues['price_currentSalesPrice'] = { from: 1000, to: 2000 };
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
return query;
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
export const buildQueryForSearch = (filters: any) => {
|
|
210
|
+
const query: { [key: string]: any } = {};
|
|
211
|
+
const MMS_GROUP: any = {};
|
|
212
|
+
|
|
213
|
+
Object.keys(filters).forEach((filter: string) => {
|
|
214
|
+
const filterValue = filters[filter];
|
|
215
|
+
|
|
216
|
+
if (filterValue && filterValue.value) {
|
|
217
|
+
if (MMS_GROUP_FIELDS.indexOf(filter) !== -1) {
|
|
218
|
+
|
|
219
|
+
if (filterValue.isSeries) {
|
|
220
|
+
MMS_GROUP.SERIES = filterValue.value;
|
|
221
|
+
} else {
|
|
222
|
+
MMS_GROUP[filter] = filterValue.value;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (filterValue === PRICE) {
|
|
228
|
+
const defaultValue = DROP_DOWN_GROUP[filter].defaultValue;
|
|
229
|
+
const valueIsDefault = filter === PRICE ? checkRangeValuesOnEqual(defaultValue, filterValue) : filterValue === defaultValue;
|
|
230
|
+
|
|
231
|
+
if (!valueIsDefault) {// check value in from / to. If we have - add it
|
|
232
|
+
Object.keys(filterValue).map((key: string) => {
|
|
233
|
+
if (filterValue[key]) {
|
|
234
|
+
if (!query.filters.rangeValues['price_currentSalesPrice']) {
|
|
235
|
+
query.filters.rangeValues['price_currentSalesPrice'] = {};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
query.filters.rangeValues['price_currentSalesPrice'][key] = filterValue[key];
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (filter === PRICE) {
|
|
245
|
+
const valueIsDefault = checkRangeValuesOnEqual(PRICE_DEFAULT, filterValue);
|
|
246
|
+
|
|
247
|
+
if (!valueIsDefault) {
|
|
248
|
+
query[PRICE] = { from: '', to: '' };
|
|
249
|
+
query[PRICE].from = _get(filterValue, 'from', '');
|
|
250
|
+
query[PRICE].to = _get(filterValue, 'to', '');
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (filter === RATE) {
|
|
255
|
+
const isRateDefault = checkRangeValuesOnEqual(RATE_DEFAULT, filterValue);
|
|
256
|
+
|
|
257
|
+
if (!isRateDefault) {
|
|
258
|
+
query[RATE] = filterValue;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (filter === MILEAGE) {
|
|
263
|
+
const defaultValue = DROP_DOWN_GROUP[filter].defaultValue;
|
|
264
|
+
if (filterValue !== defaultValue) {
|
|
265
|
+
query[MILEAGE] = { from: '', to: '' };
|
|
266
|
+
query[MILEAGE].from = _get(filterValue, 'from', '');
|
|
267
|
+
query[MILEAGE].to = _get(filterValue, 'to', '') || _get(filterValue, 'value', '');
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (filter === FIRST_REGISTRATION) {
|
|
272
|
+
const defaultValue = DROP_DOWN_GROUP[filter].defaultValue;
|
|
273
|
+
if (filterValue !== defaultValue) {
|
|
274
|
+
query[FIRST_REGISTRATION] = { from: '', to: '' };
|
|
275
|
+
query[FIRST_REGISTRATION].from = _get(filterValue, 'from', '') || _get(filterValue, 'value', '');
|
|
276
|
+
query[FIRST_REGISTRATION].to = _get(filterValue, 'to', '');
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (filter === BODY_TYPE) {
|
|
281
|
+
const defaultValue = DROP_DOWN_GROUP[filter].defaultValue;
|
|
282
|
+
|
|
283
|
+
if (filterValue.length && filterValue !== defaultValue) {
|
|
284
|
+
query[BODY_TYPE] = [];
|
|
285
|
+
|
|
286
|
+
filterValue.map((bodyTypeSelector: string) => {
|
|
287
|
+
query[BODY_TYPE].push(bodyTypeSelector);
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
if (Object.keys(MMS_GROUP).length) {
|
|
294
|
+
query[MMS_GROUPS_KEY] = [];
|
|
295
|
+
query[MMS_GROUPS_KEY].push(MMS_GROUP);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return qs.stringify(query, { encode: false });
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
export const sliceLessThan = (array: number[], to: any): number[] => {
|
|
302
|
+
const value = Number(to);
|
|
303
|
+
return value && Number.isFinite(value)
|
|
304
|
+
? array.filter((val: number) => val <= value)
|
|
305
|
+
: array;
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
export const sliceMoreThan = (array: number[], from: any): number[] => {
|
|
309
|
+
const value = Number(from);
|
|
310
|
+
return value && Number.isFinite(value)
|
|
311
|
+
? array.filter((val: number) => val >= value)
|
|
312
|
+
: array;
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
export const getFormattedPrice = (price: number, format = '$,.0f', currency = '', currencyPrefix = ''): string => {
|
|
316
|
+
if (!Number.isFinite(price)) return '-';
|
|
317
|
+
const groupingNum = 3;
|
|
318
|
+
return d3formatLocale({
|
|
319
|
+
decimal: ',',
|
|
320
|
+
thousands: '.',
|
|
321
|
+
currency: [currencyPrefix, currency],
|
|
322
|
+
grouping: [groupingNum]
|
|
323
|
+
}).format(format)(price);
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
export const getPriceRatingConfig = (currentPrice: number, pricePredicted: number) => { // tslint:disable-line
|
|
328
|
+
const round = (value: number) => {
|
|
329
|
+
return Number.isFinite(pricePredicted)
|
|
330
|
+
? Math.round((pricePredicted * (1 + (value / 100))) / 100) * 100 // tslint:disable-line
|
|
331
|
+
: '???';
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
if (currentPrice === 0) {
|
|
335
|
+
console.log('Empty current price');
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
return Object.keys(priceRatingConfig).reduce((acc: any, key: any) => {
|
|
339
|
+
const { min, max } = priceRatingConfig[key];
|
|
340
|
+
return { ...acc, [key]: { min: round(min), max: round(max) } };
|
|
341
|
+
}, {}); // tslint:disable-line
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
export const getPredictablePrice = (currentSalesPrice: number, predictablePrice: number) => {
|
|
345
|
+
if (Number.isFinite(Number.parseFloat(`${predictablePrice}`))) {
|
|
346
|
+
return predictablePrice;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return currentSalesPrice * PREDICTABLE_PRICE_INDEX;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export const getPriceRating = (currentSalesPrice: number, predictablePrice: number) => {
|
|
353
|
+
const isCorrectCurrentSalesPrice = Number.isFinite(Number.parseFloat(`${currentSalesPrice}`));
|
|
354
|
+
// const isCorrectPredictablePrice = Number.isFinite(Number.parseFloat(`${predictablePrice}`));
|
|
355
|
+
|
|
356
|
+
if (!isCorrectCurrentSalesPrice) return 0;
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
const validatedPredictablePrice = getPredictablePrice(currentSalesPrice, predictablePrice);
|
|
360
|
+
|
|
361
|
+
const ratingConfig = getPriceRatingConfig(currentSalesPrice, validatedPredictablePrice);
|
|
362
|
+
|
|
363
|
+
for (const key of Object.keys(ratingConfig)) {
|
|
364
|
+
const { min, max } = ratingConfig[key];
|
|
365
|
+
const TOP_PRICE = 5;
|
|
366
|
+
if (key === 'highPrice' && currentSalesPrice === max) return 1;
|
|
367
|
+
if (key === 'topPrice' && currentSalesPrice <= min) return TOP_PRICE;
|
|
368
|
+
if (currentSalesPrice >= min && currentSalesPrice < max) return priceRatings.indexOf(key);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
return 0;
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
export const fixNumber = (num: number | string) => {
|
|
375
|
+
const isNum = typeof num === 'number' ? num : parseFloat(num);
|
|
376
|
+
return Math.round(isNum * HUNDRED) / HUNDRED;
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
export const getOfferSliders = (financingConfig: any, t: (key: string, options?: object) => string, priceTabIndex: null | number, componentType: string) => {
|
|
380
|
+
const offerObj = offers[+priceTabIndex];
|
|
381
|
+
const offerConfig = financingConfig[offerObj.name];
|
|
382
|
+
const currentSalesPrice =
|
|
383
|
+
financingConfig.common ?
|
|
384
|
+
financingConfig.common.currentSalesPrice :
|
|
385
|
+
financingConfig.currentSalesPrice; // TODO: fix deprecated. Correct is "financingConfig.common.currentSalesPrice"
|
|
386
|
+
if (isArray(offerObj.sliders)) {
|
|
387
|
+
const sliders: any = offerObj.sliders;
|
|
388
|
+
return sliders
|
|
389
|
+
.map((slider: any, index: number) => {
|
|
390
|
+
if (componentType === 'checkout' && index === 1 && priceTabIndex === 0) return; // remove checkout annual mileage for financing
|
|
391
|
+
if (slider.name === 'firstInstallment') slider.max = offerConfig.firstInstallmentMax || currentSalesPrice;
|
|
392
|
+
slider.value = offerConfig[slider.name];
|
|
393
|
+
slider.unitName = t(`modals:financing.${slider.unit}`);
|
|
394
|
+
slider.caption = t(`modals:financing.${slider.name}`);
|
|
395
|
+
return slider;
|
|
396
|
+
}).filter(Boolean);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
export const checkWebpFeature = async () => {
|
|
402
|
+
// If the browser doesn't has the method createImageBitmap, you can't display webp format
|
|
403
|
+
if (!self.createImageBitmap) return false;
|
|
404
|
+
|
|
405
|
+
// Base64 representation of a white point image
|
|
406
|
+
const webpData = 'data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoCAAEAAQAcJaQAA3AA/v3AgAA=';
|
|
407
|
+
|
|
408
|
+
// Retrieve the Image in Blob Format
|
|
409
|
+
const blob = await fetch(webpData).then(r => r.blob());
|
|
410
|
+
|
|
411
|
+
// If the createImageBitmap method succeeds, return true, otherwise false
|
|
412
|
+
return createImageBitmap(blob).then(() => true, () => false);
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
export const getSupportedImageFormat = (IMAGE_URL: string, vehicleID: string, imageIdentifier: string, size: 'small' | 'medium' | 'large', webpFeature: boolean) => {
|
|
416
|
+
if (!imageIdentifier) return null;
|
|
417
|
+
|
|
418
|
+
const vehicleImageURL = `${IMAGE_URL}/${vehicleID}/${imageIdentifier}`;
|
|
419
|
+
|
|
420
|
+
return webpFeature ? `${vehicleImageURL}/${size}-cached.webp` : `${vehicleImageURL}/${size}-cached.jpeg`;
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
export function getChipFilterValue(
|
|
424
|
+
chip: any,
|
|
425
|
+
// Fallback keeps the function usable without an i18n instance: it returns the
|
|
426
|
+
// raw key. (The former fe-ui-core German-dictionary fallback was dropped when
|
|
427
|
+
// this module moved to @bytebrand/fe-ui-core-autobahn so the locale tree could
|
|
428
|
+
// stay behind — every real call site passes `t` explicitly.)
|
|
429
|
+
t: (key: string, options?: object) => string = (phrase: string, _?: object) => phrase,
|
|
430
|
+
language: string = 'de'
|
|
431
|
+
) {
|
|
432
|
+
let filterValue: string;
|
|
433
|
+
let title: string;
|
|
434
|
+
let from: string;
|
|
435
|
+
let to: string;
|
|
436
|
+
const chipFilterKey = chip.filterKey || chip.key; // we may have different key naming for landing or main
|
|
437
|
+
const chipFilterValue = chip.filterValue || chip.value; // we may have different key naming for landing or main
|
|
438
|
+
switch (chipFilterKey) {
|
|
439
|
+
case 'MANUFACTURER':
|
|
440
|
+
case 'MODEL':
|
|
441
|
+
case 'SUB_MODEL':
|
|
442
|
+
case 'SERIES':
|
|
443
|
+
filterValue = chipFilterValue;
|
|
444
|
+
break;
|
|
445
|
+
|
|
446
|
+
case 'MANUFACTURER_EXCLUDE':
|
|
447
|
+
case 'MODEL_EXCLUDE':
|
|
448
|
+
title = t(`SearchPage:filters.${chipFilterKey.toLocaleLowerCase()}`);
|
|
449
|
+
filterValue = `${title} ${chipFilterValue}`;
|
|
450
|
+
break;
|
|
451
|
+
|
|
452
|
+
case 'FIRST_REGISTRATION':
|
|
453
|
+
title = t(`SearchPage:filters.${chipFilterKey.toLocaleLowerCase()}`);
|
|
454
|
+
from = chipFilterValue.from ? `${t('SearchPage:filters.from')} ${chipFilterValue.from} ` : '';
|
|
455
|
+
to = chipFilterValue.to ? `${t('SearchPage:filters.to')} ${chipFilterValue.to}` : '';
|
|
456
|
+
filterValue = `${title} ${from} ${to}`;
|
|
457
|
+
break;
|
|
458
|
+
|
|
459
|
+
case 'PRICE':
|
|
460
|
+
case 'PRICE_DIFFERENCE':
|
|
461
|
+
case 'MILEAGE':
|
|
462
|
+
case 'EMISSION_CO2':
|
|
463
|
+
case 'POWER':
|
|
464
|
+
case 'IMAGES_COUNT':
|
|
465
|
+
title = t(`SearchPage:filters.${chipFilterKey.toLocaleLowerCase()}`);
|
|
466
|
+
from = chipFilterValue.from ? `${t('SearchPage:filters.from')} ${getFormattedPrice(+chipFilterValue.from)} ` : '';
|
|
467
|
+
to = chipFilterValue.to ? `${t('SearchPage:filters.to')} ${getFormattedPrice(+chipFilterValue.to)}` : '';
|
|
468
|
+
const type = chipFilterValue.type ? ` ${chipFilterValue.type}` : '';
|
|
469
|
+
filterValue = `${title} ${from} ${to}${type}`;
|
|
470
|
+
break;
|
|
471
|
+
|
|
472
|
+
case 'DOORS':
|
|
473
|
+
case 'OWNERS':
|
|
474
|
+
filterValue = t(`SearchPage:filters.${chipFilterValue}`);
|
|
475
|
+
break;
|
|
476
|
+
|
|
477
|
+
case 'SEATS':
|
|
478
|
+
case 'CUBIC_CAPACITY':
|
|
479
|
+
title = t(`SearchPage:filters.${chipFilterKey.toLocaleLowerCase()}`);
|
|
480
|
+
from = !!chipFilterValue.from ? `${t('SearchPage:filters.from')} ${chipFilterValue.from}` : '';
|
|
481
|
+
to = !!chipFilterValue.to ? `${t('SearchPage:filters.to')} ${chipFilterValue.to}` : '';
|
|
482
|
+
const fromTo = (from && to) ? `${chipFilterValue.from} - ${chipFilterValue.to}` : `${from || to}`;
|
|
483
|
+
filterValue = `${title} ${fromTo}`;
|
|
484
|
+
break;
|
|
485
|
+
|
|
486
|
+
case 'CONSUMPTION':
|
|
487
|
+
const fromValue = Number(chipFilterValue.from).toLocaleString(language);
|
|
488
|
+
const toValue = Number(chipFilterValue.to).toLocaleString(language);
|
|
489
|
+
const newFromValue: any = (fromValue === 'NaN') ? '1' : fromValue;
|
|
490
|
+
const newToValue: any = (toValue === 'NaN') ? '18' : toValue;
|
|
491
|
+
const fromToWithInfo = `${newFromValue} - ${newToValue}`;
|
|
492
|
+
filterValue = t(`SearchPage:filtersChips.${chipFilterKey.toLocaleLowerCase()}`, { value: fromToWithInfo });
|
|
493
|
+
break;
|
|
494
|
+
|
|
495
|
+
case 'ONLINE_SINCE':
|
|
496
|
+
filterValue = t(`SearchPage:filters.${chipFilterValue}`);
|
|
497
|
+
break;
|
|
498
|
+
|
|
499
|
+
case 'GENERAL_INSPECTION':
|
|
500
|
+
filterValue = t(`SearchPage:filtersChips.generalInspection`, { month: t(`SearchPage:filters.${chipFilterValue}`) });
|
|
501
|
+
break;
|
|
502
|
+
|
|
503
|
+
case 'RATE':
|
|
504
|
+
const { monthlyInstallmentFrom, monthlyInstallmentTo, firstInstallment, paybackPeriod } = chipFilterValue;
|
|
505
|
+
const rowValues: any = { monthlyInstallmentFrom, monthlyInstallmentTo, firstInstallment, paybackPeriod };
|
|
506
|
+
const values: string[][] = [
|
|
507
|
+
['monthlyInstallmentFrom', 'monthlyInstallmentTo'],
|
|
508
|
+
['firstInstallment', 'paybackPeriod']
|
|
509
|
+
].map((fields: string[]) => fields
|
|
510
|
+
.map((field: string) => {
|
|
511
|
+
const rowValue = rowValues[field];
|
|
512
|
+
const value = Number.isFinite(+rowValue) ? getFormattedPrice(+rowValue) : rowValue;
|
|
513
|
+
return +rowValue ? t(`SearchPage:filtersChips.${field}Chip`, { value }) : null;
|
|
514
|
+
})
|
|
515
|
+
.filter((item: any) => !!item)
|
|
516
|
+
);
|
|
517
|
+
const rateValue = `${t('SearchPage:filtersChips.rateChip')} ${values[0].length ? values[0].join(' ') : t('SearchPage:filtersChips.any')}`;
|
|
518
|
+
filterValue = `${rateValue}, ${values[1].join(', ')}`;
|
|
519
|
+
break;
|
|
520
|
+
|
|
521
|
+
default:
|
|
522
|
+
filterValue = t(`cbd:${chipFilterValue}`);
|
|
523
|
+
}
|
|
524
|
+
return filterValue;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
function getUtmQueryParameter() {
|
|
528
|
+
const query = window.location.search;
|
|
529
|
+
|
|
530
|
+
if (!query) { return; }
|
|
531
|
+
|
|
532
|
+
const queryString = /^[?]/.test(query) ? query.slice(1) : query;
|
|
533
|
+
|
|
534
|
+
const result = queryString.split('&').reduce(
|
|
535
|
+
(params: any, param: string) => {
|
|
536
|
+
const [key, value] = param.split('=');
|
|
537
|
+
|
|
538
|
+
if (!/^source|^campaign|^medium|^content|^term|^reference|^gclid|^adgroupid|^rtbh_pld|^cto_pld|^rtbhc|^keyword/.test(key)) { return params; }
|
|
539
|
+
|
|
540
|
+
params[key] = value ? decodeURIComponent(value.replace(/\+/g, ' ')) : '';
|
|
541
|
+
|
|
542
|
+
return params;
|
|
543
|
+
},
|
|
544
|
+
{}
|
|
545
|
+
); // eslint-disable-line indent,@typescript-eslint/indent
|
|
546
|
+
|
|
547
|
+
return result;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
export function setUtmParameters() {
|
|
551
|
+
const marketing = getUtmQueryParameter();
|
|
552
|
+
|
|
553
|
+
if (!marketing) return;
|
|
554
|
+
|
|
555
|
+
if (!Object.keys(marketing).length) { return; }
|
|
556
|
+
|
|
557
|
+
const expiresDate = new Date();
|
|
558
|
+
expiresDate.setDate(expiresDate.getDate() + 1);
|
|
559
|
+
|
|
560
|
+
const parsedUrl = new URL(window.location.href);
|
|
561
|
+
const domain = parsedUrl.hostname.split('.').slice(-2).join('.');
|
|
562
|
+
|
|
563
|
+
document.cookie = `marketing=${JSON.stringify(marketing)};expires=${expiresDate};domain=.${domain};path=/`;
|
|
564
|
+
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
export const updateCookieList = (handleSentryInit: () => void) => {
|
|
568
|
+
const cookieConfig = JSON.parse(localStorage.getItem('cookieConfig')) || {};
|
|
569
|
+
let isSentryGranted = true; // Sentry
|
|
570
|
+
let disabledCookies: any[] = [];
|
|
571
|
+
const parsedUrl = new URL(window.location.href);
|
|
572
|
+
const domain = parsedUrl.hostname.split('.').slice(-2).join('.');
|
|
573
|
+
|
|
574
|
+
Object.keys(cookieConfig).forEach((group: string) => {
|
|
575
|
+
cookieConfig[group].forEach((cookie: string) => {
|
|
576
|
+
Cookies.remove(cookie, { domain, path: '/' }); // manually remove selected cookies
|
|
577
|
+
if (cookie === 'sentry') {
|
|
578
|
+
isSentryGranted = false;
|
|
579
|
+
}
|
|
580
|
+
disabledCookies.push(cookie);
|
|
581
|
+
});
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
// grant google cookies
|
|
585
|
+
if (typeof window.grantCookieConsent === 'function') {
|
|
586
|
+
window.grantCookieConsent(disabledCookies);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// grant Sentry cookies
|
|
590
|
+
if (isSentryGranted) {
|
|
591
|
+
handleSentryInit();
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
// function returns decimal part of number with 2 digits
|
|
597
|
+
export const getCents = (value: number, prefix?: string, postfix?: string): string => {
|
|
598
|
+
if (!Number.isFinite(value)) return '';
|
|
599
|
+
const roundedValue = Math.floor(value);
|
|
600
|
+
const result = value.toFixed(2).toString().replace(`${roundedValue}.`, '');
|
|
601
|
+
return `${prefix}${result}${postfix}`;
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Generates a timestamp (Unix time) after 14 days from the current date.
|
|
606
|
+
* @returns {number} Timestamp (Unix time) after 14 days.
|
|
607
|
+
*/
|
|
608
|
+
export const getUnixTimestampAfterTwoWeeks = () => {
|
|
609
|
+
const currentDate = new Date();
|
|
610
|
+
const futureDate = new Date();
|
|
611
|
+
|
|
612
|
+
futureDate.setDate(currentDate.getDate() + 14);
|
|
613
|
+
|
|
614
|
+
const unixTimestamp = Math.floor(futureDate.getTime() / 1000);
|
|
615
|
+
return unixTimestamp;
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* Converts a Unix timestamp to the day of the month.
|
|
620
|
+
* @param {number} unixTimestamp - The Unix timestamp to convert.
|
|
621
|
+
* @returns {number} Return the number of days as the result
|
|
622
|
+
*/
|
|
623
|
+
export const convertUnixTimestampToDays = (unixTimestamp: number) => {
|
|
624
|
+
const milliseconds = Number(unixTimestamp * 1000);
|
|
625
|
+
const date = new Date(milliseconds);
|
|
626
|
+
const currentDate = new Date();
|
|
627
|
+
|
|
628
|
+
// Calculate the difference between the current date and the obtained date
|
|
629
|
+
const timeDifference = currentDate.getTime() - date.getTime();
|
|
630
|
+
const daysDifference = -Math.floor(timeDifference / (1000 * 3600 * 24));
|
|
631
|
+
return daysDifference;
|
|
632
|
+
};
|
|
633
|
+
|
|
634
|
+
export const priceParse = (value: any) => {
|
|
635
|
+
return !!value ? Number.parseFloat(value) : null;
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
// iPad on iOS 13 detection
|
|
639
|
+
export const iOS = () => {
|
|
640
|
+
return [
|
|
641
|
+
'iPad Simulator',
|
|
642
|
+
'iPhone Simulator',
|
|
643
|
+
'iPod Simulator',
|
|
644
|
+
'iPad',
|
|
645
|
+
'iPhone',
|
|
646
|
+
'iPod'
|
|
647
|
+
].includes(navigator.platform)
|
|
648
|
+
|| (navigator.userAgent.includes("Mac") && "ontouchend" in document)
|
|
649
649
|
}
|