Skip to content

Commit

Permalink
Refactor to use make zoom functionallity reusable
Browse files Browse the repository at this point in the history
  • Loading branch information
rithviknishad committed Sep 5, 2024
1 parent 5fa060e commit d7335b3
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 50 deletions.
97 changes: 97 additions & 0 deletions src/CAREUI/interactive/Zoom.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { createContext, ReactNode, useContext, useState } from "react";
import ButtonV2 from "../../Components/Common/components/ButtonV2";
import CareIcon from "../icons/CareIcon";

type ProviderValue = {
scale: number;
zoomIn: () => void;
zoomOut: () => void;
};

const ZoomContext = createContext<ProviderValue | null>(null);

type Props = {
initialScale?: number;
scaleRatio?: number;
children: ReactNode;
};

export const ZoomProvider = ({
initialScale = 1,
scaleRatio = 1.25,
children,
}: Props) => {
const [scale, setScale] = useState(initialScale);

return (
<ZoomContext.Provider
value={{
scale,
zoomIn: () => setScale((scale) => scale * scaleRatio),
zoomOut: () => setScale((scale) => scale / scaleRatio),
}}
>
{children}
</ZoomContext.Provider>
);
};

export const ZoomTransform = (props: {
children: ReactNode;
className?: string;
}) => {
const ctx = useContext(ZoomContext);

if (ctx == null) {
throw new Error("Component must be used with ZoomProvider");
}

return (
<div
className={props.className}
style={{
transform: `scale(${ctx.scale})`,
}}
>
{props.children}
</div>
);
};

export const ZoomControls = (props: { disabled?: boolean }) => {
const ctx = useContext(ZoomContext);

if (ctx == null) {
throw new Error("Component must be used with ZoomProvider");
}

return (
<div className="absolute bottom-8 right-8 flex flex-col items-center justify-center gap-1 rounded-full border border-secondary-400 bg-white p-0.5 shadow-lg md:flex-row-reverse md:gap-2">
<ButtonV2
disabled={props.disabled}
circle
variant="secondary"
size="small"
shadow={false}
className="p-2.5"
onClick={ctx.zoomIn}
>
<CareIcon icon="l-search-plus" className="text-lg" />
</ButtonV2>
<span className="text-sm font-semibold text-secondary-800">
{Math.round(ctx.scale * 100)}%
</span>
<ButtonV2
disabled={props.disabled}
circle
variant="secondary"
size="small"
shadow={false}
className="p-2.5"
onClick={ctx.zoomOut}
>
<CareIcon icon="l-search-minus" className="text-lg" />
</ButtonV2>
</div>
);
};
71 changes: 22 additions & 49 deletions src/CAREUI/misc/PrintPreview.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { ReactNode, useState } from "react";
import { ReactNode } from "react";
import ButtonV2 from "../../Components/Common/components/ButtonV2";
import CareIcon from "../icons/CareIcon";
import { classNames } from "../../Utils/utils";
import Page from "../../Components/Common/components/Page";
import useBreakpoints from "../../Common/hooks/useBreakpoints";
import { useTranslation } from "react-i18next";
import { ZoomControls, ZoomProvider, ZoomTransform } from "../interactive/Zoom";

type Props = {
children: ReactNode;
Expand All @@ -14,60 +16,31 @@ type Props = {

export default function PrintPreview(props: Props) {
const normalScale = useBreakpoints({ default: 0.44, md: 1 });
const [scale, setScale] = useState(normalScale);
const { t } = useTranslation();

return (
<Page title={props.title}>
<div className="mx-auto my-8 w-[50rem]">
<div className="top-0 z-20 flex gap-2 bg-secondary-100 px-2 py-4 xl:absolute xl:right-6 xl:top-8 xl:justify-end">
<ButtonV2 disabled={props.disabled} onClick={() => print()}>
<CareIcon icon="l-print" className="text-lg" />
Print
</ButtonV2>
</div>

<div
className="origin-top-left bg-white p-10 text-sm shadow-2xl transition-all duration-200 ease-in-out lg:origin-top print:transform-none"
style={{
transform: `scale(${scale})`,
}}
>
<div
id="section-to-print"
className={classNames("w-full", props.className)}
>
{props.children}
<ZoomProvider initialScale={normalScale}>
<div className="mx-auto my-8 w-[50rem]">
<div className="top-0 z-20 flex gap-2 bg-secondary-100 px-2 py-4 xl:absolute xl:right-6 xl:top-8 xl:justify-end">
<ButtonV2 disabled={props.disabled} onClick={print}>
<CareIcon icon="l-print" className="text-lg" />
{t("print")}
</ButtonV2>
</div>
</div>

<div className="absolute bottom-8 right-8 flex flex-col items-center justify-center gap-1 rounded-full border border-secondary-400 bg-white p-0.5 shadow-lg md:flex-row-reverse md:gap-2">
<ButtonV2
disabled={props.disabled}
circle
variant="secondary"
size="small"
shadow={false}
className="p-2.5"
onClick={() => setScale((scale) => scale * 1.25)}
>
<CareIcon icon="l-search-plus" className="text-lg" />
</ButtonV2>
<span className="text-sm font-semibold text-secondary-800">
{Math.round(scale * 100)}%
</span>
<ButtonV2
disabled={props.disabled}
circle
variant="secondary"
size="small"
shadow={false}
className="p-2.5"
onClick={() => setScale((scale) => scale / 1.25)}
>
<CareIcon icon="l-search-minus" className="text-lg" />
</ButtonV2>
<ZoomTransform className="origin-top-left bg-white p-10 text-sm shadow-2xl transition-all duration-200 ease-in-out lg:origin-top print:transform-none">
<div
id="section-to-print"
className={classNames("w-full", props.className)}
>
{props.children}
</div>
</ZoomTransform>

<ZoomControls />
</div>
</div>
</ZoomProvider>
</Page>
);
}
3 changes: 2 additions & 1 deletion src/Locale/en/Common.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"contact_person_number": "Contact person number",
"referral_letter": "Referral Letter",
"close": "Close",
"print": "Print",
"print_referral_letter": "Print Referral Letter",
"date_of_positive_covid_19_swab": "Date of Positive Covid 19 Swab",
"patient_no": "OP/IP No",
Expand Down Expand Up @@ -201,4 +202,4 @@
"oxygen_information": "Oxygen Information",
"deleted_successfully": "{{name}} deleted successfully",
"delete_item": "Delete {{name}}"
}
}

0 comments on commit d7335b3

Please sign in to comment.