Integrating api for imageGallery.
This commit is contained in:
parent
1e25e2d1ad
commit
c2bac4e640
@ -9,7 +9,6 @@ const ImageGalleryListView = ({
|
||||
hasNextPage,
|
||||
loaderRef,
|
||||
openModal,
|
||||
SCROLL_THRESHOLD,
|
||||
formatUTCToLocalTime,
|
||||
moment,
|
||||
}) => {
|
||||
@ -19,18 +18,16 @@ const ImageGalleryListView = ({
|
||||
|
||||
useEffect(() => {
|
||||
const updateThreshold = () => {
|
||||
if (window.innerWidth >= 1400) setScrollThreshold(6); // xl screens
|
||||
else if (window.innerWidth >= 992) setScrollThreshold(5); // lg
|
||||
else if (window.innerWidth >= 768) setScrollThreshold(4); // md
|
||||
else setScrollThreshold(3); // sm & xs
|
||||
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" }),
|
||||
@ -42,132 +39,104 @@ const ImageGalleryListView = ({
|
||||
[]
|
||||
);
|
||||
|
||||
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">
|
||||
{isLoading ? (
|
||||
<div className="text-center">
|
||||
<p>Loading...</p>
|
||||
</div>
|
||||
) : images.length ? (
|
||||
images.map((batch) => {
|
||||
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;
|
||||
{images.map((batch) => {
|
||||
if (!batch.documents?.length) return null; // skip empty batches
|
||||
|
||||
return (
|
||||
<div key={batch.batchId} className="grouped-section">
|
||||
<div className="group-heading">
|
||||
{/* Uploader Info */}
|
||||
<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>
|
||||
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;
|
||||
|
||||
{/* Location Info */}
|
||||
<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>
|
||||
)}
|
||||
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>
|
||||
|
||||
{/* Images */}
|
||||
<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 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>
|
||||
{hasArrows && (
|
||||
<button
|
||||
className="scroll-arrow right-arrow"
|
||||
onClick={() => scrollRight(batch.batchId)}
|
||||
>
|
||||
<i className="bx bx-chevron-right"></i>
|
||||
</button>
|
||||
{batch.workCategoryName && (
|
||||
<span className="badge bg-label-primary ms-2">{batch.workCategoryName}</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<p className="text-center text-muted mt-5">
|
||||
No images match the selected filters.
|
||||
</p>
|
||||
)}
|
||||
|
||||
<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>}
|
||||
|
@ -89,16 +89,19 @@ import { useInfiniteQuery } from "@tanstack/react-query";
|
||||
const PAGE_SIZE = 10;
|
||||
|
||||
const useImageGallery = (selectedProjectId, filters) => {
|
||||
const hasFilters = filters && Object.values(filters).some(
|
||||
value => Array.isArray(value) ? value.length > 0 : value !== null && value !== ""
|
||||
);
|
||||
const hasFilters =
|
||||
filters &&
|
||||
Object.values(filters).some((value) =>
|
||||
Array.isArray(value) ? value.length > 0 : value !== null && value !== ""
|
||||
);
|
||||
|
||||
return useInfiniteQuery({
|
||||
queryKey: ["imageGallery", selectedProjectId, hasFilters ? filters : null],
|
||||
enabled: !!selectedProjectId,
|
||||
getNextPageParam: (lastPage, allPages) => {
|
||||
if (!lastPage?.data?.length) return undefined;
|
||||
return allPages.length + 1;
|
||||
getNextPageParam: (lastPage) => {
|
||||
const currentPage = lastPage?.data?.currentPage || 1;
|
||||
const totalPages = lastPage?.data?.totalPages || 1;
|
||||
return currentPage < totalPages ? currentPage + 1 : undefined;
|
||||
},
|
||||
queryFn: async ({ pageParam = 1 }) => {
|
||||
const res = await ImageGalleryAPI.ImagesGet(
|
||||
@ -107,7 +110,7 @@ const useImageGallery = (selectedProjectId, filters) => {
|
||||
pageParam,
|
||||
PAGE_SIZE
|
||||
);
|
||||
return res;
|
||||
return res.data; // Important: use res.data to match API response
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@ -185,7 +185,8 @@ const ImageGalleryPage = () => {
|
||||
}, [hasNextPage, isFetchingNextPage, isLoading, fetchNextPage]);
|
||||
|
||||
return (
|
||||
<div className="container my-3">
|
||||
|
||||
<div className="container-fluid">
|
||||
<Breadcrumb data={[{ label: "Home", link: "/" }, { label: "Gallery" }]} />
|
||||
|
||||
{/* Card wrapper */}
|
||||
|
Loading…
x
Reference in New Issue
Block a user