diff --git a/src/components/Expenses/ExpenseFilterChips.jsx b/src/components/Expenses/ExpenseFilterChips.jsx index 9287e38e..c44dd7a5 100644 --- a/src/components/Expenses/ExpenseFilterChips.jsx +++ b/src/components/Expenses/ExpenseFilterChips.jsx @@ -40,43 +40,45 @@ const ExpenseFilterChips = ({ filters, filterData, removeFilterChip }) => { if (!filterChips.length) return null; return ( +
+
+
+ {filterChips.map((chip) => ( +
+ {/* Chip Label */} + {chip.label}: -
-
- Filter: -
-
- {filterChips.map((chip) => ( - - {chip.label}: -
- {chip.items.map((item) => ( - - {item.name} -
-
- ))} -
+ {/* Chip Items */} +
+ {chip.items.map((item) => ( + + {item.name} +
+ ))} +
+
+
+ ); @@ -85,138 +87,3 @@ const ExpenseFilterChips = ({ filters, filterData, removeFilterChip }) => { export default ExpenseFilterChips; -// import React, { useMemo } from "react"; - -// const ExpenseFilterChips = ({ filters, filterData, removeFilterChip, groupBy }) => { -// // Build filter chips -// const filterChips = useMemo(() => { -// const chips = []; - -// const buildGroup = (ids, list, label, key) => { -// if (!ids?.length) return; -// const items = ids.map((id) => ({ -// id, -// name: list.find((item) => item.id === id)?.name || id, -// })); -// chips.push({ key, label, items }); -// }; - -// buildGroup(filters.projectIds, filterData.projects, "Project", "projectIds"); -// buildGroup(filters.createdByIds, filterData.createdBy, "Submitted By", "createdByIds"); -// buildGroup(filters.paidById, filterData.paidBy, "Paid By", "paidById"); -// buildGroup(filters.statusIds, filterData.status, "Status", "statusIds"); -// buildGroup(filters.ExpenseTypeIds, filterData.expensesType, "Category", "ExpenseTypeIds"); - -// if (filters.startDate || filters.endDate) { -// const start = filters.startDate -// ? new Date(filters.startDate).toLocaleDateString("en-GB", { -// day: "2-digit", -// month: "short", -// year: "numeric", -// }) -// : ""; -// const end = filters.endDate -// ? new Date(filters.endDate).toLocaleDateString("en-GB", { -// day: "2-digit", -// month: "short", -// year: "numeric", -// }) -// : ""; -// chips.push({ -// key: "dateRange", -// label: "Date Range", -// items: [{ id: "dateRange", name: `${start} - ${end}` }], -// }); -// } - -// return chips; -// }, [filters, filterData]); - -// // Prepare groupBy chip -// const groupByChip = useMemo(() => { -// if (!groupBy) return null; - -// const formattedGroup = -// groupBy === "transactionDate" -// ? "Transaction Date" -// : groupBy === "status" -// ? "Status" -// : groupBy === "submittedBy" -// ? "Submitted By" -// : groupBy === "project" -// ? "Project" -// : groupBy === "paymentMode" -// ? "Payment Mode" -// : groupBy === "expensesType" -// ? "Expense Type" -// : groupBy === "createdAt" -// ? "Submitted Date" -// : "Others"; - -// return { -// key: "groupBy", -// label: "Group By", -// items: [{ id: groupBy, name: formattedGroup }], -// }; -// }, [groupBy]); - -// if (!filterChips.length && !groupByChip) return null; - -// return ( -//
-// {/* Filters */} -// {filterChips.length > 0 && ( -// <> -// Filters: -// {filterChips.map((chip) => ( -// -// {chip.label}: -//
-// {chip.items.map((item) => ( -// -// {item.name} -//
-//
-// ))} -// -// )} - -// {/* Group By */} -// {groupByChip && ( -// <> -// Group By: -// {groupByChip.items.map((item) => ( -// -// {item.name} -// -// ))} -// -// )} -//
-// ); -// }; - -// export default ExpenseFilterChips; diff --git a/src/components/Expenses/ExpenseFilterPanel.jsx b/src/components/Expenses/ExpenseFilterPanel.jsx index 20d300e1..fca03329 100644 --- a/src/components/Expenses/ExpenseFilterPanel.jsx +++ b/src/components/Expenses/ExpenseFilterPanel.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState, useMemo } from "react"; +import React, {forwardRef, useEffect,useImperativeHandle, useState, useMemo } from "react"; import { FormProvider, useForm, Controller } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { defaultFilter, SearchSchema } from "./ExpenseSchema"; @@ -15,7 +15,7 @@ import { useExpenseFilter } from "../../hooks/useExpense"; import { ExpenseFilterSkeleton } from "./ExpenseSkeleton"; import { useLocation, useNavigate, useParams } from "react-router-dom"; -const ExpenseFilterPanel = ({ onApply, handleGroupBy, setFilterdata }) => { +const ExpenseFilterPanel = forwardRef(({ onApply, handleGroupBy, setFilterdata }, ref) => { const { status } = useParams(); const navigate = useNavigate(); const selectedProjectId = useSelector( @@ -77,6 +77,18 @@ const ExpenseFilterPanel = ({ onApply, handleGroupBy, setFilterdata }) => { if (group) setSelectedGroup(group); }; + 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 + })); + const onSubmit = (formData) => { onApply({ ...formData, @@ -280,6 +292,6 @@ const ExpenseFilterPanel = ({ onApply, handleGroupBy, setFilterdata }) => { ); -}; +}); export default ExpenseFilterPanel; \ No newline at end of file diff --git a/src/components/Expenses/ExpenseList.jsx b/src/components/Expenses/ExpenseList.jsx index 39ef9b50..642b31d0 100644 --- a/src/components/Expenses/ExpenseList.jsx +++ b/src/components/Expenses/ExpenseList.jsx @@ -115,10 +115,10 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => { }; const expenseColumns = [ - { + { key: "expenseUId", label: "Expense Id", - getValue: (e) => e.expenseUId|| "N/A", + getValue: (e) => e.expenseUId || "N/A", align: "text-start mx-2", }, { @@ -183,7 +183,7 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => { }, ]; - if (isInitialLoading) return ; + if (isInitialLoading && !data) return ; if (isError) return
{error?.message}
; const grouped = groupBy @@ -305,26 +305,61 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => { }) } > - {canEditExpense(expense) && ( - - setManageExpenseModal({ - IsOpen: true, - expenseId: expense.id, - }) - } - > - )} - {canDetetExpense(expense) && ( - { - setIsDeleteModalOpen(true); - setDeletingId(expense.id); - }} - > - )} + {canDetetExpense(expense) && + canEditExpense(expense) && ( +
+ +
    + {canDetetExpense(expense) && ( +
  • + setManageExpenseModal({ + IsOpen: true, + expenseId: expense.id, + }) + } + > + + + + Modify + + +
  • + )} + + {canDetetExpense(expense) && ( +
  • { + setIsDeleteModalOpen(true); + setDeletingId(expense.id); + }} + > + + + + Delete + + +
  • + )} +
+
+ )}
diff --git a/src/components/Layout/Header.jsx b/src/components/Layout/Header.jsx index c75851c2..e2d10ebf 100644 --- a/src/components/Layout/Header.jsx +++ b/src/components/Layout/Header.jsx @@ -40,11 +40,11 @@ const Header = () => { const isProjectPath = pathname === "/projects"; const isDirectory = pathname === "/directory"; const isEmployeeList = pathname === "/employees"; - const isExpense = pathname === "/expenses"; + // const isExpense = pathname === "/expenses"; const isEmployeeProfile = UUID_REGEX.test(pathname); const hideDropPaths = - isDirectory || isEmployeeList || isExpense || isEmployeeProfile; + isDirectory || isEmployeeList || isEmployeeProfile; const showProjectDropdown = !hideDropPaths; diff --git a/src/pages/Expense/ExpensePage.jsx b/src/pages/Expense/ExpensePage.jsx index f6d9be16..f826c018 100644 --- a/src/pages/Expense/ExpensePage.jsx +++ b/src/pages/Expense/ExpensePage.jsx @@ -1,5 +1,5 @@ -import React, { createContext, useContext, useState, useEffect } from "react"; -import { useForm } from "react-hook-form"; +import React, { createContext, useContext, useState, useEffect, useRef } from "react"; +import { useForm, useFormContext } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { useSelector } from "react-redux"; @@ -39,7 +39,7 @@ const ExpensePage = () => { const [filters, setFilters] = useState(defaultFilter); const [groupBy, setGroupBy] = useState("transactionDate"); const [searchText, setSearchText] = useState(""); - + const filterPanelRef = useRef(); const [ManageExpenseModal, setManageExpenseModal] = useState({ IsOpen: null, expenseId: null, @@ -59,30 +59,28 @@ const ExpensePage = () => { const IsViewAll = useHasUserPermission(VIEW_ALL_EXPNESE); const IsViewSelf = useHasUserPermission(VIEW_SELF_EXPENSE); + const { setOffcanvasContent, setShowTrigger } = useFab(); - const methods = useForm({ - resolver: zodResolver(SearchSchema), - defaultValues: defaultFilter, - }); - const { reset } = methods; + const [filterData, setFilterdata] = useState(defaultFilter); - const clearFilter = () => { - setFilters(defaultFilter); - reset(); - }; - - const removeFilterChip = (key, id) => { + + + + const removeFilterChip = (key, id) => { setFilters((prev) => { const updated = { ...prev }; if (Array.isArray(updated[key])) { updated[key] = updated[key].filter((v) => v !== id); + filterPanelRef.current?.resetFieldValue(key, updated[key]); } else if (key === "dateRange") { updated.startDate = null; updated.endDate = null; + filterPanelRef.current?.resetFieldValue("startDate", null); + filterPanelRef.current?.resetFieldValue("endDate", null); } return updated; }); @@ -94,9 +92,10 @@ const ExpensePage = () => { setOffcanvasContent( "Expense Filters", ); } @@ -138,9 +137,7 @@ const ExpensePage = () => {
- + {IsCreatedAble && (
- +