Integrating api for imageGallery.
This commit is contained in:
parent
1e25e2d1ad
commit
c2bac4e640
@ -9,7 +9,6 @@ const ImageGalleryListView = ({
|
|||||||
hasNextPage,
|
hasNextPage,
|
||||||
loaderRef,
|
loaderRef,
|
||||||
openModal,
|
openModal,
|
||||||
SCROLL_THRESHOLD,
|
|
||||||
formatUTCToLocalTime,
|
formatUTCToLocalTime,
|
||||||
moment,
|
moment,
|
||||||
}) => {
|
}) => {
|
||||||
@ -19,18 +18,16 @@ const ImageGalleryListView = ({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const updateThreshold = () => {
|
const updateThreshold = () => {
|
||||||
if (window.innerWidth >= 1400) setScrollThreshold(6); // xl screens
|
if (window.innerWidth >= 1400) setScrollThreshold(6);
|
||||||
else if (window.innerWidth >= 992) setScrollThreshold(5); // lg
|
else if (window.innerWidth >= 992) setScrollThreshold(5);
|
||||||
else if (window.innerWidth >= 768) setScrollThreshold(4); // md
|
else if (window.innerWidth >= 768) setScrollThreshold(4);
|
||||||
else setScrollThreshold(3); // sm & xs
|
else setScrollThreshold(3);
|
||||||
};
|
};
|
||||||
updateThreshold();
|
updateThreshold();
|
||||||
window.addEventListener("resize", updateThreshold);
|
window.addEventListener("resize", updateThreshold);
|
||||||
return () => window.removeEventListener("resize", updateThreshold);
|
return () => window.removeEventListener("resize", updateThreshold);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const scrollLeft = useCallback(
|
const scrollLeft = useCallback(
|
||||||
(key) =>
|
(key) =>
|
||||||
imageGroupRefs.current[key]?.scrollBy({ left: -200, behavior: "smooth" }),
|
imageGroupRefs.current[key]?.scrollBy({ left: -200, behavior: "smooth" }),
|
||||||
@ -42,25 +39,24 @@ const ImageGalleryListView = ({
|
|||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!images.length && !isLoading) {
|
||||||
|
return <p className="text-center text-muted mt-5">No images match the selected filters.</p>;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="main-content">
|
<div className="main-content">
|
||||||
<div className="activity-section">
|
<div className="activity-section">
|
||||||
{isLoading ? (
|
{images.map((batch) => {
|
||||||
<div className="text-center">
|
if (!batch.documents?.length) return null; // skip empty batches
|
||||||
<p>Loading...</p>
|
|
||||||
</div>
|
|
||||||
) : images.length ? (
|
|
||||||
images.map((batch) => {
|
|
||||||
const doc = batch.documents[0];
|
const doc = batch.documents[0];
|
||||||
const userName = `${doc.uploadedBy?.firstName || ""} ${doc.uploadedBy?.lastName || ""
|
const userName = `${doc.uploadedBy?.firstName || ""} ${doc.uploadedBy?.lastName || ""}`.trim();
|
||||||
}`.trim();
|
|
||||||
const date = formatUTCToLocalTime(doc.uploadedAt);
|
const date = formatUTCToLocalTime(doc.uploadedAt);
|
||||||
const hasArrows = batch.documents.length > scrollThreshold;
|
const hasArrows = batch.documents.length > scrollThreshold;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={batch.batchId} className="grouped-section">
|
<div key={batch.batchId} className="grouped-section">
|
||||||
<div className="group-heading">
|
<div className="group-heading">
|
||||||
{/* Uploader Info */}
|
|
||||||
<div className="d-flex align-items-center mb-1">
|
<div className="d-flex align-items-center mb-1">
|
||||||
<Avatar
|
<Avatar
|
||||||
size="xs"
|
size="xs"
|
||||||
@ -74,7 +70,6 @@ const ImageGalleryListView = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Location Info */}
|
|
||||||
<div className="location-line text-secondary">
|
<div className="location-line text-secondary">
|
||||||
<div className="d-flex align-items-center flex-wrap gap-1 text-secondary">
|
<div className="d-flex align-items-center flex-wrap gap-1 text-secondary">
|
||||||
<span className="d-flex align-items-center">
|
<span className="d-flex align-items-center">
|
||||||
@ -92,42 +87,30 @@ const ImageGalleryListView = ({
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{batch.workCategoryName && (
|
{batch.workCategoryName && (
|
||||||
<span className="badge bg-label-primary ms-2">
|
<span className="badge bg-label-primary ms-2">{batch.workCategoryName}</span>
|
||||||
{batch.workCategoryName}
|
|
||||||
</span>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Images */}
|
|
||||||
<div className="image-group-wrapper">
|
<div className="image-group-wrapper">
|
||||||
{hasArrows && (
|
{hasArrows && (
|
||||||
<button
|
<button className="scroll-arrow left-arrow" onClick={() => scrollLeft(batch.batchId)}>
|
||||||
className="scroll-arrow left-arrow"
|
|
||||||
onClick={() => scrollLeft(batch.batchId)}
|
|
||||||
>
|
|
||||||
‹
|
‹
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
className="image-group-horizontal"
|
className="image-group-horizontal"
|
||||||
ref={(el) =>
|
ref={(el) => (imageGroupRefs.current[batch.batchId] = el)}
|
||||||
(imageGroupRefs.current[batch.batchId] = el)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{batch.documents.map((d, i) => {
|
{batch.documents.map((d, i) => {
|
||||||
const hoverDate = moment(d.uploadedAt).format(
|
const hoverDate = moment(d.uploadedAt).format("DD MMMM, YYYY");
|
||||||
"DD MMMM, YYYY"
|
|
||||||
);
|
|
||||||
const hoverTime = moment(d.uploadedAt).format("hh:mm A");
|
const hoverTime = moment(d.uploadedAt).format("hh:mm A");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={d.id}
|
key={d.id}
|
||||||
className="image-card"
|
className="image-card"
|
||||||
onClick={() =>
|
onClick={() => openModal(<ImagePopup batch={batch} initialIndex={i} />)}
|
||||||
openModal(<ImagePopup batch={batch} initialIndex={i} />)
|
|
||||||
}
|
|
||||||
onMouseEnter={() => setHoveredImage(d)}
|
onMouseEnter={() => setHoveredImage(d)}
|
||||||
onMouseLeave={() => setHoveredImage(null)}
|
onMouseLeave={() => setHoveredImage(null)}
|
||||||
>
|
>
|
||||||
@ -136,15 +119,9 @@ const ImageGalleryListView = ({
|
|||||||
</div>
|
</div>
|
||||||
{hoveredImage === d && (
|
{hoveredImage === d && (
|
||||||
<div className="image-hover-description">
|
<div className="image-hover-description">
|
||||||
<p>
|
<p><strong>Date:</strong> {hoverDate}</p>
|
||||||
<strong>Date:</strong> {hoverDate}
|
<p><strong>Time:</strong> {hoverTime}</p>
|
||||||
</p>
|
<p><strong>Activity:</strong> {batch.activityName}</p>
|
||||||
<p>
|
|
||||||
<strong>Time:</strong> {hoverTime}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<strong>Activity:</strong> {batch.activityName}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -152,22 +129,14 @@ const ImageGalleryListView = ({
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
{hasArrows && (
|
{hasArrows && (
|
||||||
<button
|
<button className="scroll-arrow right-arrow" onClick={() => scrollRight(batch.batchId)}>
|
||||||
className="scroll-arrow right-arrow"
|
‹
|
||||||
onClick={() => scrollRight(batch.batchId)}
|
|
||||||
>
|
|
||||||
<i className="bx bx-chevron-right"></i>
|
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})
|
})}
|
||||||
) : (
|
|
||||||
<p className="text-center text-muted mt-5">
|
|
||||||
No images match the selected filters.
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div ref={loaderRef}>
|
<div ref={loaderRef}>
|
||||||
{isFetchingNextPage && hasNextPage && <p>Loading...</p>}
|
{isFetchingNextPage && hasNextPage && <p>Loading...</p>}
|
||||||
|
|||||||
@ -89,16 +89,19 @@ import { useInfiniteQuery } from "@tanstack/react-query";
|
|||||||
const PAGE_SIZE = 10;
|
const PAGE_SIZE = 10;
|
||||||
|
|
||||||
const useImageGallery = (selectedProjectId, filters) => {
|
const useImageGallery = (selectedProjectId, filters) => {
|
||||||
const hasFilters = filters && Object.values(filters).some(
|
const hasFilters =
|
||||||
value => Array.isArray(value) ? value.length > 0 : value !== null && value !== ""
|
filters &&
|
||||||
|
Object.values(filters).some((value) =>
|
||||||
|
Array.isArray(value) ? value.length > 0 : value !== null && value !== ""
|
||||||
);
|
);
|
||||||
|
|
||||||
return useInfiniteQuery({
|
return useInfiniteQuery({
|
||||||
queryKey: ["imageGallery", selectedProjectId, hasFilters ? filters : null],
|
queryKey: ["imageGallery", selectedProjectId, hasFilters ? filters : null],
|
||||||
enabled: !!selectedProjectId,
|
enabled: !!selectedProjectId,
|
||||||
getNextPageParam: (lastPage, allPages) => {
|
getNextPageParam: (lastPage) => {
|
||||||
if (!lastPage?.data?.length) return undefined;
|
const currentPage = lastPage?.data?.currentPage || 1;
|
||||||
return allPages.length + 1;
|
const totalPages = lastPage?.data?.totalPages || 1;
|
||||||
|
return currentPage < totalPages ? currentPage + 1 : undefined;
|
||||||
},
|
},
|
||||||
queryFn: async ({ pageParam = 1 }) => {
|
queryFn: async ({ pageParam = 1 }) => {
|
||||||
const res = await ImageGalleryAPI.ImagesGet(
|
const res = await ImageGalleryAPI.ImagesGet(
|
||||||
@ -107,7 +110,7 @@ const useImageGallery = (selectedProjectId, filters) => {
|
|||||||
pageParam,
|
pageParam,
|
||||||
PAGE_SIZE
|
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]);
|
}, [hasNextPage, isFetchingNextPage, isLoading, fetchNextPage]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container my-3">
|
|
||||||
|
<div className="container-fluid">
|
||||||
<Breadcrumb data={[{ label: "Home", link: "/" }, { label: "Gallery" }]} />
|
<Breadcrumb data={[{ label: "Home", link: "/" }, { label: "Gallery" }]} />
|
||||||
|
|
||||||
{/* Card wrapper */}
|
{/* Card wrapper */}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user