marco.pms.web/src/components/ImageGallery/ImageGalleryListView.jsx

153 lines
5.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useRef, useState, useCallback, useEffect } from "react";
import Avatar from "../../components/common/Avatar";
import ImagePopup from "./ImagePopup";
const ImageGalleryListView = ({
images,
isLoading,
isFetchingNextPage,
hasNextPage,
loaderRef,
openModal,
formatUTCToLocalTime,
moment,
}) => {
const [hoveredImage, setHoveredImage] = useState(null);
const [scrollThreshold, setScrollThreshold] = useState(5);
const imageGroupRefs = useRef({});
useEffect(() => {
const updateThreshold = () => {
if (window.innerWidth >= 1400) setScrollThreshold(6);
else if (window.innerWidth >= 992) setScrollThreshold(5);
else if (window.innerWidth >= 768) setScrollThreshold(4);
else setScrollThreshold(3);
};
updateThreshold();
window.addEventListener("resize", updateThreshold);
return () => window.removeEventListener("resize", updateThreshold);
}, []);
const scrollLeft = useCallback(
(key) =>
imageGroupRefs.current[key]?.scrollBy({ left: -200, behavior: "smooth" }),
[]
);
const scrollRight = useCallback(
(key) =>
imageGroupRefs.current[key]?.scrollBy({ left: 200, behavior: "smooth" }),
[]
);
if (!images.length && !isLoading) {
return <p className="text-center text-muted mt-5">No images match the selected filters.</p>;
}
return (
<div className="main-content">
<div className="activity-section">
{images.map((batch) => {
if (!batch.documents?.length) return null; // skip empty batches
const doc = batch.documents[0];
const userName = `${doc.uploadedBy?.firstName || ""} ${doc.uploadedBy?.lastName || ""}`.trim();
const date = formatUTCToLocalTime(doc.uploadedAt);
const hasArrows = batch.documents.length > scrollThreshold;
return (
<div key={batch.batchId} className="grouped-section">
<div className="group-heading">
<div className="d-flex align-items-center mb-1">
<Avatar
size="xs"
firstName={doc.uploadedBy?.firstName}
lastName={doc.uploadedBy?.lastName}
className="me-2"
/>
<div className="d-flex flex-column align-items-start">
<strong className="user-name-text">{userName}</strong>
<span className="text-muted small">{date}</span>
</div>
</div>
<div className="location-line text-secondary">
<div className="d-flex align-items-center flex-wrap gap-1 text-secondary">
<span className="d-flex align-items-center">
<span>{batch.buildingName}</span>
<i className="bx bx-chevron-right " />
</span>
<span className="d-flex align-items-center">
<span>{batch.floorName}</span>
<i className="bx bx-chevron-right m" />
</span>
<span className="d-flex align-items-center ">
<span>{batch.workAreaName || "Unknown"}</span>
<i className="bx bx-chevron-right " />
<span>{batch.activityName}</span>
</span>
</div>
{batch.workCategoryName && (
<span className="badge bg-label-primary ms-2">{batch.workCategoryName}</span>
)}
</div>
</div>
<div className="image-group-wrapper">
{hasArrows && (
<button className="scroll-arrow left-arrow" onClick={() => scrollLeft(batch.batchId)}>
</button>
)}
<div
className="image-group-horizontal"
ref={(el) => (imageGroupRefs.current[batch.batchId] = el)}
>
{batch.documents.map((d, i) => {
const hoverDate = moment(d.uploadedAt).format("DD MMMM, YYYY");
const hoverTime = moment(d.uploadedAt).format("hh:mm A");
return (
<div
key={d.id}
className="image-card"
onClick={() => openModal(<ImagePopup batch={batch} initialIndex={i} />)}
onMouseEnter={() => setHoveredImage(d)}
onMouseLeave={() => setHoveredImage(null)}
>
<div className="image-wrapper">
<img src={d.url} alt={`Image ${i + 1}`} />
</div>
{hoveredImage === d && (
<div className="image-hover-description">
<p><strong>Date:</strong> {hoverDate}</p>
<p><strong>Time:</strong> {hoverTime}</p>
<p><strong>Activity:</strong> {batch.activityName}</p>
</div>
)}
</div>
);
})}
</div>
{hasArrows && (
<button className="scroll-arrow right-arrow" onClick={() => scrollRight(batch.batchId)}>
</button>
)}
</div>
</div>
);
})}
<div ref={loaderRef}>
{isFetchingNextPage && hasNextPage && <p>Loading...</p>}
{!hasNextPage && !isLoading && images.length > 0 && (
<p className="text-muted">You've reached the end of the images.</p>
)}
</div>
</div>
</div>
);
};
export default ImageGalleryListView;