Adding Card inside Image Gallery.
This commit is contained in:
parent
eaccf0fca2
commit
32bcaf2602
@ -22,14 +22,12 @@ const ImageGalleryPage = () => {
|
||||
const { openModal } = useModal();
|
||||
const { setOffcanvasContent, setShowTrigger } = useFab();
|
||||
|
||||
// Auto-select first project if none selected
|
||||
useEffect(() => {
|
||||
if (!selectedProjectId && projectNames?.length) {
|
||||
dispatch(setProjectId(projectNames[0].id));
|
||||
}
|
||||
}, [selectedProjectId, projectNames, dispatch]);
|
||||
|
||||
// --- Filters state ---
|
||||
const [appliedFilters, setAppliedFilters] = useState({
|
||||
buildingIds: [],
|
||||
floorIds: [],
|
||||
@ -41,18 +39,11 @@ const ImageGalleryPage = () => {
|
||||
endDate: null,
|
||||
});
|
||||
|
||||
const {
|
||||
data,
|
||||
fetchNextPage,
|
||||
hasNextPage,
|
||||
isLoading,
|
||||
isFetchingNextPage,
|
||||
refetch,
|
||||
} = useImageGallery(selectedProjectId, appliedFilters);
|
||||
const { data, fetchNextPage, hasNextPage, isLoading, isFetchingNextPage, refetch } =
|
||||
useImageGallery(selectedProjectId, appliedFilters);
|
||||
|
||||
const images = data?.pages.flatMap((page) => page.data) || [];
|
||||
|
||||
// --- Utility: store mappings independent of images ---
|
||||
const [labelMaps, setLabelMaps] = useState({
|
||||
buildings: new Map(),
|
||||
floors: new Map(),
|
||||
@ -92,31 +83,21 @@ const ImageGalleryPage = () => {
|
||||
});
|
||||
}, [images]);
|
||||
|
||||
// --- Apply filters ---
|
||||
const handleApplyFilters = useCallback((values) => setAppliedFilters(values), []);
|
||||
|
||||
// --- Remove single filter ---
|
||||
const handleRemoveFilter = (filterKey, valueId) => {
|
||||
setAppliedFilters((prev) => {
|
||||
const updated = { ...prev };
|
||||
|
||||
if (Array.isArray(updated[filterKey])) {
|
||||
updated[filterKey] = updated[filterKey].filter((id) => id !== valueId);
|
||||
}
|
||||
else if (filterKey === "startDate" || filterKey === "endDate") {
|
||||
updated[filterKey] = null;
|
||||
}
|
||||
else if (filterKey === "dateRange") {
|
||||
} else if (filterKey === "startDate" || filterKey === "endDate" || filterKey === "dateRange") {
|
||||
updated.startDate = null;
|
||||
updated.endDate = null;
|
||||
}
|
||||
|
||||
return updated;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// --- Chips ---
|
||||
const appliedFiltersChips = useMemo(() => {
|
||||
const chips = [];
|
||||
const { buildings, floors, activities, workAreas, workCategories, uploadedByUsers } = labelMaps;
|
||||
@ -139,6 +120,7 @@ const ImageGalleryPage = () => {
|
||||
appliedFilters.workCategoryIds?.forEach((id) =>
|
||||
chips.push({ label: "Work Category", value: workCategories.get(id) || id, key: "workCategoryIds", id })
|
||||
);
|
||||
|
||||
if (appliedFilters.startDate || appliedFilters.endDate) {
|
||||
const start = appliedFilters.startDate ? moment(appliedFilters.startDate).format("DD MMM, YYYY") : "";
|
||||
const end = appliedFilters.endDate ? moment(appliedFilters.endDate).format("DD MMM, YYYY") : "";
|
||||
@ -147,10 +129,8 @@ const ImageGalleryPage = () => {
|
||||
return chips;
|
||||
}, [appliedFilters, labelMaps]);
|
||||
|
||||
// --- Refetch on filter change ---
|
||||
useEffect(() => { refetch(); }, [appliedFilters, refetch]);
|
||||
|
||||
// --- Filter Panel ---
|
||||
const filterPanelElement = useMemo(
|
||||
() => (
|
||||
<ImageGalleryFilters
|
||||
@ -168,7 +148,6 @@ const ImageGalleryPage = () => {
|
||||
[labelMaps, appliedFilters, handleApplyFilters]
|
||||
);
|
||||
|
||||
// --- Fab Offcanvas ---
|
||||
useEffect(() => {
|
||||
setShowTrigger(true);
|
||||
setOffcanvasContent("Gallery Filters", filterPanelElement);
|
||||
@ -178,14 +157,12 @@ const ImageGalleryPage = () => {
|
||||
};
|
||||
}, [filterPanelElement, setOffcanvasContent, setShowTrigger]);
|
||||
|
||||
// --- EventBus ---
|
||||
useEffect(() => {
|
||||
const handler = (data) => { if (data.projectId === selectedProjectId) refetch(); };
|
||||
eventBus.on("image_gallery", handler);
|
||||
return () => eventBus.off("image_gallery", handler);
|
||||
}, [selectedProjectId, refetch]);
|
||||
|
||||
// --- Infinite scroll ---
|
||||
useEffect(() => {
|
||||
if (!loaderRef.current) return;
|
||||
const observer = new IntersectionObserver(
|
||||
@ -199,77 +176,49 @@ const ImageGalleryPage = () => {
|
||||
}, [hasNextPage, isFetchingNextPage, isLoading, fetchNextPage]);
|
||||
|
||||
return (
|
||||
<div className="gallery-container container-fluid">
|
||||
<div className="container my-3">
|
||||
<Breadcrumb data={[{ label: "Home", link: "/" }, { label: "Gallery" }]} />
|
||||
|
||||
{appliedFiltersChips.length > 0 && (
|
||||
<div className="mb-3 text-start d-flex flex-wrap align-items-center gap-2">
|
||||
<strong className="me-2 fs-6 ms-1">Filters:</strong>
|
||||
{/* Card wrapper */}
|
||||
<div className="card shadow-sm">
|
||||
<div className="card-body">
|
||||
|
||||
{/* Group chips by label */}
|
||||
{["Building", "Floor", "Work Area", "Activity", "Uploaded By", "Work Category"].map((label) => {
|
||||
const chipsForLabel = appliedFiltersChips.filter((chip) => chip.label === label);
|
||||
if (chipsForLabel.length === 0) return null;
|
||||
|
||||
return (
|
||||
<span key={label} className="d-flex align-items-center px-2 py-1 rounded" style={{ background: "transparent" }}>
|
||||
<strong className="me-1">{label} :</strong>
|
||||
{chipsForLabel.map((chip, idx) => (
|
||||
<span
|
||||
key={chip.id}
|
||||
className="d-flex align-items-center bg-label-secondary px-2 py-1 rounded me-1"
|
||||
>
|
||||
{chip.value}
|
||||
<button
|
||||
type="button"
|
||||
className="btn-close btn-close-white btn-sm ms-1"
|
||||
aria-label="Remove"
|
||||
onClick={() => handleRemoveFilter(chip.key, chip.id)}
|
||||
/>
|
||||
</span>
|
||||
))}
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
|
||||
{/* Date Range */}
|
||||
{appliedFiltersChips.some((chip) => chip.label === "Date Range") && (
|
||||
<span className="d-flex align-items-center px-2 py-1 rounded bg-label-secondary">
|
||||
<strong className="me-1">Date Range :</strong>
|
||||
{appliedFiltersChips
|
||||
.filter((chip) => chip.label === "Date Range")
|
||||
.map((chip, idx) => (
|
||||
<span key={idx} className="d-flex align-items-center me-1">
|
||||
{chip.value}
|
||||
<button
|
||||
type="button"
|
||||
className="btn-close btn-close-white btn-sm ms-1"
|
||||
aria-label="Remove"
|
||||
onClick={() => handleRemoveFilter(chip.key, chip.id)}
|
||||
/>
|
||||
</span>
|
||||
))}
|
||||
</span>
|
||||
{/* Filter Chips */}
|
||||
{appliedFiltersChips.length > 0 && (
|
||||
<div className="mb-3 d-flex flex-wrap align-items-center gap-2">
|
||||
<strong className="me-2 fs-6">Filters:</strong>
|
||||
{appliedFiltersChips.map((chip, idx) => (
|
||||
<span key={idx} className="d-flex align-items-center bg-label-secondary px-2 py-1 rounded me-1">
|
||||
{chip.label} : {chip.value}
|
||||
<button
|
||||
type="button"
|
||||
className="btn-close btn-close-white btn-sm ms-1"
|
||||
aria-label="Remove"
|
||||
onClick={() => handleRemoveFilter(chip.key, chip.id)}
|
||||
/>
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Gallery */}
|
||||
{isLoading ? (
|
||||
<ImageGallerySkeleton count={4} />
|
||||
) : (
|
||||
<ImageGalleryListView
|
||||
images={images}
|
||||
isLoading={isLoading}
|
||||
isFetchingNextPage={isFetchingNextPage}
|
||||
hasNextPage={hasNextPage}
|
||||
loaderRef={loaderRef}
|
||||
openModal={openModal}
|
||||
formatUTCToLocalTime={formatUTCToLocalTime}
|
||||
moment={moment}
|
||||
/>
|
||||
)}
|
||||
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
{isLoading ? (
|
||||
<ImageGallerySkeleton count={4} />
|
||||
) : (
|
||||
<ImageGalleryListView
|
||||
images={images}
|
||||
isLoading={isLoading}
|
||||
isFetchingNextPage={isFetchingNextPage}
|
||||
hasNextPage={hasNextPage}
|
||||
loaderRef={loaderRef}
|
||||
openModal={openModal}
|
||||
formatUTCToLocalTime={formatUTCToLocalTime}
|
||||
moment={moment}
|
||||
/>
|
||||
)}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user