\n \n \n );\n};\n","import { ChevronLeftIcon, ChevronRightIcon } from \"@heroicons/react/24/outline\";\nimport { createRef, useEffect, useState } from \"react\";\n// import { trackImageSlideChange } from \"../../Tracking\";\nimport { classNames } from \"../../shared\";\nimport { useElementOnScreen } from \"../../hooks/useElementOnScreen\";\nimport { useLocation } from \"react-router-dom\";\ntype TImageCarousellProps = {\n images: string[];\n};\n\ntype TImageRefs = {\n [key: string]: React.RefObject;\n};\n\nexport const ImageCarousell = ({\n images = [],\n}: TImageCarousellProps): JSX.Element => {\n // We will start by storing the index of the current image in the state.\n const [currentImage, setCurrentImage] = useState(0);\n const location = useLocation();\n\n // We are using react ref to 'tag' each of the images. Below will create an array of\n // objects with numbered keys. We will use those numbers (i) later to access a ref of a\n // specific image in this array.\n const refs = images.reduce((acc: TImageRefs, val, i) => {\n acc[i] = createRef();\n return acc;\n }, {});\n\n useEffect(() => {\n setCurrentImage(0);\n scrollToImage(0);\n }, [location, setCurrentImage]);\n\n const scrollToImage = (i: number) => {\n // TODO DUP-232 remove if confirmed by max\n // trackImageSlideChange(i);\n // First let's set the index of the image we want to see next\n setCurrentImage(i);\n // Now, this is where the magic happens. We 'tagged' each one of the images with a ref,\n // we can then use built-in scrollIntoView API to do eaxactly what it says on the box - scroll it into\n // your current view! To do so we pass an index of the image, which is then use to identify our current\n // image's ref in 'refs' array above.\n refs[i]?.current?.scrollIntoView({\n // Defines the transition animation.\n behavior: \"smooth\",\n // Defines vertical alignment.\n block: \"nearest\",\n // Defines horizontal alignment.\n inline: \"start\",\n });\n };\n\n // Some validation for checking the array length could be added if needed\n const totalImages = images.length;\n\n // Below functions will assure that after last image we'll scroll back to the start,\n // or another way round - first to last in previousImage method.\n const nextImage = () => {\n if (currentImage >= totalImages - 1) {\n scrollToImage(0);\n } else {\n scrollToImage(currentImage + 1);\n }\n };\n\n const previousImage = () => {\n if (currentImage === 0) {\n scrollToImage(totalImages - 1);\n } else {\n scrollToImage(currentImage - 1);\n }\n };\n\n // Tailwind styles. Most importantly notice position absolute, this will sit relative to the carousel's outer div.\n const arrowStyle =\n \"absolute text-white text-2xl z-10 h-10 w-10 rounded-full opacity-75 flex items-center justify-center\";\n\n // Let's create dynamic buttons. It can be either left or right. Using\n // isLeft boolean we can determine which side we'll be rendering our button\n // as well as change its position and content.\n const sliderControl = (isLeft?: boolean) => (\n \n \n {isLeft ? (\n \n ) : (\n \n )}\n \n \n );\n\n return (\n // Images are placed using inline flex. We then wrap an image in a div\n // with flex-shrink-0 to stop it from 'shrinking' to fit the outer div.\n // Finally the image itself will be 100% of a parent div. Outer div is\n // set with position relative, so we can place our cotrol buttons using\n // absolute positioning on each side of the image.\n
\n );\n};\n","//...\nimport * as Sentry from \"@sentry/react\";\nimport { createBrowserRouter } from \"react-router-dom\";\n\nexport const initSentry = () => {\n if (import.meta.env.VITE_IS_DEVELOPMENT) {\n return;\n }\n\n Sentry.init({\n dsn: \"https://091be180670e065b0599233568a37716@o4506790987300864.ingest.sentry.io/4506790989266944\",\n integrations: [\n Sentry.browserTracingIntegration(),\n Sentry.replayIntegration({\n maskAllText: false,\n blockAllMedia: false,\n }),\n ],\n environment: import.meta.env.VITE_FIREBASE_PROJECT_ID,\n // Performance Monitoring\n tracesSampleRate: 1.0, // Capture 100% of the transactions\n // Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled\n tracePropagationTargets: [\"localhost\", /^https:\\/\\/yourserver\\.io\\/api/],\n // Session Replay\n replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.\n replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.\n });\n};\n\nexport const sentryCreateBrowserRouter =\n Sentry.wrapCreateBrowserRouter(createBrowserRouter);\n","import i18n from \"i18next\";\nimport { initReactI18next } from \"react-i18next\";\nimport de from \"./de.json\";\nimport en from \"./en.json\";\n\n// the translations\n// (tip move them in a JSON file and import them,\n// or even better, manage them separated from your code: https://react.i18next.com/guides/multiple-translation-files)\nconst resources = {\n de: {\n translation: de,\n },\n en: {\n translation: en,\n },\n};\n\nconst languages = navigator.languages || navigator.language;\n\ni18n\n .use(initReactI18next) // passes i18n down to react-i18next\n .init({\n resources,\n supportedLngs: [\"de\", \"en\"],\n lng: languages[0] || \"de\",\n fallbackLng: \"de\", // language to use, more information here: https://www.i18next.com/overview/configuration-options#languages-namespaces-resources\n // you can use the i18n.changeLanguage function to change the language manually: https://www.i18next.com/overview/api#changelanguage\n // if you're using a language detector, do not define the lng option\n\n interpolation: {\n escapeValue: false, // react already safes from xss\n },\n });\n\nexport default i18n;\n","export const ProductDetailPageSkeletonLoading = () => {\n return (\n
\n
\n \n \n \n \n \n
\n
\n \n \n \n
\n \n
\n
\n
\n );\n};\n","// import { aboutUsDe, aboutUsEn } from \"./aboutUs\";\n// import { contact, contactEn } from \"./contact\";\n// import { dataPolicy, dataPolicyEn } from \"./dataPolicy\";\n// import { imprint, imprintEn } from \"./imprint\";\n// import { terms, termsEn } from \"./terms\";\n\nimport aboutUsDe from \"./aboutUs/aboutUsDe.json\";\nimport aboutUsEn from \"./aboutUs/aboutUsEn.json\";\n\nimport contactDe from \"./contact/contactDe.json\";\nimport contactEn from \"./contact/contactEn.json\";\n\nimport faqDe from \"./faq/faqDe.json\";\nimport faqEn from \"./faq/faqEn.json\";\n\nimport dataPolicyDe from \"./dataPolicy/dataPolicyDe.json\";\nimport dataPolicyEn from \"./dataPolicy/dataPolicyEn.json\";\n\nimport imprintDe from \"./imprint/imprintDe.json\";\nimport imprintEn from \"./imprint/imprintEn.json\";\n\nimport termsDe from \"./terms/termsDe.json\";\nimport termsEn from \"./terms/termsEn.json\";\n\nexport const infoPagesDe = [\n aboutUsDe,\n contactDe,\n faqDe,\n imprintDe,\n dataPolicyDe,\n termsDe,\n];\nexport const infoPagesEn = [\n aboutUsEn,\n contactEn,\n faqEn,\n imprintEn,\n dataPolicyEn,\n termsEn,\n];\n\nexport const infoPages: { [key: string]: any } = {\n de: infoPagesDe,\n en: infoPagesEn,\n};\n\nexport const getInfoPages = (lang: string) => {\n console.log(infoPages, lang);\n if (\n lang === \"en-US\" ||\n lang === \"en\" ||\n lang === \"en-GB\" ||\n lang === \"en-EN\"\n ) {\n return infoPages.en;\n }\n if (lang === \"de-De\" || lang === \"de-DE\") {\n return infoPages.de;\n }\n\n if (infoPages[lang]) {\n return infoPages[lang];\n }\n\n return infoPages.de;\n};\n","export function randomId() {\n return Math.random().toString(36).substr(2, 9);\n}\n","import { useLocation, useNavigate, useSearchParams } from \"react-router-dom\";\nimport { useEffect } from \"react\";\nimport { ChevronLeftIcon } from \"@heroicons/react/24/outline\";\nimport { getInfoPages } from \"./configs/infoPages\";\nimport { useTranslation } from \"react-i18next\";\nimport { TInfoPage } from \"../../../types\";\nimport { randomId } from \"../../utils/randomId\";\n\nexport const InfoPage = () => {\n const location = useLocation();\n\n const { i18n } = useTranslation();\n\n const _infoPages: TInfoPage[] = getInfoPages(i18n.language);\n\n const page = _infoPages.find(\n (page: any) => page.urlKey === location.pathname\n );\n\n const [searchParams] = useSearchParams();\n const jumpTo = searchParams.get(\"jumpTo\");\n const naviagte = useNavigate();\n\n useEffect(() => {\n if (!jumpTo) {\n window.scrollTo(0, 0);\n return;\n }\n const timeOut = setTimeout(() => {\n const ele = document.getElementById(jumpTo);\n if (!ele) return;\n window.scrollTo(ele.offsetLeft, ele.offsetTop);\n }, 100);\n\n return () => {\n clearTimeout(timeOut);\n };\n }, [jumpTo]);\n\n const onClickBack = () => {\n naviagte(-1);\n };\n\n return (\n
\n \n );\n};\n","import { Link } from \"react-router-dom\";\nimport HeroImageSection from \"./components/HeroImageSection\";\nimport { HeroImageSmallSection } from \"./components/HeroImageSmallSection\";\nimport ImageTextSection from \"./components/ImageTextSection\";\nimport { NumberShowCaseSection } from \"./components/NumberShowCaseSection\";\nimport { TitleShowCaseSection } from \"./components/TitleShowCaseSection\";\nimport { VideoTextSection } from \"./components/VideoTextSection\";\nimport { ChevronLeftIcon } from \"@heroicons/react/24/outline\";\nimport { t } from \"i18next\";\nexport const AboutUsPage = () => {\n return (\n
\n
\n
\n \n \n \n
\n
About Us
\n
\n
\n \n
\n \n
\n
\n \n
\n\n \n\n
\n \n
\n\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n \n
\n
\n );\n};\n","import { useEffect } from \"react\";\n\nexport const usePreventScrollOnTouch = (\n canvasRef: React.RefObject\n) => {\n useEffect(() => {\n function stopTouchScrolling(canvas: any) {\n // Prevent scrolling when touching the canvas\n document.body.addEventListener(\n \"touchstart\",\n function (e) {\n if (e.target == canvas) {\n e.preventDefault();\n }\n },\n { passive: false }\n );\n document.body.addEventListener(\n \"touchend\",\n function (e) {\n if (e.target == canvas) {\n e.preventDefault();\n }\n },\n { passive: false }\n );\n document.body.addEventListener(\n \"touchmove\",\n function (e) {\n if (e.target == canvas) {\n e.preventDefault();\n }\n },\n { passive: false }\n );\n }\n\n stopTouchScrolling(canvasRef.current);\n }, []);\n};\n","import { Position } from \"../ImageUploadColorMatchPage\";\n\nexport function checkIfCircleIsClicked(\n event: any,\n canvas: HTMLCanvasElement,\n position: Position\n): boolean {\n let x: number;\n let y: number;\n\n if (event.clientX) {\n const rect = canvas.getBoundingClientRect();\n x = event.clientX - rect.left;\n y = event.clientY - rect.top;\n } else {\n const touch = event.touches[0];\n const rect = canvas.getBoundingClientRect();\n x = touch.clientX - rect.left;\n y = touch.clientY - rect.top;\n }\n\n const dx = position.x - x;\n const dy = position.y - y;\n\n // Check if the mouse is inside the circle\n if (Math.sqrt(dx * dx + dy * dy) < 50) {\n return true;\n }\n return false;\n}\n","export const getTouchPosition = (event: any, canvas: HTMLCanvasElement) => {\n let x: number;\n let y: number;\n\n if (event.clientX) {\n const rect = canvas.getBoundingClientRect();\n x = event.clientX - rect.left;\n y = event.clientY - rect.top;\n } else {\n const touch = event.touches[0];\n const rect = canvas.getBoundingClientRect();\n x = touch.clientX - rect.left;\n y = touch.clientY - rect.top;\n }\n\n return { x, y };\n};\n","export const calculateCanvasDimensions = (\n container: HTMLDivElement,\n image: HTMLImageElement\n) => {\n const screenWidth = container.clientWidth;\n const screenHeight = container.clientHeight;\n\n const imageAspectRatio = image.width / image.height;\n let canvasWidth = screenWidth;\n let canvasHeight = screenWidth / imageAspectRatio;\n\n if (canvasHeight > screenHeight) {\n canvasHeight = screenHeight;\n canvasWidth = screenHeight * imageAspectRatio;\n }\n\n return { canvasWidth, canvasHeight };\n};\n","export function drawCrossair(\n context: CanvasRenderingContext2D,\n x: number,\n y: number\n) {\n context.beginPath();\n context.moveTo(x - 15, y);\n context.lineTo(x - 6, y);\n context.moveTo(x + 6, y);\n context.lineTo(x + 15, y);\n context.moveTo(x, y - 15);\n context.lineTo(x, y - 6);\n context.moveTo(x, y + 6);\n context.lineTo(x, y + 15);\n context.strokeStyle = \"white\";\n context.lineWidth = 2;\n context.stroke();\n}\n","import React, { useEffect, useRef, useState } from \"react\";\nimport { useLocation, useNavigate } from \"react-router-dom\";\nimport { ERoutePaths } from \"../../../../types\";\nimport { ChevronLeftIcon } from \"@heroicons/react/24/outline\";\n\nimport { pickColor } from \"./utils/pickColor\";\nimport { Button } from \"../../../components/buttons/Button\";\nimport { t } from \"i18next\";\nimport { usePreventScrollOnTouch } from \"../../../../hooks/usePreventScrollOnTouch\";\nimport { checkIfCircleIsClicked } from \"./utils/checkIfCircleIsClicked\";\nimport { getTouchPosition } from \"./utils/getTouchPosition\";\nimport { calculateCanvasDimensions } from \"./utils/calculateCanvasDimensions\";\nimport { drawCircle } from \"./utils/drawCircle\";\nimport { drawCrossair } from \"./utils/drawCrossair\";\n\nexport interface Position {\n x: number;\n y: number;\n}\n\nconst ImageUploadColorMatchPage = () => {\n const location = useLocation();\n const imageData = location.state.imageDataUrl;\n const canvasRef = useRef(null);\n const containerRef = useRef(null);\n const navigate = useNavigate();\n const currentColor = useRef(null);\n const [dragging, setDragging] = useState(false);\n const [position, setPosition] = useState({ x: 100, y: 100 });\n const [chosenImage, setImage] = useState(null);\n\n usePreventScrollOnTouch(canvasRef);\n\n if (!imageData) {\n navigate(ERoutePaths.COLORMATCH);\n return null;\n }\n\n useEffect(() => {\n window.addEventListener(\"colorPicked\", (data: any) => {\n currentColor.current = data.detail;\n });\n }, []);\n\n useEffect(() => {\n const canvas = canvasRef.current;\n const context = canvas?.getContext(\"2d\");\n\n if (canvas && context) {\n const image = new Image();\n image.src = imageData;\n\n image.onload = () => {\n if (!containerRef.current) return console.log(\"containerRef is null\");\n\n const { canvasHeight, canvasWidth } = calculateCanvasDimensions(\n containerRef.current,\n image\n );\n\n canvas.width = canvasWidth;\n canvas.height = canvasHeight;\n setPosition({ x: canvasWidth / 2, y: canvasHeight / 2 });\n context.drawImage(image, 0, 0, canvasWidth, canvasHeight);\n pickColor(position.x, position.y, context);\n drawCrossair(context, position.x, position.y);\n setImage(image);\n };\n }\n }, [imageData]);\n\n const handleMouseDown = (event: any) => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n\n if (checkIfCircleIsClicked(event, canvas, position)) {\n setDragging(true);\n }\n };\n\n const handleMouseUp = () => {\n setDragging(false);\n };\n\n const handleMouseMove = (event: any) => {\n if (dragging) {\n const canvas = canvasRef.current;\n if (!canvas) return;\n\n const { x, y } = getTouchPosition(event, canvas);\n\n setPosition({ x, y });\n }\n };\n\n const onPickColor = () => {\n navigate(`/de/scanner/pick-categroy/${currentColor.current}`);\n };\n\n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas) return console.log(\"canvas is null\");\n\n const context = canvas.getContext(\"2d\");\n if (!context) return console.log(\"context is null\");\n\n context.clearRect(0, 0, canvas.width, canvas.height);\n\n if (chosenImage) {\n context.drawImage(chosenImage, 0, 0, canvas.width, canvas.height);\n }\n\n pickColor(position.x, position.y, context);\n drawCrossair(context, position.x, position.y);\n }, [position]);\n\n return (\n
\n
\n
\n Color Match\n
\n navigate(`${ERoutePaths.COLORMATCH}?mode=color`)}\n >\n Close panel\n \n \n\n