All files / src/pages/AcquirerPortal/LegalDocuments/LegalDocumentDetail/components HistorySidePanel.tsx

88.46% Statements 23/26
81.81% Branches 9/11
100% Functions 6/6
85.71% Lines 18/21

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92                                        6x                         259x         259x   259x 259x     259x 38x 30x 30x 30x     8x   8x       8x 8x       259x                               259x                 259x   56x    
import { useEffect, useState } from "react";
import GiveSidePanel from "@shared/SidePanel/GiveSidePanel";
import { useCustomThemeV2 } from "@theme/hooks/useCustomThemeV2";
import { useVersionHistory } from "../../api/useLegalDocuments";
import { HistoryContent } from "./HistoryElements";
 
interface HistorySidePanelProps {
  open: boolean;
  onClose: () => void;
  documentID?: number;
  /** versionID of the version currently being viewed (highlighted row). */
  activeVersionID?: number;
  onSelectVersion: (versionID: number) => void;
  onEdit?: () => void;
  editDisabled?: boolean;
  isEditLoading?: boolean;
  /** Measured page-banner height so the panel sits beneath it. */
  bannerHeight?: number;
}
 
const ANIMATION_DURATION = 300;
 
export default function HistorySidePanel({
  open,
  onClose,
  documentID,
  activeVersionID,
  onSelectVersion,
  onEdit,
  editDisabled,
  isEditLoading,
  bannerHeight,
}: HistorySidePanelProps) {
  const { isMobileView } = useCustomThemeV2();
  const {
    data: versions = [],
    isLoading,
    isError,
  } = useVersionHistory(open ? documentID : undefined);
 
  const [shouldRender, setShouldRender] = useState(false);
  const [isAnimatedIn, setIsAnimatedIn] = useState(false);
 
  // Keep the node mounted through the slide-out animation before unmounting.
  useEffect(() => {
    if (!open) {
      setIsAnimatedIn(false);
      const timeout = setTimeout(() => setShouldRender(false), ANIMATION_DURATION);
      return () => clearTimeout(timeout);
    }
 
    setShouldRender(true);
    // Run the enter animation on the frame after mount.
    Iif (typeof requestAnimationFrame === "undefined") {
      setIsAnimatedIn(true);
      return;
    }
    const raf = requestAnimationFrame(() => setIsAnimatedIn(true));
    return () => cancelAnimationFrame(raf);
  }, [open]);
 
  const content = (
    <HistoryContent
      versions={versions}
      isLoading={isLoading}
      isError={isError}
      activeVersionID={activeVersionID}
      onSelectVersion={onSelectVersion}
      onClose={onClose}
      onEdit={onEdit}
      editDisabled={editDisabled}
      isEditLoading={isEditLoading}
      bannerHeight={bannerHeight}
      isOpen={isAnimatedIn}
    />
  );
 
  // Mobile: bottom sheet.
  Iif (isMobileView) {
    return (
      <GiveSidePanel open={open} onClose={onClose} anchor="bottom">
        {content}
      </GiveSidePanel>
    );
  }
 
  // Desktop: inline sticky panel; only mounted while visible/animating.
  if (!shouldRender) return null;
 
  return content;
}