Skip to content

Commit 863ee18

Browse files
authored
Merge pull request #114 from Ansh-2222/anshDev
added image preview + zoom in out + edit architect profile
2 parents 0b5e4fc + 5274017 commit 863ee18

File tree

4 files changed

+299
-35
lines changed

4 files changed

+299
-35
lines changed

package-lock.json

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
"react-i18next": "^15.4.1",
6363
"react-resizable-panels": "^2.1.3",
6464
"react-router-dom": "^6.26.2",
65+
"react-zoom-pan-pinch": "^3.7.0",
6566
"recharts": "^2.12.7",
6667
"sonner": "^2.0.7",
6768
"tailwind-merge": "^2.5.2",

src/components/ImageViewer.tsx

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import { motion } from "framer-motion";
2+
import { useEffect, useState } from "react";
3+
import { X } from "lucide-react";
4+
import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";
5+
6+
interface ImageViewerProps {
7+
photos: string[];
8+
currentIndex: number;
9+
setCurrentIndex: React.Dispatch<React.SetStateAction<number>>;
10+
onClose: () => void;
11+
canDelete: boolean; // still kept for future use
12+
onDelete: (index: number) => void; // still kept for future use
13+
}
14+
15+
export default function ImageViewer({
16+
photos,
17+
currentIndex,
18+
setCurrentIndex,
19+
onClose,
20+
}: ImageViewerProps) {
21+
22+
const [scale, setScale] = useState(1);
23+
24+
useEffect(() => {
25+
document.body.style.overflow = "hidden";
26+
return () => {
27+
document.body.style.overflow = "auto";
28+
};
29+
}, []);
30+
31+
useEffect(() => {
32+
const keyHandler = (e: KeyboardEvent) => {
33+
if (e.key === "Escape") onClose();
34+
35+
if (scale === 1 && e.key === "ArrowRight" && currentIndex < photos.length - 1) {
36+
setCurrentIndex(currentIndex + 1);
37+
}
38+
39+
if (scale === 1 && e.key === "ArrowLeft" && currentIndex > 0) {
40+
setCurrentIndex(currentIndex - 1);
41+
}
42+
};
43+
44+
window.addEventListener("keydown", keyHandler);
45+
return () => window.removeEventListener("keydown", keyHandler);
46+
}, [scale, currentIndex, photos.length, setCurrentIndex, onClose]);
47+
48+
49+
return (
50+
<motion.div
51+
className="fixed inset-0 bg-black/85 flex items-center justify-center z-[999]"
52+
initial={{ opacity: 0 }}
53+
animate={{ opacity: 1 }}
54+
exit={{ opacity: 0 }}
55+
onClick={(e) => {
56+
if (e.target === e.currentTarget) onClose();
57+
}}
58+
>
59+
60+
{/* Close Button Only */}
61+
<button
62+
className="absolute top-5 right-6 text-white hover:text-gray-300 transition cursor-pointer"
63+
onClick={(e) => {
64+
e.stopPropagation();
65+
onClose();
66+
}}
67+
>
68+
<X size={26} />
69+
</button>
70+
71+
72+
{/* Left Arrow */}
73+
{currentIndex > 0 && scale === 1 && (
74+
<button
75+
className="absolute left-6 text-white text-3xl cursor-pointer"
76+
onClick={(e) => {
77+
e.stopPropagation();
78+
setCurrentIndex(currentIndex - 1);
79+
}}
80+
>
81+
82+
</button>
83+
)}
84+
85+
{/* Zoom Wrapper */}
86+
<TransformWrapper
87+
doubleClick={{ mode: "toggle" }}
88+
maxScale={4}
89+
minScale={1}
90+
wheel={{ disabled: false, step: 0.25, smoothStep: 0.05 }}
91+
pinch={{ disabled: false }}
92+
panning={{ disabled: true }}
93+
onTransformed={(instance) => setScale(instance.state.scale)}
94+
>
95+
<TransformComponent>
96+
97+
<motion.img
98+
src={photos[currentIndex]}
99+
className="max-w-[90vw] max-h-[80vh] rounded-xl select-none"
100+
draggable={false}
101+
onClick={(e) => e.stopPropagation()}
102+
onWheel={(e) => e.stopPropagation()}
103+
onMouseDown={(e) => e.preventDefault()}
104+
onContextMenu={(e) => e.preventDefault()}
105+
initial={{ scale: 0.9 }}
106+
animate={{ scale: 1 }}
107+
/>
108+
109+
</TransformComponent>
110+
</TransformWrapper>
111+
112+
113+
{/* Right Arrow */}
114+
{currentIndex < photos.length - 1 && scale === 1 && (
115+
<button
116+
className="absolute right-6 text-white text-3xl cursor-pointer"
117+
onClick={(e) => {
118+
e.stopPropagation();
119+
setCurrentIndex(currentIndex + 1);
120+
}}
121+
>
122+
123+
</button>
124+
)}
125+
126+
</motion.div>
127+
);
128+
}

0 commit comments

Comments
 (0)