Adding ImageGallery Chips.
This commit is contained in:
parent
18e739f3ab
commit
7c4932b019
59
src/components/gallary/GalleryFilterChips.jsx
Normal file
59
src/components/gallary/GalleryFilterChips.jsx
Normal file
@ -0,0 +1,59 @@
|
||||
import React, { useMemo } from "react";
|
||||
|
||||
const GalleryFilterChips = ({ filter, filterData, removeFilterChip, clearFilter }) => {
|
||||
const data = filterData?.data || filterData || {};
|
||||
|
||||
const filterChips = useMemo(() => {
|
||||
const chips = [];
|
||||
|
||||
const addGroup = (ids, list, label, key) => {
|
||||
if (!ids?.length) return;
|
||||
const items = ids.map((id) => ({
|
||||
id,
|
||||
name: list?.find((i) => i.id === id)?.name || id,
|
||||
}));
|
||||
chips.push({ key, label, items });
|
||||
};
|
||||
|
||||
addGroup(filter.buildingIds, data.buildings, "Building", "buildingIds");
|
||||
addGroup(filter.floorIds, data.floors, "Floor", "floorIds");
|
||||
addGroup(filter.workAreaIds, data.workAreas, "Work Area", "workAreaIds");
|
||||
addGroup(filter.activityIds, data.activities, "Activity", "activityIds");
|
||||
addGroup(filter.workCategoryIds, data.workCategories, "Work Category", "workCategoryIds");
|
||||
addGroup(filter.uploadedByIds, data.uploadedBy, "Uploaded By", "uploadedByIds");
|
||||
addGroup(filter.serviceIds, data.services, "Service", "serviceIds");
|
||||
|
||||
return chips;
|
||||
}, [filter, filterData]);
|
||||
|
||||
if (!filterChips.length) return null;
|
||||
return (
|
||||
<div className="d-flex flex-wrap align-items-center gap-2">
|
||||
{filterChips.map((chipGroup) => (
|
||||
<div key={chipGroup.key} className="d-flex align-items-center flex-wrap">
|
||||
<span className="fw-semibold me-2">{chipGroup.label}:</span>
|
||||
{chipGroup.items.map((item) => (
|
||||
<span
|
||||
key={item.id}
|
||||
className="d-flex align-items-center bg-light rounded px-2 py-1 me-1"
|
||||
>
|
||||
<span>{item.name}</span>
|
||||
<button
|
||||
type="button"
|
||||
className="btn-close btn-close-white btn-sm ms-2"
|
||||
style={{
|
||||
filter: "invert(1) grayscale(1)",
|
||||
opacity: 0.7,
|
||||
fontSize: "0.6rem",
|
||||
}}
|
||||
onClick={() => removeFilterChip(chipGroup.key, item.id)}
|
||||
/>
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default GalleryFilterChips;
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import React, { forwardRef, useEffect, useImperativeHandle, useMemo, useState } from "react";
|
||||
import { useImageGalleryFilter } from "../../hooks/useImageGallery";
|
||||
import { useSelectedProject } from "../../slices/apiDataManager";
|
||||
import { FormProvider, useForm } from "react-hook-form";
|
||||
@ -10,19 +10,52 @@ import SelectMultiple from "../common/SelectMultiple";
|
||||
import { localToUtc } from "../../utils/appUtils";
|
||||
import { useLocation } from "react-router-dom";
|
||||
|
||||
const GalleryFilterPanel = ({ onApply }) => {
|
||||
const GalleryFilterPanel = forwardRef(({ onApply, setFilterdata, clearFilter }, ref) => {
|
||||
const selectedProject = useSelectedProject();
|
||||
const [resetKey, setResetKey] = useState(0);
|
||||
|
||||
const { data, isLoading, isError, error } =
|
||||
useImageGalleryFilter(selectedProject);
|
||||
|
||||
|
||||
const dynamicDefaultFilter = useMemo(() => {
|
||||
return {
|
||||
...defaultGalleryFilterValue,
|
||||
buildingIds: defaultGalleryFilterValue.buildingIds || [],
|
||||
floorIds: defaultGalleryFilterValue.floorIds || [],
|
||||
workAreaIds: defaultGalleryFilterValue.workAreaIds || [],
|
||||
activityIds: defaultGalleryFilterValue.activityIds || [],
|
||||
workCategoryIds: defaultGalleryFilterValue.workCategoryIds || [],
|
||||
startDate: defaultGalleryFilterValue.startDate,
|
||||
endDate: defaultGalleryFilterValue.endDate,
|
||||
uploadedByIds: defaultGalleryFilterValue.uploadedByIds || [],
|
||||
serviceIds: defaultGalleryFilterValue.serviceIds || [],
|
||||
};
|
||||
}, [selectedProject]);
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
resetFieldValue: (name, value) => {
|
||||
// Reset specific field
|
||||
if (value !== undefined) {
|
||||
setValue(name, value);
|
||||
} else {
|
||||
reset({ ...methods.getValues(), [name]: defaultFilter[name] });
|
||||
}
|
||||
},
|
||||
getValues: methods.getValues, // optional, to read current filter state
|
||||
}));
|
||||
|
||||
useEffect(() => {
|
||||
if (data && setFilterdata) {
|
||||
setFilterdata(data);
|
||||
}
|
||||
}, [data, setFilterdata]);
|
||||
const closePanel = () => {
|
||||
document.querySelector(".offcanvas.show .btn-close")?.click();
|
||||
};
|
||||
const methods = useForm({
|
||||
resolver: zodResolver(gallerySchema),
|
||||
defaultValues: defaultGalleryFilterValue,
|
||||
defaultValues: dynamicDefaultFilter,
|
||||
});
|
||||
|
||||
const {
|
||||
@ -144,6 +177,6 @@ const GalleryFilterPanel = ({ onApply }) => {
|
||||
</FormProvider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
export default GalleryFilterPanel;
|
||||
|
||||
@ -8,7 +8,8 @@ import { ITEMS_PER_PAGE } from "../../utils/constants";
|
||||
import Pagination from "../common/Pagination";
|
||||
import { formatUTCToLocalTime } from "../../utils/dateUtils";
|
||||
import { SpinnerLoader } from "../common/Loader";
|
||||
const ImageGalleryListView = ({filter}) => {
|
||||
import GalleryFilterChips from "./GalleryFilterChips";
|
||||
const ImageGalleryListView = ({ filter, filterData, removeFilterChip, clearFilter }) => {
|
||||
const [hoveredImage, setHoveredImage] = useState(null);
|
||||
const selectedProject = useSelectedProject();
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
@ -51,15 +52,25 @@ const ImageGalleryListView = ({filter}) => {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div className="main-content">
|
||||
<div className="col-12 mb-2 mt-2 px-4">
|
||||
<GalleryFilterChips
|
||||
filter={filter}
|
||||
filterData={filterData}
|
||||
removeFilterChip={removeFilterChip}
|
||||
clearFilter={clearFilter}
|
||||
/>
|
||||
</div>
|
||||
<div className="activity-section">
|
||||
{data?.data?.map((batch) => {
|
||||
if (!batch.documents?.length) return null;
|
||||
|
||||
const doc = batch.documents[0];
|
||||
const userName = `${doc.uploadedBy?.firstName || ""} ${
|
||||
doc.uploadedBy?.lastName || ""
|
||||
const userName = `${doc.uploadedBy?.firstName || ""} ${doc.uploadedBy?.lastName || ""
|
||||
}`.trim();
|
||||
const date = formatUTCToLocalTime(doc.uploadedAt);
|
||||
// const hasArrows = batch.documents.length > scrollThreshold;
|
||||
|
||||
@ -23,6 +23,7 @@ import GlobalModel from "../../components/common/GlobalModel";
|
||||
import ViewGallery from "../../components/gallary/ViewGallery";
|
||||
import { useFab } from "../../Context/FabContext";
|
||||
import GalleryFilterPanel from "../../components/gallary/GalleryFilterPanel";
|
||||
import { defaultGalleryFilterValue } from "../../components/gallary/GallerySchema";
|
||||
|
||||
const GalleryContext = createContext();
|
||||
|
||||
@ -36,12 +37,12 @@ export const useGalleryContext = () => {
|
||||
};
|
||||
|
||||
const ImageGalleryPage = () => {
|
||||
const [filter, setFilter] = useState();
|
||||
const [filter, setFilter] = useState(defaultGalleryFilterValue);
|
||||
const selectedProjectId = useSelectedProject();
|
||||
const { projectNames } = useProjectName();
|
||||
|
||||
const [filterData, setFilterdata] = useState(null);
|
||||
const updatedRef = useRef();
|
||||
const [openGallery, setOpenGallery] = useState({ isOpen: false, data: null });
|
||||
|
||||
const { data: assignedServices = [], isLoading } =
|
||||
useProjectAssignedServices(selectedProjectId);
|
||||
|
||||
@ -55,13 +56,18 @@ const ImageGalleryPage = () => {
|
||||
setOpenGallery,
|
||||
};
|
||||
|
||||
const clearFilter = () => setFilter(defaultGalleryFilterValue);
|
||||
const { setOffcanvasContent, setShowTrigger } = useFab();
|
||||
|
||||
useEffect(() => {
|
||||
setShowTrigger(true);
|
||||
setOffcanvasContent(
|
||||
"Gallery Filter",
|
||||
<GalleryFilterPanel onApply={setFilter} />
|
||||
<GalleryFilterPanel
|
||||
onApply={setFilter}
|
||||
ref={updatedRef}
|
||||
clearFilter={clearFilter}
|
||||
setFilterdata={setFilterdata} />
|
||||
);
|
||||
|
||||
return () => {
|
||||
@ -70,6 +76,22 @@ const ImageGalleryPage = () => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleRemoveChip = (key, id) => {
|
||||
setFilter((prev) => {
|
||||
const updated = { ...prev };
|
||||
|
||||
if (Array.isArray(updated[key])) {
|
||||
updated[key] = updated[key].filter((v) => v !== id);
|
||||
setTimeout(() => updatedRef.current?.resetFieldValue(key, updated[key]), 0);
|
||||
} else {
|
||||
updated[key] = null;
|
||||
setTimeout(() => updatedRef.current?.resetFieldValue(key, null), 0);
|
||||
}
|
||||
|
||||
return updated;
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<GalleryContext.Provider value={contextMessager}>
|
||||
<div className="container-fluid">
|
||||
@ -105,7 +127,11 @@ const ImageGalleryPage = () => {
|
||||
</div>
|
||||
)} */}
|
||||
|
||||
<ImageGalleryListView filter={filter} />
|
||||
<ImageGalleryListView
|
||||
filter={filter}
|
||||
filterData={filterData}
|
||||
removeFilterChip={handleRemoveChip}
|
||||
clearFilter={clearFilter} />
|
||||
</div>
|
||||
|
||||
{openGallery?.isOpen && (
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user