pages/ValuePartnership/PartnershipsPage/SlideView.jsxjavascript
import { useEffect, useRef, useState } from "react";
import PropTypes from "prop-types";
import { UIMCButton } from "@ui-marcom/react/button";
import { UIMCControlButton } from "@ui-marcom/react/control-button";
import { UIMCPagination } from "@ui-marcom/react/pagination";
// ui-marcom-pagination's own "compact" template renders a <ui-marcom-dropdown>
// for the page counter but never imports @ui-marcom/dropdown itself (likely a
// packaging oversight) - register it ourselves or the dropdown just sits
// inert/undefined (same fix as GlobeBottomNav.jsx; route-level code
// splitting means that page's own registration can't be relied on here).
import "@ui-marcom/dropdown";
import { QrCodeCanvas } from "./QrCodeCanvas";
import { resolveWebLink } from "./qrCodeLink";
import "./SlideView.scss";

/**
 * Fullscreen presentation-deck viewer, ported from value-slideview.js
 * (minus the QR/congress-app "save highlights" checkbox mode, which lives in
 * PresentationBrowser, and the manual `<link rel=preload>` injection, replaced
 * by the browser's own image decoding/caching). Mount with `key={ppt.id}` so
 * opening a different deck resets `page` cleanly instead of syncing it via effect.
 *
 * @param {Object} props
 * @param {{id: string, content: string, pictures: string[]}} props.ppt
 * @param {number} [props.initialPage=1]
 * @param {Object} props.labels
 * @param {function(): void} props.onClose
 */
// ported verbatim from value-slideview.js's __disclaimer block, which hard-
// codes this the same way (not content/labels-driven there either)
const COPYRIGHT_NOTICE = "Unrestricted © Siemens Healthineers AG, 2025";

export const SlideView = ({ ppt, initialPage = 1, labels, onClose }) => {
  const [page, setPage] = useState(initialPage);
  const [qrOpen, setQrOpen] = useState(false);
  const total = ppt.pictures.length;
  const webLink = resolveWebLink(ppt.webLink);

  // keeps the active thumbnail visible as `page` changes (Prev/Next,
  // thumbnail click, or a deep initialPage on mount) - .slide-view__thumbnails
  // scrolls independently of the rest of the bar, and nothing else keeps the
  // highlighted thumbnail (see --active in SlideView.scss) in view otherwise
  const activeThumbRef = useRef(null);
  useEffect(() => {
    activeThumbRef.current?.scrollIntoView({
      behavior: "smooth",
      inline: "center",
      block: "nearest",
    });
  }, [page]);

  return (
    <div className="slide-view">
      <div className="slide-view__slide">
        <img src={ppt.pictures[page - 1]} alt="" />

        {labels.showQRCode && webLink && (
          <UIMCButton
            className="slide-view__qr-trigger"
            variant="primary-cta"
            title={labels.showQRCode}
            onClick={() => setQrOpen(true)}>
            <ui-marcom-icon slot="prefix" icon="arrow-right-medium"></ui-marcom-icon>
            {labels.showQRCode}
          </UIMCButton>
        )}
      </div>

      <div className="slide-view__nav">
        <div className="slide-view__nav-buttons">
          <UIMCControlButton
            icon="home"
            title="Home"
            onClick={onClose}
            className="slide-view__nav-button--home"
          />
          <UIMCButton
            variant="standard"
            title={labels.backToOverview}
            onClick={onClose}
            className="slide-view__nav-button--back">
            <ui-marcom-icon slot="prefix" icon="arrow-long-left"></ui-marcom-icon>
            {labels.backToOverview}
          </UIMCButton>
          <UIMCPagination
            className="slide-view__pagination"
            variant="compact"
            totalItems={total}
            itemsPerPage={1}
            currentPage={page}
            i18n={{
              prev: labels.previous,
              next: labels.next,
              prevLabel: labels.previous,
              nextLabel: labels.next,
              separatorLabel: "of",
            }}
            onChange={(newPage) => setPage(newPage)}
          />
        </div>

        <div className="slide-view__thumbnails">
          {ppt.pictures.map((src, index) => {
            const isActive = index === page - 1;
            return (
              <div
                key={src}
                ref={isActive ? activeThumbRef : undefined}
                className={
                  isActive
                    ? "slide-view__thumbnail slide-view__thumbnail--active"
                    : "slide-view__thumbnail"
                }
                onClick={() => setPage(index + 1)}>
                <img src={src} alt="" loading="lazy" />
                <span>Slide {index + 1}</span>
              </div>
            );
          })}
        </div>

        <div className="slide-view__nav-meta">
          <span className="slide-view__copyright">{COPYRIGHT_NOTICE}</span>
        </div>
      </div>

      {qrOpen && (
        <div className="slide-view__qr-overlay" onClick={() => setQrOpen(false)}>
          <div className="slide-view__qr-card" onClick={(e) => e.stopPropagation()}>
            <h5>Scan your assets to read them later</h5>
            <QrCodeCanvas url={webLink} />
            <UIMCControlButton icon="close" title="Schließen" onClick={() => setQrOpen(false)} />
          </div>
        </div>
      )}
    </div>
  );
};

SlideView.propTypes = {
  ppt: PropTypes.shape({
    id: PropTypes.string,
    content: PropTypes.string,
    pictures: PropTypes.arrayOf(PropTypes.string).isRequired,
  }).isRequired,
  initialPage: PropTypes.number,
  labels: PropTypes.object.isRequired,
  onClose: PropTypes.func.isRequired,
};