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