From 8705e065f6f38f57122e5be456ec9fa9cd3804b7 Mon Sep 17 00:00:00 2001 From: Gigin George Date: Thu, 22 Aug 2024 18:09:02 +0530 Subject: [PATCH 1/3] Fix Scroll Issue with Pressure Sores Popup --- src/CAREUI/display/PopupModal.tsx | 59 ++++++++++++++----- .../Sections/PressureSore/PressureSore.tsx | 4 +- 2 files changed, 47 insertions(+), 16 deletions(-) diff --git a/src/CAREUI/display/PopupModal.tsx b/src/CAREUI/display/PopupModal.tsx index 37b5719d9bd..25e7c3c0a34 100644 --- a/src/CAREUI/display/PopupModal.tsx +++ b/src/CAREUI/display/PopupModal.tsx @@ -13,6 +13,12 @@ type Props = { onSubmit?: () => void; }; +type Position = + | { left: number; top: number } + | { right: number; bottom: number } + | { left: number; bottom: number } + | { right: number; top: number }; + export default function PopupModal(props: Props) { const { t } = useTranslation(); const isMobile = useBreakpoints({ default: true, lg: false }); @@ -43,7 +49,7 @@ export default function PopupModal(props: Props) { const DesktopView = (props: Props) => { const { t } = useTranslation(); - const [position, setPosition] = useState({ x: 0, y: 0 }); + const [position, setPosition] = useState({ left: 0, top: 0 }); const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 }); const modal = useRef(null); const [children, setChildren] = useState(props.children); @@ -72,15 +78,36 @@ const DesktopView = (props: Props) => { const yRelative = currentMousePosition.y; const containerHeight = window.innerHeight; const containerWidth = window.innerWidth; - const top = - yRelative + modalHeight > containerHeight - ? yRelative - modalHeight - : yRelative; - const left = - xRelative + modalWidth > containerWidth - ? xRelative - modalWidth - : xRelative; - setPosition({ x: left, y: top }); + const verticalCenter = containerHeight / 2; + const horizontalCenter = containerWidth / 2; + // place the modal on the bottom right of the mouse + // if the modal is going out of the screen, place it on the top left of the mouse + // if the modal is still going out of the screen, place it on the bottom left of the mouse + // if the modal is still going out of the screen, place it on the top right of the mouse + console.log( + xRelative, + xRelative + modalWidth, + yRelative, + yRelative + modalHeight, + containerWidth, + containerHeight, + ); + let position; + if (xRelative > horizontalCenter) { + position = { right: containerWidth - xRelative }; + } else { + position = { left: xRelative }; + } + if (yRelative > verticalCenter) { + position = { ...position, bottom: containerHeight - yRelative }; + } else { + position = { ...position, top: yRelative }; + } + const mountingTo = Object.keys(position).reduce((acc, key) => { + return `${acc} ${key}`; + }, ""); + console.log("mounting to ", mountingTo); + setPosition(position); } document.addEventListener("mousedown", handleOutsideClick); @@ -99,13 +126,17 @@ const DesktopView = (props: Props) => { }; }, []); + const positionAttributes = Object.entries(position).reduce( + (acc, [key, value]) => { + return { ...acc, [key]: `${value}px` }; + }, + {}, + ); + return (
{ // TODO: wrap with a div with relative class so that the editor sticks on scroll. return ( - <> +
{ } regionText={(r) => regionPushScore(r)?.toString() ?? ""} /> - +
); }; From d374af0b25471aebbb27bbefaa3e836c05506704 Mon Sep 17 00:00:00 2001 From: Gigin George Date: Thu, 22 Aug 2024 19:21:18 +0530 Subject: [PATCH 2/3] Improve Computation to anchor next to the click --- src/CAREUI/display/PopupModal.tsx | 49 ++++++++----------- .../Sections/PressureSore/PressureSore.tsx | 8 ++- .../LogUpdate/components/PainChart.tsx | 10 ++-- 3 files changed, 34 insertions(+), 33 deletions(-) diff --git a/src/CAREUI/display/PopupModal.tsx b/src/CAREUI/display/PopupModal.tsx index 25e7c3c0a34..3b2ce314da0 100644 --- a/src/CAREUI/display/PopupModal.tsx +++ b/src/CAREUI/display/PopupModal.tsx @@ -9,6 +9,7 @@ type Props = { show: boolean; onHide: () => void; children: ReactNode; + anchorRef: React.RefObject; className?: string; onSubmit?: () => void; }; @@ -74,39 +75,30 @@ const DesktopView = (props: Props) => { const currentMousePosition = mousePosition; const modalHeight = modal.current?.clientHeight || 0; const modalWidth = modal.current?.clientWidth || 0; - const xRelative = currentMousePosition.x; - const yRelative = currentMousePosition.y; - const containerHeight = window.innerHeight; - const containerWidth = window.innerWidth; - const verticalCenter = containerHeight / 2; - const horizontalCenter = containerWidth / 2; - // place the modal on the bottom right of the mouse - // if the modal is going out of the screen, place it on the top left of the mouse - // if the modal is still going out of the screen, place it on the bottom left of the mouse - // if the modal is still going out of the screen, place it on the top right of the mouse - console.log( - xRelative, - xRelative + modalWidth, - yRelative, - yRelative + modalHeight, - containerWidth, - containerHeight, - ); + const clickX = currentMousePosition.x; + const clickY = currentMousePosition.y; + const windowHeight = window.innerHeight; + const windowWidth = window.innerWidth; + + const anchorPosition = props.anchorRef.current?.getBoundingClientRect(); + const anchorX = anchorPosition?.x || 0; + const anchorY = anchorPosition?.y || 0; + const verticalCenter = windowHeight / 2; + const horizontalCenter = windowWidth / 2; + const mountLeft = clickX - anchorX; + const mountTop = clickY - anchorY; + let position; - if (xRelative > horizontalCenter) { - position = { right: containerWidth - xRelative }; + if (clickX > horizontalCenter) { + position = { left: mountLeft - modalWidth }; } else { - position = { left: xRelative }; + position = { left: mountLeft }; } - if (yRelative > verticalCenter) { - position = { ...position, bottom: containerHeight - yRelative }; + if (clickY > verticalCenter) { + position = { ...position, top: mountTop - modalHeight }; } else { - position = { ...position, top: yRelative }; + position = { ...position, top: mountTop }; } - const mountingTo = Object.keys(position).reduce((acc, key) => { - return `${acc} ${key}`; - }, ""); - console.log("mounting to ", mountingTo); setPosition(position); } @@ -114,6 +106,7 @@ const DesktopView = (props: Props) => { return () => { document.removeEventListener("mousedown", handleOutsideClick); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [props.show]); useEffect(() => { diff --git a/src/Components/LogUpdate/Sections/PressureSore/PressureSore.tsx b/src/Components/LogUpdate/Sections/PressureSore/PressureSore.tsx index 8fd12518705..850d402e8d7 100644 --- a/src/Components/LogUpdate/Sections/PressureSore/PressureSore.tsx +++ b/src/Components/LogUpdate/Sections/PressureSore/PressureSore.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import PopupModal from "../../../../CAREUI/display/PopupModal"; import HumanBodyChart from "../../../../CAREUI/interactive/HumanChart"; import { SelectFormField } from "../../../Form/FormFields/SelectFormField"; @@ -17,6 +17,7 @@ import { calculatePushScore } from "./utils"; const PressureSore = ({ log, onChange, readonly }: LogUpdateSectionProps) => { const value = log.pressure_sore ?? []; + const containerRef = useRef(null); const [current, setCurrent] = useState(); const regionPushScore = (region: IPressureSore["region"]) => { @@ -35,9 +36,10 @@ const PressureSore = ({ log, onChange, readonly }: LogUpdateSectionProps) => { // TODO: wrap with a div with relative class so that the editor sticks on scroll. return ( -
+
setCurrent(undefined)} onSave={ @@ -88,6 +90,7 @@ export default PressureSore; type RegionEditorProps = { show: boolean; value: IPressureSore; + anchorRef: React.RefObject; onCancel: () => void; onSave?: (value: IPressureSore) => void; }; @@ -106,6 +109,7 @@ const RegionEditor = (props: RegionEditorProps) => { (); + const containerRef = useRef(null); const valueDescription = (region: IPainScale["region"]) => { const scale = pain.find((obj) => obj.region === region)?.scale; @@ -24,10 +25,11 @@ export default function PainChart({ pain, onChange }: Props) { }; return ( - <> +
setCurrent(undefined)} onSave={ onChange @@ -60,13 +62,14 @@ export default function PainChart({ pain, onChange }: Props) { pain.find((p) => p.region === region)?.scale.toString() ?? "" } /> - +
); } type RegionEditorProps = { show: boolean; value: IPainScale; + anchorRef: React.RefObject; onCancel: () => void; onSave?: (value: IPainScale) => void; }; @@ -85,6 +88,7 @@ const RegionEditor = (props: RegionEditorProps) => { Date: Thu, 22 Aug 2024 19:35:16 +0530 Subject: [PATCH 3/3] remove todo comment from pressure sore component --- src/Components/LogUpdate/Sections/PressureSore/PressureSore.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Components/LogUpdate/Sections/PressureSore/PressureSore.tsx b/src/Components/LogUpdate/Sections/PressureSore/PressureSore.tsx index 850d402e8d7..a56457ef257 100644 --- a/src/Components/LogUpdate/Sections/PressureSore/PressureSore.tsx +++ b/src/Components/LogUpdate/Sections/PressureSore/PressureSore.tsx @@ -34,7 +34,6 @@ const PressureSore = ({ log, onChange, readonly }: LogUpdateSectionProps) => { } }; - // TODO: wrap with a div with relative class so that the editor sticks on scroll. return (