From def5ef71f6a74799f6dbcb98863bc2b0d5c603ec Mon Sep 17 00:00:00 2001 From: Kartik Sharma Date: Wed, 10 Dec 2025 14:24:28 +0530 Subject: [PATCH] Adding Filter chips at Tenant. --- .../TaskReportFilterPanel.jsx | 4 +- .../DailyProgressRport/TaskReportList.jsx | 1 - src/components/Tenant/TenantFilterChips.jsx | 100 ++++++++++++++++ src/components/Tenant/TenantFilterPanel.jsx | 42 +++++-- src/components/Tenant/TenantsList.jsx | 107 ++++++++++-------- src/pages/Tenant/TenantPage.jsx | 40 ++++++- 6 files changed, 233 insertions(+), 61 deletions(-) create mode 100644 src/components/Tenant/TenantFilterChips.jsx diff --git a/src/components/DailyProgressRport/TaskReportFilterPanel.jsx b/src/components/DailyProgressRport/TaskReportFilterPanel.jsx index c5f833bb..55b0810b 100644 --- a/src/components/DailyProgressRport/TaskReportFilterPanel.jsx +++ b/src/components/DailyProgressRport/TaskReportFilterPanel.jsx @@ -30,8 +30,8 @@ const TaskReportFilterPanel = forwardRef(({ handleFilter, setFilterdata, clearFi buildingIds: TaskReportDefaultValue.buildingIds || [], floorIds: TaskReportDefaultValue.floorIds || [], activityIds: TaskReportDefaultValue.activityIds || [], - dateFrom: TaskReportDefaultValue.startDate, - dateTo: TaskReportDefaultValue.endDate, + dateFrom: TaskReportDefaultValue.dateFrom, + dateTo: TaskReportDefaultValue.dateTo, }; }, [selectedProject]); diff --git a/src/components/DailyProgressRport/TaskReportList.jsx b/src/components/DailyProgressRport/TaskReportList.jsx index a991a1d3..e9e74c80 100644 --- a/src/components/DailyProgressRport/TaskReportList.jsx +++ b/src/components/DailyProgressRport/TaskReportList.jsx @@ -203,7 +203,6 @@ const TaskReportList = ({ filter, filterData, removeFilterChip, clearFilter }) = removeFilterChip={removeFilterChip} clearFilter={clearFilter} /> -
diff --git a/src/components/Tenant/TenantFilterChips.jsx b/src/components/Tenant/TenantFilterChips.jsx new file mode 100644 index 00000000..9c5b8b8b --- /dev/null +++ b/src/components/Tenant/TenantFilterChips.jsx @@ -0,0 +1,100 @@ +import React, { useMemo } from "react"; +import { TENANT_STATUS, reference } from "../../utils/constants"; +import { formatUTCToLocalTime } from "../../utils/dateUtils"; + +const TenantFilterChips = ({ filter, filterData, removeFilterChip, clearFilter }) => { + const data = filterData || {}; + + const filterChips = useMemo(() => { + const chips = []; + + const addGroup = (ids, list, label, key, valueKey = "id") => { + if (!ids || ids.length === 0) return; + + const items = ids.map((id) => { + const found = list?.find((i) => i[valueKey] === id); + return { + id, + name: found?.name || id, + }; + }); + + chips.push({ key, label, items }); + }; + + // Industries + addGroup(filter?.industryIds, data, "Industries", "industryIds"); + + // References + addGroup(filter?.references, reference, "References", "references", "val"); + + // Tenant Status + addGroup(filter?.tenantStatusIds, TENANT_STATUS, "Status", "tenantStatusIds"); + + // Date Range Chip + if (filter?.startDate || filter?.endDate) { + chips.push({ + key: "date", + label: "Date Range", + items: [ + { + id: "date-range", + name: `${filter?.startDate ? formatUTCToLocalTime(filter.startDate) : ""}${ + filter?.endDate ? " to " + formatUTCToLocalTime(filter.endDate) : "" + }`, + }, + ], + }); + } + + return chips; + }, [filter, filterData]); + + if (!filterChips.length) return null; + + return ( +
+ {filterChips.map((chipGroup) => ( +
+ {chipGroup.label}: + + {chipGroup.items.map((item) => ( + + {item.name} + + {/* Remove Date Range → remove full filter */} + {chipGroup.key === "date" ? ( +
+ ))} +
+ ); +}; + +export default TenantFilterChips; diff --git a/src/components/Tenant/TenantFilterPanel.jsx b/src/components/Tenant/TenantFilterPanel.jsx index 1c2c43ca..8700391b 100644 --- a/src/components/Tenant/TenantFilterPanel.jsx +++ b/src/components/Tenant/TenantFilterPanel.jsx @@ -1,5 +1,5 @@ import { zodResolver } from "@hookform/resolvers/zod"; -import React, { useState, useCallback, useEffect } from "react"; +import React, { useState, useCallback, useEffect, useImperativeHandle, forwardRef, useMemo } from "react"; import { FormProvider, useForm, useFormContext } from "react-hook-form"; import { defaultFilterValues, filterSchema } from "./TenantSchema"; import Label from "../common/Label"; @@ -10,16 +10,44 @@ import { DateRangePicker1 } from "../common/DateRangePicker"; import moment from "moment"; import { useLocation } from "react-router-dom"; -const TenantFilterPanel = ({ onApply }) => { +const TenantFilterPanel = forwardRef(({ onApply, setFilterdata, clearFilter }, ref) => { const [resetKey, setResetKey] = useState(0); const methods = useForm({ resolver: zodResolver(filterSchema), defaultValues: defaultFilterValues, }); + const { handleSubmit, reset, setValue } = methods; + const { data: industries, isLoading } = useIndustries(); + + const dynamicDefaultFilter = useMemo(() => { + return { + ...defaultFilterValues, + industryIds: defaultFilterValues.industryIds || [], + tenantStatusIds: defaultFilterValues.tenantStatusIds || [], + references: defaultFilterValues.references || [], + startDate: defaultFilterValues.startDate, + endDate: defaultFilterValues.endDate, + }; + }, [defaultFilterValues]); + +useImperativeHandle(ref, () => ({ + resetFieldValue: (name, value) => { + setValue(name, value); + }, + resetFields: () => { + reset(defaultFilterValues); + setResetKey(prev => prev + 1); // reset date picker + } +})); + + + useEffect(() => { + if (industries && setFilterdata) { + setFilterdata(industries); + } + }, [industries, setFilterdata]); - const { handleSubmit, reset } = methods; - const { data: industries = [], isLoading } = useIndustries(); const handleClosePanel = useCallback(() => { document.querySelector(".offcanvas.show .btn-close")?.click(); @@ -32,9 +60,8 @@ const TenantFilterPanel = ({ onApply }) => { startDate: moment.utc(formData.startDate, "DD-MM-YYYY").toISOString(), endDate: moment.utc(formData.endDate, "DD-MM-YYYY").toISOString(), }); - handleClosePanel(); }, - [onApply, handleClosePanel] + [onApply] ); @@ -65,6 +92,7 @@ const TenantFilterPanel = ({ onApply }) => { endField="endDate" resetSignal={resetKey} defaultRange={false} + className="w-100" />
@@ -119,6 +147,6 @@ const TenantFilterPanel = ({ onApply }) => { ); -}; +}); export default TenantFilterPanel; diff --git a/src/components/Tenant/TenantsList.jsx b/src/components/Tenant/TenantsList.jsx index d82cb6f2..bb6ac50c 100644 --- a/src/components/Tenant/TenantsList.jsx +++ b/src/components/Tenant/TenantsList.jsx @@ -7,12 +7,14 @@ import Pagination from "../common/Pagination"; import { TenantTableSkeleton } from "./TenanatSkeleton"; import { useTenantContext } from "../../pages/Tenant/TenantPage"; import { useNavigate } from "react-router-dom"; +import TenantFilterChips from "./TenantFilterChips"; const TenantsList = ({ filters, searchText, setIsRefetching, setRefetchFn, + filterData, removeFilterChip, clearFilter }) => { const [currentPage, setCurrentPage] = useState(1); const navigate = useNavigate(); @@ -135,54 +137,65 @@ const TenantsList = ({ ); return ( <> -
-
-
- - - {TenantColumns.map((col) => ( - - ))} - - - - {data?.data.length > 0 ? ( - data.data.map((tenant) => ( - - {TenantColumns.map((col) => ( - - ))} - - )) - ) : ( - - +
+
+ + +
+
+
+
-
{col.label}
-
- {col.customRender - ? col.customRender(tenant) - : col.getValue(tenant)} -
- No Tenants Found -
+ + + {TenantColumns.map((col) => ( + + ))} - )} - -
+
{col.label}
+
- {data?.data?.length > 0 && ( - - )} + + + {data?.data.length > 0 ? ( + data.data.map((tenant) => ( + + {TenantColumns.map((col) => ( + + {col.customRender + ? col.customRender(tenant) + : col.getValue(tenant)} + + ))} + + )) + ) : ( + + + No Tenants Found + + + )} + + + {data?.data?.length > 0 && ( + + )} +
diff --git a/src/pages/Tenant/TenantPage.jsx b/src/pages/Tenant/TenantPage.jsx index 3ab2015c..8d805cdf 100644 --- a/src/pages/Tenant/TenantPage.jsx +++ b/src/pages/Tenant/TenantPage.jsx @@ -5,6 +5,7 @@ import React, { useContext, useCallback, useMemo, + useRef, } from "react"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; @@ -59,6 +60,7 @@ const TenantPage = () => { const [refetchFn, setRefetchFn] = useState(null); const [filters, setFilters] = useState(); + // ---------- Hooks ---------- const debouncedSearch = useDebounce(searchText, 500); const { setOffcanvasContent, setShowTrigger } = useFab(); @@ -66,6 +68,9 @@ const TenantPage = () => { const isSuperTenant = useHasUserPermission(SUPPER_TENANT); const canManageTenants = useHasUserPermission(MANAGE_TENANTS); const isSelfTenant = useHasUserPermission(VIEW_TENANTS); + const updatedRef = useRef(); + const [filterData, setFilterdata] = useState(null); + const [filter, setFilter] = useState('') const methods = useForm({ resolver: zodResolver(filterSchema), @@ -77,8 +82,18 @@ const TenantPage = () => { setFilters(values); }, []); + const clearFilter = () => { + setFilters(defaultFilterValues); // update active filters + updatedRef.current?.resetFields?.(); // reset RHF fields in panel + }; + const filterPanelElement = useMemo( - () => , + () => , [handleApplyFilters] ); // ---------- Fab Filter Panel ---------- @@ -112,6 +127,20 @@ const TenantPage = () => { // ---------- Context Value ---------- const contextValue = {}; + const handleRemoveChip = (key, id) => { + setFilters((prev) => { + const updated = { ...prev }; + if (Array.isArray(updated[key])) { + updated[key] = updated[key].filter((v) => v !== id); + } else { + updated[key] = null; + } + + setTimeout(() => updatedRef.current?.resetFieldValue(key, updated[key]), 0); + return updated; + }); + }; + return (
@@ -121,7 +150,7 @@ const TenantPage = () => { { label: "Tenant", link: null }, ]} /> -
+
{/* Super Tenant Actions */} {isSuperTenant && (
@@ -157,10 +186,13 @@ const TenantPage = () => { {/* Tenant List or Access Denied */} {isSuperTenant ? ( ) : !isSelfTenant ? (