{"version":3,"file":"index.b533e498.js","sources":["../../vite/modulepreload-polyfill","../../src/components/indicators/LoadingIndicator.tsx","../../src/shared/allbrands.ts","../../src/state/atoms/filterAtoms.ts","../../src/state/atoms/selectedMatchAtom.ts","../../src/state/atoms/sideNavbarAtom.ts","../../src/state/atoms/affiliateShopsDialogAtom.ts","../../src/state/atoms/globalErrorAtom.ts","../../src/state/atoms/debugModeAtom.ts","../../src/Tracking/tealium/track.ts","../../src/Tracking/tealium/trackingEvents.ts","../../src/components/navigation/Footer.tsx","../../src/components/icons/GoogleLogo.tsx","../../src/components/dialogs/ErrorDialog.tsx","../../src/components/dialogs/GlobalErrorDialog.tsx","../../src/pages/LoadingPage.tsx","../../src/shared/utils/classNames.ts","../../src/shared/utils/cookies.ts","../../src/shared/utils/deepCopy.ts","../../src/types/index.ts","../../src/api/getRequest.ts","../../src/api/checkIfUserIsSubscribedRequest.ts","../../src/state/atoms/userAtom.ts","../../src/thridparty/firebase/firebaseInit.ts","../../src/state/atoms/routeToRedirectToAfterLoginAtom.ts","../../src/components/RouteGuard.tsx","../../src/v2/components/helper/ScrollToTop.tsx","../../src/pages/Root.tsx","../../src/v2/components/modals/BottomModal.tsx","../../src/v2/components/buttons/Button.tsx","../../src/v2/pages/notFound/NotFoundPage.v2.tsx","../../src/api/searchProductsRequest.ts","../../src/Tracking/google/sendGaEvent.ts","../../src/Tracking/google/trackingEvents.ts","../../src/api/postRequest.ts","../../src/api/subscribeToNewsletterRequest.ts","../../src/state/atoms/tinyAdminAtom.ts","../../src/state/selectors/accountInfoSelector.ts","../../src/v2/pages/account/components/DeleteAccountModal.tsx","../../src/v2/pages/account/AccountPageV2.tsx","../../src/api/getSearchSuggestionsRequest.ts","../../src/state/atoms/searchSuggestionsAtom.ts","../../src/state/selectors/searchSuggestionsSelector.ts","../../src/hooks/useTrackSearch.ts","../../src/v2/pages/search/components/SearchBar.tsx","../../src/v2/pages/search/components/FilterBar/FilterDropdownPill.tsx","../../src/v2/pages/search/components/FilterBar/FilterButtonPill.tsx","../../src/v2/pages/search/components/FilterBar/FilterBar.tsx","../../src/state/selectors/shownSearchResultsSelector.ts","../../src/hooks/useSearchResults.ts","../../src/hooks/useTrackProductView.ts","../../src/v2/utils/truncateString.ts","../../src/v2/components/hooks/useSearchResultsScroll.ts","../../src/Tracking/general/generalTrackingEvents.ts","../../src/v2/utils/addTwoDigitsAfterComma.ts","../../src/v2/utils/replaceDotWithComma.ts","../../src/v2/utils/formatPrice.ts","../../src/v2/utils/formatSize.ts","../../src/hooks/useTrackProductImpression.ts","../../src/v2/utils/priceInRange.ts","../../src/v2/pages/search/components/SearchResultList.tsx","../../src/v2/components/hooks/useShowNavbarOnScroll.ts","../../src/v2/components/buttons/MatchicButton.tsx","../../src/v2/components/navbar/BottomNavBar/components/ScanButton.tsx","../../src/assets/house.svg","../../src/v2/components/hooks/useIsStandalone.tsx","../../src/v2/components/navbar/BottomNavBar/BottomNavBar.tsx","../../src/v2/pages/search/components/SearchResultCardSkeleton.tsx","../../src/v2/pages/search/SearchPage.v2.tsx","../../src/v2/components/inputs/LabledInput.tsx","../../src/v2/components/inputs/EmailInputLabled.tsx","../../src/v2/components/divider/LabledLineDivider.tsx","../../src/thridparty/firebase/auth/auth.ts","../../src/thridparty/firebase/auth/loginWithPassword.ts","../../src/thridparty/firebase/auth/loginWithGoogle.ts","../../src/shared/utils/convertError/convertFirebaseErrorMessage.ts","../../src/shared/utils/convertError/convertError.ts","../../src/v2/pages/auth/LoginModal.tsx","../../src/v2/components/inputs/CheckBoxLabelGroup.tsx","../../src/thridparty/firebase/auth/signUpNewUser.ts","../../src/v2/pages/auth/utils/getNewsLetterLabel.tsx","../../src/v2/pages/auth/RegisterModal.tsx","../../src/v2/pages/auth/ForgotPasswordModal.tsx","../../src/v2/pages/auth/PasswordResetSendModal.tsx","../../src/v2/pages/auth/ThankYouForRegisteringModal.tsx","../../src/v2/pages/auth/AuthPage.v2.tsx","../../src/state/atoms/selectedDupeGtinAtom.ts","../../src/api/findProductByGtinRequest.ts","../../src/state/selectors/selectedProductToDupeSelector.ts","../../src/components/carousell/DupeCarousell/utils/calculateMatchPriceDifference.ts","../../src/v2/utils/extractNumberFromString.ts","../../src/v2/components/text/Price.tsx","../../src/v2/pages/match/components/ProductToMatchCard.tsx","../../src/v2/pages/match/components/PriceMatchToggle.tsx","../../src/api/findDupeProductsRequest.ts","../../src/state/selectors/findDupeProductsSelector.ts","../../src/state/selectors/matchingDupesSelector.ts","../../src/hooks/useElementOnScreen.ts","../../src/state/atoms/currentlyVisibleMatchAtom.ts","../../src/v2/components/special/MatchCircle.tsx","../../src/v2/pages/match/utils/calculateColorBrightness.ts","../../src/v2/pages/match/components/PriceSectionMatchCard.tsx","../../src/v2/pages/match/components/MatchCard.tsx","../../src/thridparty/firebase/db/saveLastSeenDupesWithHighestDiscount.ts","../../src/hooks/useTrackInstoreMatch.ts","../../src/v2/pages/match/components/MatchSlider.tsx","../../src/v2/pages/match/components/MatchSlideLoadingSkeleton.tsx","../../src/v2/pages/match/MatchPage.v2.tsx","../../src/v2/pages/details/components/ProductCircle.tsx","../../src/v2/pages/details/components/MatchedCosmos.tsx","../../src/v2/pages/details/components/ProductDetailAccordion.tsx","../../src/v2/pages/match/utils/filterShownShops.ts","../../src/v2/pages/match/components/AffliateShopsModal.tsx","../../src/components/carousell/ImageCarousell.tsx","../../src/v2/pages/details/ProductDetailPage.tsx","../../src/v2/pages/home/components/CategoryDiscoverSection.tsx","../../src/v2/pages/home/components/FeatureMatchesSection.tsx","../../src/thridparty/firebase/db/getRecentlyAddedDupesFilters.ts","../../src/state/atoms/recentlyAddedDupesAtom.ts","../../src/hooks/useTrackRecentlyReleasedImpression.ts","../../src/v2/pages/home/components/RecentlyReleasedSection.tsx","../../src/v2/pages/home/components/RecentlyReleasedSectionLoadingSkeleton.tsx","../../src/v2/pages/home/components/TutorialSection.tsx","../../src/v2/pages/home/HomePage.v2.tsx","../../src/thridparty/firebase/auth/logoutUser.ts","../../src/v2/pages/menu/MenuPage.v2.tsx","../../src/thridparty/sentry/sentry.ts","../../src/locales/i18n.ts","../../src/v2/pages/details/ProductDetailPageSkeletonLoading.tsx","../../src/v2/pages/info/configs/infoPages.ts","../../src/v2/utils/randomId.ts","../../src/v2/pages/info/InfoPage.v2.tsx","../../src/v2/pages/scanner/ScannerPage.tsx","../../src/v2/pages/scanner/childrenPages/components/ProductNotFoundModal.tsx","../../src/thridparty/scandit/sdk.tsx","../../src/v2/pages/scanner/childrenPages/InstoreScannerMatchPage.tsx","../../src/v2/pages/scanner/childrenPages/components/ChooseAScannerButtons.tsx","../../src/v2/utils/colorCalculations.ts","../../src/v2/pages/scanner/childrenPages/utils/pickColor.ts","../../src/v2/pages/scanner/childrenPages/utils/getBackCamera.ts","../../src/v2/pages/scanner/childrenPages/utils/getIndicatorPosition.ts","../../src/assets/crossair.svg","../../src/assets/uploadButton.svg","../../src/v2/pages/scanner/childrenPages/ColorScannerMatchPage.tsx","../../src/v2/pages/scanner/childrenPages/CategoryColorMatchPickerPage.tsx","../../src/api/getAllProductsRequest.ts","../../src/state/atoms/allProductsAtom.ts","../../src/state/selectors/getColorMatchesSelector.ts","../../src/v2/pages/match/components/ColorMatchCard.tsx","../../src/state/atoms/colorMatchMemoryAtom.ts","../../src/v2/pages/match/components/ColorMatchSlider.tsx","../../src/v2/pages/match/MatchPageForColor.tsx","../../src/state/selectors/selectSingleProductSelector.ts","../../src/v2/pages/details/ProductDetailPageColorMatch.tsx","../../src/v2/pages/aboutUs/components/HeroImageSection.tsx","../../src/v2/pages/aboutUs/components/HeroImageSmallSection.tsx","../../src/v2/pages/aboutUs/components/ImageTextSection.tsx","../../src/v2/pages/aboutUs/components/NumberShowCaseSection.tsx","../../src/v2/pages/aboutUs/components/TitleShowCaseSection.tsx","../../src/v2/pages/aboutUs/components/VideoTextSection.tsx","../../src/v2/pages/aboutUs/AboutUsPage.tsx","../../src/hooks/usePreventScrollOnTouch.ts","../../src/v2/pages/scanner/childrenPages/utils/checkIfCircleIsClicked.ts","../../src/v2/pages/scanner/childrenPages/utils/getTouchPosition.ts","../../src/v2/pages/scanner/childrenPages/utils/calculateCanvasDimensions.ts","../../src/v2/pages/scanner/childrenPages/utils/drawCrossair.ts","../../src/v2/pages/scanner/childrenPages/ImageUploadColorMatchPage.tsx","../../src/v2/pages/auth/VerifyEmailModal.tsx","../../src/v2/pages/auth/ChangePasswordModal.tsx","../../src/v2/pages/auth/AuthCodePage.tsx","../../src/main.tsx","../../index.html?html-proxy&index=1.js"],"sourcesContent":["__VITE_IS_MODERN__&&(function polyfill() {\n const relList = document.createElement('link').relList;\n if (relList && relList.supports && relList.supports('modulepreload')) {\n return;\n }\n for (const link of document.querySelectorAll('link[rel=\"modulepreload\"]')) {\n processPreload(link);\n }\n new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n if (mutation.type !== 'childList') {\n continue;\n }\n for (const node of mutation.addedNodes) {\n if (node.tagName === 'LINK' && node.rel === 'modulepreload')\n processPreload(node);\n }\n }\n }).observe(document, { childList: true, subtree: true });\n function getFetchOpts(script) {\n const fetchOpts = {};\n if (script.integrity)\n fetchOpts.integrity = script.integrity;\n if (script.referrerpolicy)\n fetchOpts.referrerPolicy = script.referrerpolicy;\n if (script.crossorigin === 'use-credentials')\n fetchOpts.credentials = 'include';\n else if (script.crossorigin === 'anonymous')\n fetchOpts.credentials = 'omit';\n else\n fetchOpts.credentials = 'same-origin';\n return fetchOpts;\n }\n function processPreload(link) {\n if (link.ep)\n // ep marker = processed\n return;\n link.ep = true;\n // prepopulate the load record\n const fetchOpts = getFetchOpts(link);\n fetch(link.href, fetchOpts);\n }\n}());","type TLoadingIndicatorProps = {\n height?: number;\n width?: number;\n};\n\n// TODO: Replace with acctual loading indicator\nexport const LoadingIndicator = ({\n height = 100,\n width = 100,\n}: TLoadingIndicatorProps) => {\n return (\n <>\n \n \n \n \n \n \n \n \n \n );\n};\n","export const possibleBrands = [\n // { value: \"total\", label: \"Best\" },\n { value: \"essence\", label: \"Essence\" },\n { value: \"catrice\", label: \"Catrice\" },\n // { value: \"chanel\", label: \"Chanel\" },\n // { value: \"kiko milano\", label: \"Kiko Milano\" },\n // { value: \"zaron true\", label: \"Zaron True\" },\n // { value: \"lancôme\", label: \"Lancôme\" },\n // { value: \"dior\", label: \"Dior\" },\n // { value: \"neonail\", label: \"Neonail\" },\n // { value: \"guerlain\", label: \"Guerlain\" },\n // { value: \"nyx\", label: \"NYX\" },\n // { value: \"gucci\", label: \"Gucci\" },\n // { value: \"kylie cosmetics\", label: \"Kylie Cosmetics\" },\n // { value: \"deborah lippmann\", label: \"Deborah Lippmann\" },\n // { value: \"maison mirage\", label: \"Maison Mirage\" },\n // { value: \"opi\", label: \"OPI\" },\n // { value: \"gitti\", label: \"Gitti\" },\n // { value: \"make up for ever\", label: \"Make Up For Ever\" },\n // { value: \"nars\", label: \"NARS\" },\n // { value: \"bobbi brown\", label: \"Bobbi Brown\" },\n // { value: \"inglot\", label: \"Inglot\" },\n // { value: \"l’oréal\", label: \"L’Oréal\" },\n // { value: \"charlotte tilbury\", label: \"Charlotte Tilbury\" },\n // { value: \"mac\", label: \"MAC\" },\n // { value: \"herome\", label: \"Herome\" },\n // { value: \"artdeco\", label: \"Artdeco\" },\n // { value: \"essie\", label: \"Essie\" },\n // { value: \"sephora collection\", label: \"Sephora Collection\" },\n // { value: \"dear dahlia\", label: \"Dear Dahlia\" },\n // { value: \"smashbox\", label: \"Smashbox\" },\n // { value: \"fenty beauty\", label: \"Fenty Beauty\" },\n // { value: \"inika organic\", label: \"Inika Organic\" },\n // { value: \"urban decay\", label: \"Urban Decay\" },\n // { value: \"trend !t up\", label: \"Trend !t Up\" },\n // { value: \"l'oréal paris\", label: \"L'Oréal Paris\" },\n // { value: \"estée lauder\", label: \"Estée Lauder\" },\n // { value: \"wet n wild\", label: \"Wet n Wild\" },\n // { value: \"giorgio armani\", label: \"Giorgio Armani\" },\n // { value: \"nails.inc\", label: \"Nails.Inc\" },\n // { value: \"jeffree star cosmetics\", label: \"Jeffree Star Cosmetics\" },\n // { value: \"haus labs\", label: \"Haus Labs\" },\n // { value: \"manhattan\", label: \"Manhattan\" },\n // { value: \"luvia\", label: \"Luvia\" },\n // { value: \"maybelline new york\", label: \"Maybelline New York\" },\n // { value: \"honest\", label: \"Honest\" },\n // { value: \"fenty beauty by rihanna\", label: \"Fenty Beauty by Rihanna\" },\n // { value: \"anny\", label: \"Anny\" },\n // { value: \"sigma beauty\", label: \"Sigma Beauty\" },\n // { value: \"lime crime\", label: \"Lime Crime\" },\n // { value: \"korres\", label: \"Korres\" },\n // { value: \"la roche-posay\", label: \"La Roche-Posay\" },\n // { value: \"alessandro\", label: \"Alessandro\" },\n // { value: \"clarins\", label: \"Clarins\" },\n // { value: \"rare beauty\", label: \"Rare Beauty\" },\n // { value: \"vapour beauty\", label: \"Vapour Beauty\" },\n // { value: \"buxom\", label: \"Buxom\" },\n // { value: \"lavera naturkosmetik\", label: \"Lavera Naturkosmetik\" },\n // { value: \"shiseido\", label: \"Shiseido\" },\n // { value: \"micro cell\", label: \"Micro Cell\" },\n // { value: \"kylie cosmetics \", label: \"Kylie Cosmetics\" },\n // { value: \"nyx professional makeup\", label: \"NYX Professional Makeup\" },\n // { value: \"bellápierre\", label: \"Bellápierre\" },\n // { value: \"laura mercier\", label: \"Laura Mercier\" },\n // { value: \"t.leclerc\", label: \"T.Leclerc\" },\n // { value: \"shiseido - ginza tokyo\", label: \"Shiseido - Ginza Tokyo\" },\n // { value: \"rival\", label: \"Rival\" },\n // { value: \"sleek\", label: \"Sleek\" },\n // { value: \"misslyn\", label: \"Misslyn\" },\n // { value: \"absolute new york\", label: \"Absolute New York\" },\n // { value: \"clinique\", label: \"Clinique\" },\n // { value: \"max factor\", label: \"Max Factor\" },\n // { value: \"givenchy\", label: \"Givenchy\" },\n // { value: \"morgan taylor\", label: \"Morgan Taylor\" },\n // { value: \"maybelline ny\", label: \"Maybelline NY\" },\n // { value: \"manucurist paris\", label: \"Manucurist Paris\" },\n // { value: \"faby\", label: \"Faby\" },\n // { value: \"rival de loop\", label: \"Rival de Loop\" },\n // { value: \"huda beauty\", label: \"Huda Beauty\" },\n // { value: \"e.l.f. cosmetics\", label: \"E.L.F. Cosmetics\" },\n // { value: \"l`oreal paris \", label: \"L`Oreal Paris\" },\n // { value: \"delfy\", label: \"Delfy\" },\n // { value: \"yves saint laurent\", label: \"Yves Saint Laurent\" },\n // { value: \"lipstick queen\", label: \"Lipstick Queen\" },\n // { value: \"ere perez\", label: \"Ere Perez\" },\n // { value: \"nyx - professional makeup\", label: \"NYX - Professional Makeup\" },\n // { value: \"make up forever\", label: \"Make Up Forever\" },\n // { value: \"lanature\", label: \"Lanature\" },\n // { value: \"kvd beauty\", label: \"KVD Beauty\" },\n // { value: \"kjaer weis\", label: \"Kjaer Weis\" },\n // { value: \"kryolan\", label: \"Kryolan\" },\n // { value: \"nudestix\", label: \"Nudestix\" },\n // { value: \"eisenberg\", label: \"Eisenberg\" },\n // { value: \"tarte\", label: \"Tarte\" },\n // { value: \"revolution beauty london\", label: \"Revolution Beauty London\" },\n // { value: \"dior addict\", label: \"Dior Addict\" },\n // { value: \"babor\", label: \"Babor\" },\n // { value: \"be+radiance cucumber\", label: \"Be+Radiance Cucumber\" },\n // { value: \"alverde naturkosmetik\", label: \"Alverde Naturkosmetik\" },\n // { value: \"néonail\", label: \"Néonail\" },\n // { value: \"glossier.\", label: \"Glossier.\" },\n // { value: \"too faced\", label: \"Too Faced\" },\n // { value: \"glossworks\", label: \"Glossworks\" },\n // { value: \"l´oreal\", label: \"L´Oreal\" },\n // { value: \"glossier\", label: \"Glossier\" },\n // { value: \"edding\", label: \"Edding\" },\n // { value: \"lavera\", label: \"Lavera\" },\n // { value: \"loreal\", label: \"Loreal\" },\n // { value: \"ilia\", label: \"Ilia\" },\n // { value: \"kia-charlotta\", label: \"Kia-Charlotta\" },\n // { value: \"logona\", label: \"Logona\" },\n // { value: \"vogue\", label: \"Vogue\" },\n // { value: \"sally hansen\", label: \"Sally Hansen\" },\n // { value: \"tom ford\", label: \"Tom Ford\" },\n // { value: \"diego dalla palma\", label: \"Diego Dalla Palma\" },\n // { value: \"l´oreal paris\", label: \"L´Oreal Paris\" },\n // { value: \"estee lauder\", label: \"Estee Lauder\" },\n // { value: \"pat mcgrath labs\", label: \"Pat McGrath Labs\" },\n // { value: \"lia\", label: \"Lia\" },\n // { value: \"sacha\", label: \"Sacha\" },\n // { value: \"l.a girl\", label: \"L.A Girl\" },\n // { value: \"benecos\", label: \"Benecos\" },\n // { value: \"dolce&gabbana\", label: \"Dolce&Gabbana\" },\n // { value: \"isadora\", label: \"Isadora\" },\n // { value: \"revolution pro\", label: \"Revolution Pro\" },\n // { value: \"cover / fx\", label: \"Cover / FX\" },\n // { value: \"black opal\", label: \"Black Opal\" },\n // { value: \"alverde\", label: \"Alverde\" },\n // { value: \"charlotte tilburry\", label: \"Charlotte Tilburry\" },\n // { value: \"e.l.f.\", label: \"E.L.F.\" },\n // { value: \"black|up\", label: \"Black|Up\" },\n // { value: \"jimmy choo\", label: \"Jimmy Choo\" },\n // { value: \"lord & berry\", label: \"Lord & Berry\" },\n // { value: \"rimmel london\", label: \"Rimmel London\" },\n // { value: \"nyx professional makeup \", label: \"NYX Professional Makeup\" },\n // { value: \"dolce&gabanna\", label: \"Dolce&Gabanna\" },\n // { value: \"anastasia berverly hills\", label: \"Anastasia Berverly Hills\" },\n // { value: \"anastasia beverly hills\", label: \"Anastasia Beverly Hills\" },\n // { value: \"mavala\", label: \"Mavala\" },\n // { value: \"l\\\\'oreal paris\", label: \"L\\\\'Oreal Paris\" },\n // { value: \"manucurist\", label: \"Manucurist\" },\n // { value: \"haus labs by lady gaga\", label: \"Haus Labs by Lady Gaga\" },\n // { value: \"carslan\", label: \"Carslan\" },\n // { value: \"absolution\", label: \"Absolution\" },\n // { value: \"maybelline - new york \", label: \"Maybelline - New York\" },\n // {\n // value: \"wyn beauty by serena williams\",\n // label: \"Wyn Beauty by Serena Williams\",\n // },\n // { value: \"r.e.m. beauty\", label: \"R.E.M. Beauty\" },\n // { value: \"lavera \", label: \"Lavera\" },\n // { value: \"sheglam\", label: \"Sheglam\" },\n // { value: \"morphe \", label: \"Morphe\" },\n // { value: \"bell hypoallergenic\", label: \"Bell Hypoallergenic\" },\n // { value: \"nailberry\", label: \"Nailberry\" },\n // { value: \"3ina\", label: \"3INA\" },\n // { value: \"alcina\", label: \"Alcina\" },\n // { value: \"collistar\", label: \"Collistar\" },\n // { value: \"bourjois\", label: \"Bourjois\" },\n // { value: \"maybelline\", label: \"Maybelline\" },\n // { value: \"dior \", label: \"Dior\" },\n // { value: \"dior - backstage\", label: \"Dior - Backstage\" },\n // { value: \"zao\", label: \"Zao\" },\n // { value: \"idun minerals\", label: \"Idun Minerals\" },\n // { value: \"kylie jenner\", label: \"Kylie Jenner\" },\n // { value: \"maybellin ny\", label: \"Maybellin NY\" },\n // { value: \"thebalm\", label: \"TheBalm\" },\n // { value: \"no_entry\", label: \"No Entry\" },\n // { value: \"delilah\", label: \"Delilah\" },\n // { value: \"tower 28 beauty\", label: \"Tower 28 Beauty\" },\n // { value: \"physicians formula\", label: \"Physicians Formula\" },\n // { value: \"laneige\", label: \"Laneige\" },\n // { value: \"makeup by mario\", label: \"Makeup by Mario\" },\n // { value: \"beauty made easy le papier\", label: \"Beauty Made Easy Le Papier\" },\n // { value: \"jovina cosmetics\", label: \"Jovina Cosmetics\" },\n // { value: \"revlon\", label: \"Revlon\" },\n // { value: \"hynt beauty\", label: \"Hynt Beauty\" },\n // { value: \"mistine\", label: \"Mistine\" },\n // {\n // value: \"revolution makeup revolution london \",\n // label: \"Revolution Makeup Revolution London\",\n // },\n // { value: \"zoeva\", label: \"Zoeva\" },\n // { value: \"lakme\", label: \"Lakme\" },\n // { value: \"kryolan \", label: \"Kryolan\" },\n // { value: \"kia charlotta\", label: \"Kia Charlotta\" },\n // { value: \"dolce&gabannna\", label: \"Dolce&Gabannna\" },\n // { value: \"youth foria\", label: \"Youth Foria\" },\n // { value: \"sante\", label: \"Sante\" },\n // { value: \"elizabeth arden new york\", label: \"Elizabeth Arden New York\" },\n // { value: \"illamasqua\", label: \"Illamasqua\" },\n // { value: \"maybelline - new york\", label: \"Maybelline - New York\" },\n // { value: \"summer fridays\", label: \"Summer Fridays\" },\n // { value: \"armani\", label: \"Armani\" },\n // { value: \"rimmel london\", label: \"Rimmel London\" },\n // { value: \"r.e.m beauty\", label: \"R.E.M Beauty\" },\n // { value: \"etienne\", label: \"Etienne\" },\n // { value: \"londontown\", label: \"Londontown\" },\n // { value: \"stagecolor\", label: \"Stagecolor\" },\n // { value: \"l\\\\'oréal\", label: \"L\\\\'Oréal\" },\n // { value: \"mádara\", label: \"Mádara\" },\n // { value: \"y.o.u\", label: \"Y.O.U\" },\n // { value: \"nip+fab\", label: \"Nip+Fab\" },\n // { value: \"artdeco \", label: \"Artdeco\" },\n // { value: \"paese\", label: \"Paese\" },\n // { value: \"morphe\", label: \"Morphe\" },\n // { value: \"cover fx\", label: \"Cover FX\" },\n // { value: \"tarte \", label: \"Tarte\" },\n // { value: \"ciaté london\", label: \"Ciaté London\" },\n // { value: \"herzlack\", label: \"Herzlack\" },\n // { value: \"jean & len\", label: \"Jean & Len\" },\n // { value: \"by terry\", label: \"By Terry\" },\n // { value: \"the sign tribe\", label: \"The Sign Tribe\" },\n // { value: \"zarko beauty by oli\", label: \"Zarko Beauty by Oli\" },\n // { value: \"rival \", label: \"Rival\" },\n // { value: \"t. leclerc\", label: \"T. Leclerc\" },\n // { value: \"ozn\", label: \"OZN\" },\n // { value: \"velvetines\", label: \"Velvetines\" },\n // { value: \"wardah\", label: \"Wardah\" },\n // { value: \"ash cosmetics\", label: \"Ash Cosmetics\" },\n // { value: \"anastasia beverly hills \", label: \"Anastasia Beverly Hills\" },\n // { value: \"skintific\", label: \"Skintific\" },\n // { value: \"trend it up\", label: \"Trend It Up\" },\n // { value: \"bareminerals\", label: \"BareMinerals\" },\n // { value: \"uslu airlines\", label: \"Uslu Airlines\" },\n // { value: \"laura mercier paris ny\", label: \"Laura Mercier Paris NY\" },\n // { value: \"tom ford soleil\", label: \"Tom Ford Soleil\" },\n // { value: \"doucce\", label: \"Doucce\" },\n // { value: \"kylie jenner \", label: \"Kylie Jenner\" },\n // { value: \"maybelline new york \", label: \"Maybelline New York\" },\n // { value: \"strong\", label: \"Strong\" },\n // { value: \"glossier. \", label: \"Glossier.\" },\n // { value: \"urban declay\", label: \"Urban Declay\" },\n // { value: \"kiko - milano\", label: \"Kiko - Milano\" },\n // { value: \"beter nail care\", label: \"Beter Nail Care\" },\n // { value: \"rodial\", label: \"Rodial\" },\n // { value: \"youth floria\", label: \"Youth Floria\" },\n // { value: \"l´oréal paris\", label: \"L´Oréal Paris\" },\n // { value: \"pixi\", label: \"Pixi\" },\n // { value: \"lancome paris\", label: \"Lancome Paris\" },\n // { value: \"laura geller\", label: \"Laura Geller\" },\n // { value: \"medipharma cosmetics\", label: \"Medipharma Cosmetics\" },\n // { value: \"gosh copenhagen\", label: \"gosh copenhagen\" },\n // { value: \"sephora\", label: \"Sephora\" },\n // { value: \"fenty beauty \", label: \"Fenty Beauty \" },\n // { value: \"lancome\", label: \"Lancome\" },\n // { value: \"neonnail\", label: \"Neonnail\" },\n // { value: \"l`oreal paris\", label: \"L`oreal paris\" },\n // { value: \"neonnail\", label: \"Neonnail\" },\n // { value: \"lavera - naturkosmetik\", label: \"Lavera - Naturkosmetik\" },\n // { value: \"avant\", label: \"Avant\" },\n // { value: \"lòreal\", label: \"Lòreal\" },\n // { value: \"kester black\", label: \"Kester Black\" },\n];\n","import { atom } from \"recoil\";\nimport { TSearchTypeFilter } from \"../../types\";\nimport { possibleBrands } from \"../../shared/allbrands\";\n\nexport const searchStringFilterAtom = atom({\n key: \"searchStringFilterAtom\",\n default: \"\",\n});\n\nexport const searchTypeFiltersAtom = atom({\n key: \"searchTypeFiltersAtom\",\n default: [\n {\n id: 6,\n category: \"Face\",\n label: \"SHARED.TYPE_FILTER_FOUNDATION\",\n value: \"Make-up\",\n type: \"button\",\n selected: false,\n selectedValue: \"\",\n },\n {\n id: 1,\n category: \"Nail\",\n label: \"SHARED.TYPE_FILTER_NAILPOLISH\",\n value: \"Nail Polish\",\n type: \"button\",\n selected: false,\n selectedValue: \"\",\n },\n {\n id: 2,\n category: \"Lip\",\n label: \"SHARED.TYPE_FILTER_LIPSTICK\",\n value: \"Lipstick\",\n type: \"button\",\n selected: false,\n selectedValue: \"\",\n },\n {\n id: 3,\n category: \"Lip\",\n label: \"SHARED.TYPE_FILTER_LIPGLOSS\",\n value: \"Lipgloss\",\n type: \"button\",\n selected: false,\n selectedValue: \"\",\n },\n {\n id: 4,\n category: \"Lip\",\n label: \"SHARED.TYPE_FILTER_LIPLINER\",\n value: \"Lip Pencil\",\n type: \"button\",\n selected: false,\n selectedValue: \"\",\n },\n {\n id: 5,\n category: \"Lip\",\n label: \"SHARED.TYPE_FILTER_BRAND\",\n selected: false,\n selectedValue: \"\",\n options: possibleBrands,\n type: \"dropdown\",\n filterType: \"bestBrandMatch\",\n },\n ],\n});\n\nexport const categoryFilterAtom = atom({\n key: \"categoryFilterAtom\",\n default: \"\",\n});\n\nexport const searchPaginationAtom = atom({\n key: \"searchPaginationAtom\",\n default: 1,\n});\n\nexport const matchFilterAtom = atom({\n key: \"matchFilterAtom\",\n default: \"price\",\n});\n","import { atom } from \"recoil\";\nimport { TDupeProduct } from \"../../types\";\n\nexport const selectedMatchAtom = atom({\n key: \"selectedMatchAtom\",\n default: null,\n});\n","import { atom } from \"recoil\";\n\nexport const sideNavbarOpenAtom = atom({\n key: \"sideNavbarOpenAtom\",\n default: false,\n});\n","import { atom } from \"recoil\";\nimport { TDupeProduct } from \"../../types\";\n\nexport const affiliateShopsDialogAtom = atom({\n key: \"affiliateShopsDialogAtom\",\n default: null,\n});\n","import { atom } from \"recoil\";\n\nexport const globalErrorAtom = atom({\n key: \"globalErrorAtom\",\n default: null,\n});\n","import { atom } from \"recoil\";\n\nexport const debugModeAtom = atom({\n key: \"debugModeAtom\",\n default: false,\n});\n","import { TrackingDataObject, TrackingEventType } from \"./types\";\n\nexport const track = (\n eventType: TrackingEventType,\n dataObject: TrackingDataObject\n): Promise =>\n new Promise((resolve) => {\n if (typeof window === \"undefined\" || !window.utag) return resolve();\n\n window.utag.track(eventType, dataObject, () => resolve());\n });\n","import { data } from \"cypress/types/jquery\";\nimport { TColorMatch } from \"../../state/atoms/colorMatchMemoryAtom\";\nimport { TDupeProduct, TProduct } from \"../../types\";\nimport { track } from \"./track\";\n\nexport const trackSeachSuggestionClicked = (option: string) =>\n track(\"link\", {\n tealium_event: \"search_suggestion_click\",\n page_context: \"n/a\",\n sitesearch_suggest: [option],\n });\n\n// export const trackSiteSearchWithBarcodeComplete = (\n// barcodeGtin: string,\n// searchResults: number\n// ) =>\n// // After search for twin products\n// track(\"link\", {\n// tealium_event: \"sitesearch_complete\",\n// page_context: \"n/a\",\n// search_category: \"Scan\",\n// search_method: \"Product Search\",\n// // \"search_option\": \"type search\", Suggest Freeform\n// //TODO barcode of the item\n// sitesearch_keyword: barcodeGtin,\n// search_results: searchResults,\n// });\n\n// export const trackPurchaseSubscription = () => {\n// // TODO: This was done because the tealium event mapping is not working\n// // and we needed to track these manually. Hopefully the tealium tracking will be fixed soon\n// if (window?.ttq?.track) {\n// window.ttq.track(\"Subscribe\", {\n// currency: \"EUR\",\n// value: \"2.99\",\n// content_id: \"123\",\n// });\n// }\n\n// if (window?.fbq) {\n// window.fbq(\"track\", \"Purchase\", {\n// currency: \"EUR\",\n// value: \"2.99\",\n// });\n// }\n\n// track(\"link\", {\n// tealium_event: \"purchase\",\n// currency_code: \"EUR\",\n// order_value: \"2.99\",\n// order_total_gross: \"2.99\",\n// });\n// };\n\n// TODO wait for Max response here: DUP-232\n// On click on show me the shops ====> implemented!\nexport const trackStoreButtonClick = (product: TProduct) => {\n track(\"link\", {\n tealium_event: \"store_button_click\",\n page_context: \"n/a\",\n product_gtin: [product?.gtin?.toString()],\n product_id: [product?.fid?.toString()],\n product_name: [product?.namecomplete],\n product_price_gross: [product?.price_de?.toString()],\n product_brand: [product?.brand],\n product_variant: [product?.colormain],\n product_position: [\"n/a\"],\n currency_code: \"EUR\",\n product_price_net: [\"n/a\"],\n product_tax: [\"n/a\"],\n });\n};\n\nexport const trackDupeListSwitch = (product: TProduct, toggleType: string) =>\n track(\"link\", {\n tealium_event: \"dupe_list_switch\",\n data_source: \"FEdataLayer\",\n page_context: \"n/a\",\n product_impression_list:\n toggleType === \"price\" ? \"dupe_list_bestprice\" : \"dupe_list_bestmatch\",\n product_gtin: [product.gtin?.toString()],\n product_id: [product.fid?.toString()],\n product_name: [product?.namecomplete],\n product_price_gross: [product?.price_de?.toString()],\n product_brand: [product?.brand?.toString()],\n product_variant: [\"n/a\"],\n product_position: [1],\n currency_code: \"EUR\",\n product_price_net: [\"n/a\"],\n product_tax: [\"n/a\"],\n });\n\n// On click on look for product online ====> implemented!\n// export const trackSearchProductButtonClick = (\n// product: TProduct | null | undefined,\n// toggleType: string\n// ) => {\n// if (!product) return;\n// track(\"link\", {\n// tealium_event: \"store_button_search\",\n// page_context: \"n/a\",\n// product_impression_list:\n// toggleType === \"price\" ? \"dupe_list_bestprice\" : \"dupe_list_bestmatch\",\n// product_gtin: [product?.gtin?.toString()],\n// product_id: [product?.fid?.toString()],\n// product_name: [product?.namecomplete],\n// product_price_gross: [product?.price_de?.toString()],\n// product_brand: [product?.brand],\n// product_variant: [product?.colormain],\n// product_position: [\"n/a\"],\n// currency_code: \"EUR\",\n// product_price_net: [\"n/a\"],\n// product_tax: [\"n/a\"],\n// });\n// };\n\n// On Product Clicked in dupe view ====> implemented!\n\n// On Dupe Menu open ====> implemented!\nexport const trackMenuOpen = () =>\n track(\"link\", {\n tealium_event: \"menu_open\",\n page_context: \"n/a\",\n });\n\nexport const trackProductImpression = (\n products: TProduct[] = [],\n pageContext: string,\n productImpressionList: string\n) =>\n track(\"link\", {\n tealium_event: \"product_impression\",\n data_source: \"FEdataLayer\",\n page_context: pageContext,\n product_impression_list: productImpressionList,\n product_impression_gtin: products?.map((product) => product.gtin),\n product_impression_id: products?.map((product) => product.fid),\n product_impression_name: products?.map((product) => product.namecomplete),\n product_impression_price_gross: products?.map(\n (product) => product.price_de\n ),\n product_impression_brand: products?.map((product) => product.brand),\n product_impression_variant: products?.map((product) => product.colormain),\n product_impression_position: products?.map((product) => product.gtin),\n currency_code: \"EUR\",\n product_impression_price_net: [\"n/a\"],\n product_tax: [\"n/a\"],\n });\n\nexport const trackAccountLogin = (userId: string) =>\n track(\"link\", {\n tealium_event: \"account_login\",\n data_source: \"FEdataLayer\",\n page_context: \"Login\",\n customer_truepid: userId,\n });\n\nexport const trackAccountCreateStart = () => {\n track(\"link\", {\n tealium_event: \"account_create_start\",\n data_source: \"FEdataLayer\",\n page_context: \"Registration\",\n });\n};\n\nexport const trackAccountCreateComplete = (userId: string) =>\n track(\"link\", {\n tealium_event: \"account_create_complete\",\n data_source: \"FEdataLayer\",\n page_context: \"Registration\",\n customer_truepid: userId,\n });\n\nexport const trackFindRetailerButtonClicked = (\n product: TProduct | undefined\n) => {\n if (!product) return;\n\n track(\"link\", {\n tealium_event: \"find_retailer_button_clicked\",\n data_source: \"FEdataLayer\",\n page_context: \"match-details\",\n cart_total_gross: \"NA\",\n product_gtin: [product.gtin],\n product_id: [product.fid],\n product_name: [product.namecomplete],\n product_price_gross: [product.price_de],\n product_brand: [product.brand],\n product_color: [product.colormain],\n product_variant: [],\n product_quantity: [],\n currency_code: \"EUR\",\n product_price_net: [],\n product_tax: [],\n cart_total_net: \"NA\",\n });\n};\n\nexport const trackInstoreMatch = (product: TProduct) => {\n track(\"link\", {\n tealium_event: \"instore_match\",\n data_source: \"FEdataLayer\",\n page_context: \"ProductFinder\",\n search_category: \"Filters\",\n search_method: \"instore_match\",\n search_results: [],\n product_gtin: product?.gtin,\n product_id: product?.id,\n product_name: product?.namecomplete,\n product_price_gross: product?.price_de,\n product_brand: product?.brand,\n product_color: product?.colormain,\n });\n};\n\nexport const trackMatchCosmosOpenend = (product: TProduct) => {\n track(\"link\", {\n tealium_event: \"matched_cosmos_opened\",\n data_source: \"FEdataLayer\",\n page_context: \"match_details\",\n product_gtin: [product.gtin],\n product_id: [product.fid],\n product_name: [product.namecomplete],\n });\n};\n\nexport const trackNewsletterComplete = (userId: string) => {\n track(\"link\", {\n tealium_event: \"newsletter_complete\",\n data_source: \"FEdataLayer\",\n page_context: \"Registration\",\n customer_truepid: userId,\n });\n};\n\nexport const teTrackProductClick = (\n product: TProduct,\n productPosition: number,\n pageContext: string\n) =>\n track(\"link\", {\n tealium_event: \"product_click\",\n data_source: \"FEdataLayer\",\n page_context: pageContext,\n product_impression_list: \"navigation\",\n product_gtin: [product?.gtin],\n product_id: [product?.fid],\n product_name: [product?.namecomplete],\n product_price_gross: [product?.price_de],\n product_brand: [product?.brand],\n product_variant: [\"n/a\"],\n product_position: [productPosition],\n product_color: [product?.colormain],\n currency_code: \"EUR\",\n product_price_net: [\"n/a\"],\n product_tax: [\"n/a\"],\n product_tag: [\"n/a\"],\n });\n\nexport const trackProductFilterComplete = (\n numberOfSearchResults: string,\n filters: string[]\n) =>\n track(\"link\", {\n tealium_event: \"productfilter_complete\",\n data_source: \"FEdataLayer\",\n page_context: \"Search_results\",\n search_category: \"Filters\",\n search_method: \"Suggest\",\n search_option: \"Product Filter\",\n search_results: numberOfSearchResults,\n search_filter_product: filters, //[\"recommendedFilter:lipstick\"],\n });\n\nexport const trackProductView = (dupeProduct: TDupeProduct) => {\n track(\"link\", {\n tealium_event: \"product_view\",\n data_source: \"FEdataLayer\",\n page_context: \"ProductDetails\",\n product_gtin: [dupeProduct?.gtin_twinproduct?.toString()],\n product_id: [dupeProduct?.data.fid?.toString()],\n product_name: [dupeProduct?.data?.namecomplete],\n product_price_gross: [dupeProduct?.data?.price_de?.toString()],\n product_brand: [dupeProduct?.data.brand],\n product_variant: [\"n/a\"],\n product_color: [dupeProduct?.data.colormain],\n currency_code: \"EUR\",\n product_price_net: [\"n/a\"],\n product_tax: [\"n/a\"],\n product_tag: [\"n/a\"],\n });\n};\n\nexport const trackShopNowButtonClick = (product: TProduct) => {\n track(\"link\", {\n tealium_event: \"shop_now_button_clicked\",\n data_source: \"FEdataLayer\",\n page_context: \"Match-details\",\n product_gtin: [product.gtin],\n product_id: [product.fid],\n product_name: [product.namecomplete],\n product_brand: [product.brand],\n product_variant: [\"n/a\"],\n product_color: [product.colormain],\n product_position: [\"n/a\"],\n });\n};\n\nexport const trackSiteSearchComplete = (\n numberOfSearchResults: string,\n query: string\n) => {\n track(\"link\", {\n tealium_event: \"sitesearch_complete\",\n data_source: \"FEdatLayer\",\n page_context: \"Searchbar\",\n search_category: \"Search Bar\",\n search_method: \"Sitesearch\",\n search_option: \"Freeform\",\n sitesearch_keyword: query,\n search_results: numberOfSearchResults,\n });\n};\n\nexport const trackColorMatchCompleteEvent = (colorMatch: TColorMatch) => {\n track(\"link\", {\n tealium_event: \"color_match_complete\",\n data_source: \"FEdataLayer\",\n page_context: \"ColorMatch\",\n search_category: \"Filters\",\n search_step: \"3\",\n search_method: \"color_match\",\n search_results: \"10\",\n product_gtin: colorMatch.matches.map((p: TProduct) => p.gtin),\n product_id: colorMatch.matches.map((p: TProduct) => p.fid),\n product_name: colorMatch.matches.map((p: TProduct) => p.namecomplete),\n product_price_gross: colorMatch.matches.map((p: TProduct) => p.price_de),\n product_brand: colorMatch.matches.map((p: TProduct) => p.brand),\n product_color: colorMatch.matches.map((p: TProduct) => p.colormain),\n searched_color: colorMatch.hex!,\n });\n};\n\nexport const trackColorMatchProgress = () => {\n track(\"link\", {\n tealium_event: \"color_match_progress\",\n data_source: \"FEdataLayer\",\n page_context: \"ColorMatch\",\n search_category: \"Filters\",\n search_step: \"2\",\n search_method: \"colour_match\",\n });\n};\n\nexport const trackColorMatchStart = () => {\n track(\"link\", {\n tealium_event: \"color_match_start\",\n data_source: \"FEdataLayer\",\n page_context: \"ColorMatch\",\n search_category: \"Filters\",\n search_step: \"1\",\n search_method: \"color_match\",\n });\n};\n\nexport const trackContentClicked = (\n contentName: string,\n contentTitle: string,\n position: number\n) => {\n track(\"link\", {\n tealium_event: \"content_clicked\",\n data_source: \"FEdataLayer\",\n page_context: \"Home\",\n content_name: [contentName],\n content_slider_position: [String(position)],\n content_title: [contentTitle],\n });\n};\n\n// TODO: DUP-232 remove if confirmed by max\n// export const trackAccountLogout = () =>\n// track(\"link\", {\n// tealium_event: \"account_logout\",\n// page_context: \"n/a\",\n// });\n\n// USED FOR THE LANDING PAGE\n// track(\"link\", {\n// tealium_event: \"find_match_clicked\",\n// page_context: \"n/a\",\n// });\n\n// track(\"link\", {\n// tealium_event: \"search_suggestion_impression\",\n// page_context: \"n/a\",\n// sitesearch_suggest: [\"Nails\", \"Lips\"],\n// content_slider_position: [1, 2],\n// });\n","import { Link } from \"react-router-dom\";\nimport { Trans, useTranslation } from \"react-i18next\";\n\nconst footerLinks = [\n {\n id: \"1\",\n label: \"LINK_DATAPOLICY\",\n link: \"/de/datenschutz\",\n },\n {\n id: \"2\",\n label: \"LINK_IMPRINT\",\n link: \"/de/impressum\",\n },\n {\n id: \"3\",\n label: \"LINK_TERMS\",\n link: \"/de/nutzungsbedingungen\",\n },\n {\n id: \"4\",\n label: \"LINK_CONTACT\",\n link: \"/de/kontakt\",\n },\n];\nconst remarks = [\n \"FOOTER.REMARK_HOW_IT_WORKS\",\n \"FOOTER.REMARK_PRICE_CALCULATION\",\n \"FOOTER.REMARK_INCL_VAT\",\n];\n\nexport const Footer = () => {\n const { t } = useTranslation();\n return (\n \n
\n {remarks?.map((remark, index) => (\n \n \n hier\n \n ),\n link2: (\n \n hier\n \n ),\n hoch1: ¹,\n hoch2: ²,\n }}\n />\n \n ))}\n
\n
\n {footerLinks.map((element) => (\n \n \n {t(`FOOTER.${element.label}`)}\n \n \n ))}\n
\n \n );\n};\n","export const GoogleLogo = () => {\n return (\n \n \n \n \n \n \n );\n};\n","import { Fragment } from \"react\";\nimport { Dialog, Transition } from \"@headlessui/react\";\nimport { ExclamationTriangleIcon } from \"@heroicons/react/24/outline\";\n\ntype TErrorDialogProps = {\n error: Error | string| null;\n onClose: () => void;\n title: string;\n description: string;\n buttonLabel: string;\n};\n\nexport default function ErrorDialog({\n error,\n onClose,\n title,\n description,\n buttonLabel,\n}: TErrorDialogProps) {\n return (\n \n \n \n
\n \n\n
\n
\n \n \n
\n
\n \n
\n
\n \n {title}\n \n
\n

\n {description}\n

\n
\n
\n
\n
\n \n {buttonLabel}\n \n
\n
\n \n
\n
\n
\n
\n );\n}\n","import { useRecoilState } from \"recoil\";\nimport { globalErrorAtom } from \"../../state/atoms\";\nimport ErrorDialog from \"./ErrorDialog\";\n\nexport const GlobalErrorDialog = () => {\n const [globalError, setGlobalError] = useRecoilState(globalErrorAtom);\n\n if (!globalError) {\n return null;\n }\n\n return (\n setGlobalError(null)}\n />\n );\n};\n","import { LoadingIndicator, Logo } from \"../components\";\n\n// TODO: Replace with acctual loading indicator\nexport const LoadingPage = () => {\n return (\n
\n
\n
\n \n
\n
\n \n
\n
\n
\n );\n};\n","export function classNames(...classes: string[]) {\n return classes.filter(Boolean).join(\" \");\n}\n","import Cookies from \"js-cookie\";\n\nexport function getCookie(name: ECookie): string | undefined {\n return Cookies.get(name);\n}\n\nexport function setCookie(name: ECookie, value: string, days: number) {\n Cookies.set(name, value, { expires: days });\n}\n\nexport function deleteCookie(name: ECookie) {\n Cookies.remove(name);\n}\n\nexport function getAllCookies() {\n return document.cookie.split(\";\").map((cs) => {\n const [key, value] = cs.split(\"=\");\n return { [key]: value };\n });\n}\n\nexport enum ECookie {\n AccessToken = \"accessToken\",\n OnBoarded = \"onBoarded\",\n DesiredMatch = \"desiredMatch\",\n}\n","export const deepCopy = (data: any) => JSON.parse(JSON.stringify(data));\n","import { User } from \"firebase/auth\";\n\nexport type TSearchProductsRequestResponse = {\n totalMatches: number;\n products: TProduct[];\n};\n\nexport type TProduct = {\n id: number;\n fid: string;\n gtin: string;\n name: string;\n type: string;\n brand: string;\n range1: string;\n range2: string;\n sizeml: string;\n category: string;\n colorhex: string;\n price_de: string;\n affiliate: number;\n colormain: string;\n colorname: string;\n imageside: string;\n imagebrush: string;\n imagefront: string;\n imagetop: string;\n imageswatch: string;\n namecomplete: string;\n ingredient_de: string;\n description_de: string;\n imagepackaging: string;\n priceper100ml_de: number;\n};\n\nexport type TDupeProduct = {\n gtin_originalproduct: string;\n gtin_twinproduct: string;\n id: number;\n shops_data: TShopData[];\n sim_color: string;\n sim_gloss: string;\n sim_particles: string;\n sim_total: string;\n stock: number;\n data: TProduct;\n};\n\nexport type TShopData = {\n gtin: string;\n id: number;\n price_de: number;\n retailer: string;\n retailer_logo: string;\n url: string;\n};\n\nexport type TSearchTypeFilter = TSearchButtonFilter | TSearchDropdownFilter;\n\nexport type TSearchDropdownFilter = {\n id: number;\n options: TFilterValue[];\n label: string;\n category: string;\n selected: boolean;\n selectedValue: string | null;\n type: \"dropdown\";\n filterType?: string;\n};\n\nexport type TSearchButtonFilter = {\n id: number;\n label: string;\n value: string;\n category: string;\n selected: boolean;\n selectedValue: string | null;\n type: \"button\";\n filterType?: string;\n};\n\nexport type TFilterValue = {\n label: string;\n value: string;\n};\n\nexport enum AppLanguages {\n EN = \"en\",\n DE = \"de\",\n}\n\nexport enum EAuthLevel {\n ALWAYS = \"ALWAYS\", // contents are always visible\n ISUSER = \"ISUSER\", // only visible to logged in users\n ISPREMIUMUSER = \"ISPREMIUMUSER\", // only visible to logged in users with premium subscription\n ISADMIN = \"ISADMIN\", // only visible to Admins\n ISGUEST = \"ISGUEST\", // only visible to Guests\n}\n\nexport type TNaviagtionConfigLink = {\n name: string;\n href: string;\n authLevel: EAuthLevel;\n};\n\nexport type TNavigationConfig = {\n bigNavLinks: TNaviagtionConfigLink[];\n smallNavLinks: TNaviagtionConfigLink[];\n};\n\nexport type TNewsLetterComponentConfig = {\n title: string;\n description: string;\n legalDisclaimer: string;\n buttonLabel: string;\n};\n\nexport type TComponentConfig = {\n newsletter: TNewsLetterComponentConfig;\n blurredCarousellCard: TBlurredCarousellCardConfig;\n footer: TFooterConfig;\n};\n\nexport type TFooterConfig = {\n remarks: string[];\n elements: TFooterElement[];\n};\n\nexport type TFooterElement = {\n id: string;\n label: string;\n link: string;\n};\n\nexport type TBlurredCarousellCardConfig = {\n description: string;\n buttonLabel: string;\n benefitList: string[];\n};\n\nexport type THomePageConfig = {\n title: string;\n buttonLabel: string;\n barcodeScannerButtonLabel: string;\n filterCategories: TFilterCategories[];\n};\n\nexport type TPaywallConfig = {\n title: string;\n subTitle: string;\n youGetLabel: string;\n acceptTermLabel: string;\n termsLink: {\n link: string;\n label: string;\n };\n userNameInputPlaceHolder: string;\n emailInputPlaceHolder: string;\n passwordInputPlaceHolder: string;\n heroImage: string;\n shownSubscription: {\n id: string;\n };\n loginOrRegisterDescription: string;\n buttonLabel: string;\n};\n\nexport type TThankYouReason = {\n id: string;\n title: string;\n description: string;\n buttonLabel: string;\n goToDupeLabel: string;\n};\n\nexport type TRegisterPageConfig = {\n title: string;\n emailLabel: string;\n passwordLabel: string;\n loginInsteadLinkLabel: string;\n loginInsteadLink: string;\n buttonLabel: string;\n orLoginWith: string;\n backButtonLabel: string;\n acceptTermLabel: string;\n pleaseAcceptTermsLabel: string;\n termsLink: {\n link: string;\n label: string;\n };\n sucessFullRegistrationDialog: {\n title: string;\n iconType: string;\n description: string;\n buttonLabel: string;\n };\n registrationFailedDialog: {\n title: string;\n iconType: string;\n description: string;\n buttonLabel: string;\n };\n newsletterLabels: {\n title: string;\n description: string;\n unfoldDescription: string;\n };\n dataPolicyLink: {\n link: string;\n label: string;\n };\n};\n\nexport type TConfirmEmailAuthLinkPageConfig = {\n title: string;\n sucessDialog: {\n title: string;\n description: string;\n buttonLabel: string;\n };\n errorDialog: {\n title: string;\n description: string;\n buttonLabel: string;\n };\n};\n\nexport type TForgotPasswordPageConfig = {\n title: string;\n descritpion: string;\n linkLabel: string;\n emailInputLabel: string;\n buttonLabel: string;\n emailSendTitle: string;\n emailSendDescription: string;\n emailSendButtonLabel: string;\n};\n\nexport type TSetNewPasswordPageConfig = {\n title: string;\n passwordInputLabel: string;\n passwordRepeatInputLabel: string;\n};\n\nexport type TLoginPageConfig = {\n title: string;\n linkToRegisterLabel: string;\n linkToRegister: string;\n inputLabel: string;\n orLoginWith: string;\n passwordInputLabel: string;\n forgotPasswordLink: string;\n buttonLabel: string;\n errorTitle: string;\n errorDescription: string;\n backButtonLabel: string;\n};\n\nexport type TTutorialStepConfig = {\n id: number;\n imageUrl: string;\n title: string;\n description: string;\n};\n\nexport type TTutorialPageConfig = {\n title: string;\n slides: TTutorialStepConfig[];\n buttonLabel: string;\n skipLabel: string;\n};\n\nexport type TCategoryFilterConfig = {\n id: number;\n category: string;\n value: string;\n label: string;\n};\n\nexport type TToggleOptionsConfig = {\n label: string;\n value: string;\n};\n\nexport type TSearchPageConfig = {\n searchBarPlaceholder: string;\n filtersLabel: string;\n deleteFiltersLabel: string;\n productsFoundLabel: string;\n fromCurrencyLabel: string;\n currencyLabel: string;\n categoryFilters: TCategoryFilterConfig[];\n typeFilters: TSearchTypeFilter[];\n};\n\nexport type TMatchPageConfig = {\n toggleOptions: TToggleOptionsConfig[];\n goToShopButtonLabel: string;\n searchProductButtonLabel: string;\n goToProductDetailsLabel: string;\n cheaperLabel: string;\n moreExpensiveLabel: string;\n shipableLabel: string;\n offersLabel: string;\n linksNotCorrectLabel: string;\n goToShopLabel: string;\n legalDisclaimerLabel: string;\n};\n\nexport type TPageNotFoundConfig = {\n title: string;\n description: string;\n buttonLabel: string;\n};\n\nexport type TLogoutPageConfig = {\n logoutStartedLabel: string;\n logoutEndLabel: string;\n};\n\nexport type TAbonnomentPageConfig = {\n loadingLabel: string;\n};\n\nexport type TDetailPageConfig = {\n saveLabel: string;\n ingredientsLabel: string;\n buyProductButtonLabel: string;\n searchProductButtonLabel: string;\n colorLabel: string;\n glossLabel: string;\n glitterLabel: string;\n fromLabel: string;\n visualComparison: string;\n};\n\nexport type TPageConfigs = {\n home: THomePageConfig;\n paywall: TPaywallConfig;\n logout: TLogoutPageConfig;\n detail: TDetailPageConfig;\n abonnement: TAbonnomentPageConfig;\n notFound: TPageNotFoundConfig;\n confirmEmailAuthLink: TConfirmEmailAuthLinkPageConfig;\n register: TRegisterPageConfig;\n forgotPassword: TForgotPasswordPageConfig;\n setNewPassword: TSetNewPasswordPageConfig;\n login: TLoginPageConfig;\n tutorial: TTutorialPageConfig;\n search: TSearchPageConfig;\n matches: TMatchPageConfig;\n info: TInfoPage[];\n accountPage: TAccountPageConfig;\n registerSearch: TRegisterSearchPageConfig;\n};\n\nexport type TRegisterSearchPageConfig = {\n titleOne: string;\n titleTwo: string;\n titleThree: string;\n showMeLabel: string;\n showMeTheProduct: string;\n searchingLabel: string;\n foundItLabel: string;\n variantOne: {\n titleOne: string;\n titleTwo: string;\n titleThree: string;\n showMeLabel: string;\n showMeTheProduct: string;\n searchingLabel: string;\n foundItLabel: string;\n };\n};\n\nexport type TAccountPageConfig = {\n createdAtLabel: string;\n nextExtensionLabel: string;\n deleteAccountButtonLabel: string;\n title: string;\n cancelDeleteAccountLabel: string;\n endsAtLabel: string;\n deleteAccountTitle: string;\n buyPremiumButtonLabel: string;\n manageSubscriptionButtonLabel: string;\n deleteFreeAccountDescription: string;\n deleteAccountDescription: string;\n deleteAcccountButtonLabel: string;\n};\n\nexport type TInfoPageSection = {\n id: string;\n title: string;\n paragraphs: string[];\n tables: TInfoPageTable[];\n};\n\nexport type TInfoPageTable = {\n title: string;\n headerColumns: string[];\n rows: TInfoPageTableRow[];\n};\n\nexport type TInfoPageTableRow = {\n [key: string]: string;\n};\n\nexport type TInfoPage = {\n urlKey: string;\n pageTitle: string;\n sections: TInfoPageSection[];\n};\n\nexport type TFilterCategories = {\n name: string;\n value: string;\n imageUrl: string;\n labelKey: string;\n};\n\nexport type TLangConfig = {\n navigation: TNavigationConfig;\n components: TComponentConfig;\n pages: TPageConfigs;\n};\n\nexport type TRemoteConfig = {\n deConfig: TLangConfig;\n enConfig: TLangConfig;\n searchSuggestions: string[];\n};\n\nexport type TCardRefs = {\n [key: string]: React.RefObject;\n};\n\nexport type TGaEventParameters = {\n [key: string]: string | ((value: any) => void);\n};\n\nexport enum EIntentType {\n NAILS = \"Nails\",\n LIPS = \"Lips\",\n BARCODE = \"Barcode\",\n INFORMATION = \"Information\",\n}\n\nexport enum ELoadedLevel {\n LOADING = 1,\n LOADED = 2,\n ERROR = 3,\n None = 4,\n}\n\nexport enum EErrorType {\n UserError = \"UserError\",\n ApiError = \"ApiError\",\n Exception = \"Exception\",\n FirebaseError = \"FirebaseError\",\n}\n\nexport type TFirebaseError = {\n code: string;\n customData: Record;\n name: string;\n};\n\nexport type TError = {\n type: EErrorType;\n message: string;\n userMessage: string;\n};\n\nexport type TLoggedInUser = {\n status: ELoadedLevel;\n user: IUser | null;\n hasSubscription?: boolean;\n};\n\ninterface IUser extends User {\n createdAt: string;\n}\n\ndeclare global {\n interface Window {\n gtag: (\n type: string,\n eventName: string,\n parameters: TGaEventParameters\n ) => void;\n REACT_APP_SCANDIT_KEY: string;\n VITE_SCANDIT_KEY: string;\n REACT_APP_TEALIUM_ENVIRONMENT: string; // still set to react app, as this was used before and used on the environments\n }\n}\n\nexport enum ERoutePaths {\n HOME = \"/\",\n SEARCH = \"/de/suche\",\n DETAIL = \"/de/detail\",\n MATCHES = \"/de/matches\",\n INFO = \"/de/info\",\n ACCOUNT = \"/de/account\",\n REGISTER_SEARCH = \"/de/register-search\",\n TUTORIAL = \"/de/tutorial\",\n LOGIN = \"/de/login\",\n REGISTER = \"/de/register\",\n FORGOT_PASSWORD = \"/de/forgot-password\",\n SET_NEW_PASSWORD = \"/de/set-new-password\",\n CONFIRM_EMAIL_AUTH_LINK = \"/de/confirm-email-auth-link\",\n THANK_YOU = \"/de/thank-you\",\n NOT_FOUND = \"/de/not-found\",\n LOGOUT = \"/de/logout\",\n ABONNOMENT = \"/de/abonnement\",\n PICK_SCANNER = \"/de/scanner/color-match?mode=choose\",\n COLORMATCH_PICK_CATEGORY = \"/de/scanner/pick-categroy\",\n COLORMATCH = \"/de/scanner/color-match\",\n COLORMATCH_UPLOAD = \"/de/scanner/upload\",\n INSTOREMATCH = \"/de/scanner/instore-match\",\n}\n","export const getRequest = async (url: string) => {\n const response = await fetch(url);\n\n if (!response.ok || response.status !== 200) {\n throw new Error(`Error: ${response.status} ${response.statusText}`);\n }\n\n const data = await response.json();\n return data;\n};\n","import { getRequest } from \"./getRequest\";\n\nexport const checkIfUserIsSubscribed = async (): Promise => {\n try {\n const searchUrl = `${\n import.meta.env.VITE_BACKEND_URL\n }/checkUserHasSubscription`;\n\n const isSubscribed = await getRequest(searchUrl);\n return isSubscribed;\n } catch (error) {\n console.log(error); // TODO show this to the user\n return false;\n }\n};\n","import { atom } from \"recoil\";\nimport { ELoadedLevel, TLoggedInUser } from \"../../types\";\nimport { checkIfUserIsSubscribed } from \"../../api/checkIfUserIsSubscribedRequest\";\n\nconst setUserSubscriptionStatus = (\n setSelf: (arg0: any) => void,\n newUserState: TLoggedInUser | null\n) =>\n checkIfUserIsSubscribed()\n .then((hasSubscription) => {\n setSelf({\n ...newUserState,\n hasSubscription,\n });\n })\n .catch((error) => console.log(error));\n\nexport const userAtom = atom({\n key: \"userAtom\",\n default: {\n status: ELoadedLevel.LOADING,\n user: null,\n hasSubscription: false,\n },\n effects: [\n ({ onSet, setSelf }) => {\n onSet((newUserState, oldUserState) => {\n const oldUser = oldUserState as TLoggedInUser; // TODO: dirty fix it\n if (\n (!oldUserState && newUserState?.user?.uid) ||\n newUserState?.user?.uid !== oldUser?.user?.uid\n ) {\n setUserSubscriptionStatus(setSelf, newUserState);\n } else {\n setSelf(newUserState);\n }\n });\n },\n ],\n});\n","// Import the functions you need from the SDKs you need\nimport { initializeApp } from \"firebase/app\";\nimport { getFirestore } from \"firebase/firestore\";\nimport { getAnalytics } from \"firebase/analytics\";\n\n// TODO: Add SDKs for Firebase products that you want to use\n// https://firebase.google.com/docs/web/setup#available-libraries\n\n// Your web app's Firebase configuration\n// For Firebase JS SDK v7.20.0 and later, measurementId is optional\nconst firebaseConfig = {\n apiKey: import.meta.env.VITE_FIREBASE_API_KEY,\n authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,\n projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,\n storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,\n messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,\n appId: import.meta.env.VITE_FIREBASE_APP_ID,\n measurementId: import.meta.env.VITE_FIREBASE_MEASUREMENT_ID,\n};\n\n// Initialize Firebase\nexport const app = initializeApp(firebaseConfig);\nexport const analytics = getAnalytics(app);\nexport const db = getFirestore(app);\n","import { atom } from \"recoil\";\n\nexport const routeToRedirectToAfterLoginAtom = atom({\n key: \"routeToRedirectToAfterLoginAtom\",\n default: null,\n});\n","import { getAuth, onAuthStateChanged } from \"firebase/auth\";\nimport { ReactNode, useEffect } from \"react\";\nimport { Navigate, Outlet, useLocation } from \"react-router-dom\";\nimport { useRecoilState, useRecoilValue, useSetRecoilState } from \"recoil\";\nimport { deleteCookie, ECookie, setCookie } from \"../shared\";\nimport { userAtom } from \"../state/atoms/userAtom\";\nimport { app } from \"../thridparty/firebase/firebaseInit\";\nimport { ELoadedLevel } from \"../types\";\nimport { LoadingPage } from \"../pages/LoadingPage\";\nimport { captureException } from \"@sentry/react\";\nimport { routeToRedirectToAfterLoginAtom } from \"../state/atoms/routeToRedirectToAfterLoginAtom\";\n\nexport const RouteGuard = ({ children }: { children: ReactNode }) => {\n const setUser = useSetRecoilState(userAtom);\n const [routeToRedirectTo, setRouteToRedirectTo] = useRecoilState(\n routeToRedirectToAfterLoginAtom\n );\n\n useEffect(() => {\n onAuthStateChanged(getAuth(app), async (_user) => {\n try {\n if (!_user) {\n deleteCookie(ECookie.AccessToken);\n setUser((prev) => ({\n ...prev,\n status: ELoadedLevel.ERROR,\n user: null,\n }));\n return;\n }\n\n const idToken = await _user.getIdToken(true);\n\n if (!idToken) {\n console.log(\"No id Token found\");\n return;\n }\n setCookie(ECookie.AccessToken, idToken, 30);\n setUser((prev) => ({\n ...prev,\n status: ELoadedLevel.LOADED,\n user: JSON.parse(JSON.stringify(_user)),\n }));\n } catch (error) {\n captureException(error);\n }\n });\n }, [setUser]);\n\n return <>{children};\n};\n\nexport const ProtectedRoute = ({\n redirectPath = \"/de/login\",\n children,\n}: {\n redirectPath?: string;\n children?: React.ReactNode;\n}): JSX.Element => {\n const user = useRecoilValue(userAtom);\n\n const [routeToRedirectTo, setRouteToRedirectTo] = useRecoilState(\n routeToRedirectToAfterLoginAtom\n );\n const { search } = useLocation();\n\n if (user?.status === ELoadedLevel.LOADING) {\n return ;\n }\n\n if (!user || !user.user) {\n const pathToRedirect = window.location.pathname;\n setRouteToRedirectTo(pathToRedirect + search);\n return ;\n }\n\n if (user && routeToRedirectTo) {\n const sendTo = routeToRedirectTo;\n setRouteToRedirectTo(null);\n return ;\n }\n\n return children ? <>{children} : ;\n};\n","import { useEffect } from \"react\";\nimport { useLocation } from \"react-router-dom\";\n\nexport default function ScrollToTop() {\n const { pathname } = useLocation();\n\n useEffect(() => {\n window.scrollTo(0, 0);\n }, [pathname]);\n\n return null;\n}\n","import { Suspense } from \"react\";\nimport { Outlet } from \"react-router-dom\";\nimport { Footer } from \"../components\";\nimport { GlobalErrorDialog } from \"../components/dialogs/GlobalErrorDialog\";\nimport { LoadingPage } from \"./LoadingPage\";\n\nimport { RouteGuard } from \"../components/RouteGuard\";\nimport ScrollToTop from \"../v2/components/helper/ScrollToTop\";\n\nexport const Root = () => {\n return (\n }>\n \n \n
\n
\n

\n Wir sind bald zurück - bleibt gespannt!\n

\n

\n Eure Matchies\n

\n
\n
\n \n