Compare commits

..

No commits in common. "d27546073fa6cac69f2be07c5fc1216fbc9af1e0" and "80717f0458a3774f92a1379d7126bb65c085fd89" have entirely different histories.

6 changed files with 61 additions and 160 deletions

View File

@ -72,7 +72,7 @@ export const FilelistView = ({ files, viewFile }) => {
e.preventDefault(); e.preventDefault();
viewFile({ viewFile({
IsOpen: true, IsOpen: true,
Image: files, Image: file.preSignedUrl,
}); });
}} }}
> >

View File

@ -1,169 +1,80 @@
import { useState, useRef, useEffect } from "react"; import { useState } from "react";
const PreviewDocument = ({ files = [] }) => {
const images = Array.isArray(files) ? files : [files];
const [index, setIndex] = useState(0); const PreviewDocument = ({ imageUrl }) => {
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [rotation, setRotation] = useState(0); const [rotation, setRotation] = useState(0);
const [scale, setScale] = useState(1); const [scale, setScale] = useState(1);
const [position, setPosition] = useState({ x: 0, y: 0 });
const [dragging, setDragging] = useState(false);
const startPos = useRef({ x: 0, y: 0 });
const MIN_ZOOM = 0.4;
const MAX_ZOOM = 3;
const currentImage = images[index];
// Reset on image change
useEffect(() => {
setRotation(0);
setScale(1);
setPosition({ x: 0, y: 0 });
setLoading(true);
}, [index]);
const zoomIn = () => setScale((prev) => Math.min(prev + 0.2, MAX_ZOOM));
const zoomOut = () => setScale((prev) => Math.max(prev - 0.2, MIN_ZOOM));
const zoomIn = () => setScale((prev) => Math.min(prev + 0.2, 3));
const zoomOut = () => setScale((prev) => Math.max(prev - 0.2, 0.4));
const resetAll = () => { const resetAll = () => {
setRotation(0); setRotation(0);
setScale(1); setScale(1);
setPosition({ x: 0, y: 0 });
}; };
const nextImage = () => {
if (index < images.length - 1) setIndex((i) => i + 1);
};
const prevImage = () => {
if (index > 0) setIndex((i) => i - 1);
};
const handleWheel = (e) => {
e.preventDefault();
if (e.ctrlKey) {
const delta = e.deltaY > 0 ? -0.1 : 0.1;
setScale((prev) => {
let next = prev + delta;
if (next < MIN_ZOOM) next = MIN_ZOOM;
if (next > MAX_ZOOM) next = MAX_ZOOM;
return next;
});
} else {
if (e.deltaY > 0) nextImage();
else prevImage();
}
};
const handleMouseDown = (e) => {
setDragging(true);
startPos.current = {
x: e.clientX - position.x,
y: e.clientY - position.y,
};
};
const handleMouseMove = (e) => {
if (!dragging) return;
setPosition({
x: e.clientX - startPos.current.x,
y: e.clientY - startPos.current.y,
});
};
const handleMouseUp = () => setDragging(false);
const handleDoubleClick = () => resetAll();
return ( return (
<> <>
{/* Top Controls */} <div className="d-flex justify-content-start gap-3 mb-2">
<div className="d-flex justify-content-start align-items-center mb-2"> <i
{/* Left */} className="bx bx-rotate-right cursor-pointer fs-4"
<div className="d-flex gap-3"> title="Rotate"
<i onClick={() => setRotation((prev) => prev + 90)}
className="bx bx-rotate-right cursor-pointer fs-4" ></i>
onClick={() => setRotation((prev) => prev + 90)}
title="Rotate" <i
/> className="bx bx-zoom-in cursor-pointer fs-4"
<i title="Zoom In"
className="bx bx-zoom-in cursor-pointer fs-4" onClick={zoomIn}
onClick={zoomIn} ></i>
title="Zoom In"
/> <i
<i className="bx bx-zoom-out cursor-pointer fs-4"
className="bx bx-zoom-out cursor-pointer fs-4" title="Zoom Out"
onClick={zoomOut} onClick={zoomOut}
title="Zoom Out" ></i>
/>
<i
className="bx bx-reset cursor-pointer fs-4"
onClick={resetAll}
title="Reset"
/>
</div>
</div> </div>
<div <div
onWheel={handleWheel} className="position-relative d-flex flex-column justify-content-center align-items-center overflow-hidden"
onMouseDown={handleMouseDown} style={{ minHeight: "80vh" }}
onMouseMove={handleMouseMove}
onMouseUp={handleMouseUp}
onMouseLeave={handleMouseUp}
onDoubleClick={handleDoubleClick}
className="position-relative d-flex justify-content-center align-items-center bg-light-secondary overflow-hidden"
style={{
minHeight: "70vh",
userSelect: "none",
borderRadius: "10px",
}}
> >
{loading && <div className="text-secondary">Loading...</div>} {loading && (
<div className="text-secondary text-center mb-2">
Loading...
</div>
)}
<img <div className="mb-3 d-flex justify-content-center align-items-center">
src={currentImage?.preSignedUrl} <img
alt="Preview" src={imageUrl}
draggable="false" alt="Full View"
style={{ className="img-fluid"
maxHeight: "60vh", style={{
display: loading ? "none" : "block", maxHeight: "80vh",
transform: ` objectFit: "contain",
translate(${position.x}px, ${position.y}px) display: loading ? "none" : "block",
scale(${scale}) transform: `rotate(${rotation}deg) scale(${scale})`,
rotate(${rotation}deg) transition: "transform 0.3s ease",
`, cursor: "grab",
transition: dragging ? "none" : "transform 0.2s ease", }}
cursor: dragging ? "grabbing" : "grab", onLoad={() => setLoading(false)}
}} />
onLoad={() => setLoading(false)}
/>
</div>
<div className="d-flex justify-content-between">
<div className="text-center text-muted mt-2 small">
Scroll = change image | Double click = reset
</div> </div>
<div className="d-flex align-items-center gap-2">
<i <div className="position-absolute bottom-0 start-0 m-2">
className="bx bx-chevron-left cursor-pointer fs-4" <button
onClick={prevImage} className="btn btn-outline-secondary"
/> onClick={resetAll}
<span> >
{index + 1} / {images.length} <i className="bx bx-reset"></i> Reset
</span> </button>
<i
className="bx bx-chevron-right cursor-pointer fs-4"
onClick={nextImage}
/>
</div> </div>
</div> </div>
</> </>
); );
}; };
export default PreviewDocument; export default PreviewDocument;

View File

@ -393,7 +393,7 @@ const tdsPercentage = Number(watch("tdsPercentage")) || 0;
if (isImage) { if (isImage) {
setDocumentView({ setDocumentView({
IsOpen: true, IsOpen: true,
Images: data?.documents, Image: doc.preSignedUrl,
}); });
} }
}} }}

View File

@ -51,6 +51,7 @@ const InputSuggestions = ({
{filteredList.map((org) => ( {filteredList.map((org) => (
<li <li
key={org} key={org}
className="ropdown-item"
style={{ style={{
cursor: "pointer", cursor: "pointer",
padding: "5px 12px", padding: "5px 12px",

View File

@ -1,11 +0,0 @@
import React from 'react'
const PurchaseList = () => {
return (
<div>
</div>
)
}
export default PurchaseList

View File

@ -62,7 +62,7 @@ const ExpensePage = () => {
const [ViewDocument, setDocumentView] = useState({ const [ViewDocument, setDocumentView] = useState({
IsOpen: false, IsOpen: false,
Images: null, Image: null,
}); });
const IsCreatedAble = useHasUserPermission(CREATE_EXEPENSE); const IsCreatedAble = useHasUserPermission(CREATE_EXEPENSE);
@ -208,10 +208,10 @@ const ExpensePage = () => {
<GlobalModel <GlobalModel
isOpen isOpen
size="md" size="md"
key={ViewDocument.Images ?? "doc"} key={ViewDocument.Image ?? "doc"}
closeModal={() => setDocumentView({ IsOpen: false, Images: null })} closeModal={() => setDocumentView({ IsOpen: false, Image: null })}
> >
<PreviewDocument files={ViewDocument.Images} /> <PreviewDocument imageUrl={ViewDocument.Image} />
</GlobalModel> </GlobalModel>
)} )}
</div> </div>