added currency,rename of ExpenseType to expenseCategory - hooks,( expenseCategoryIds = fileter object)
This commit is contained in:
parent
6a97dcf5f6
commit
6f228ed5f1
@ -4,21 +4,19 @@ const ExpenseFilterChips = ({ filters, filterData, removeFilterChip }) => {
|
||||
// Build chips from filters
|
||||
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,
|
||||
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");
|
||||
buildGroup(filters.expenseCategoryIds, filterData.expenseCategory, "Category", "expenseCategoryIds");
|
||||
|
||||
if (filters.startDate || filters.endDate) {
|
||||
const start = filters.startDate
|
||||
|
||||
@ -31,7 +31,7 @@ const ExpenseFilterPanel = forwardRef(({ onApply, handleGroupBy, setFilterdata }
|
||||
{ id: "submittedBy", name: "Submitted By" },
|
||||
{ id: "project", name: "Project" },
|
||||
{ id: "paymentMode", name: "Payment Mode" },
|
||||
{ id: "expensesType", name: "Expense Category" },
|
||||
{ id: "expenseCategory", name: "Expense Category" },
|
||||
{ id: "createdAt", name: "Submitted Date" },
|
||||
].sort((a, b) => a.name.localeCompare(b.name));
|
||||
}, []);
|
||||
@ -46,7 +46,7 @@ const ExpenseFilterPanel = forwardRef(({ onApply, handleGroupBy, setFilterdata }
|
||||
projectIds: defaultFilter.projectIds || [],
|
||||
createdByIds: defaultFilter.createdByIds || [],
|
||||
paidById: defaultFilter.paidById || [],
|
||||
ExpenseCategoryIds: defaultFilter.ExpenseCategoryIds || [],
|
||||
expenseCategoryIds: defaultFilter.expenseCategoryIds || [],
|
||||
isTransactionDate: defaultFilter.isTransactionDate ?? true,
|
||||
startDate: defaultFilter.startDate,
|
||||
endDate: defaultFilter.endDate,
|
||||
@ -214,7 +214,7 @@ const ExpenseFilterPanel = forwardRef(({ onApply, handleGroupBy, setFilterdata }
|
||||
valueKey="id"
|
||||
/>
|
||||
<SelectMultiple
|
||||
name="ExpenseCategoryIds"
|
||||
name="expenseCategoryIds"
|
||||
label="Category :"
|
||||
options={data.expenseCategory}
|
||||
labelKey={(item) => item.name}
|
||||
|
||||
@ -129,7 +129,7 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
|
||||
align: "text-start mx-2",
|
||||
},
|
||||
{
|
||||
key: "expensesCategory",
|
||||
key: "expenseCategory",
|
||||
label: "Expense Category",
|
||||
getValue: (e) => e.expenseCategory?.name || "N/A",
|
||||
align: "text-start",
|
||||
@ -225,6 +225,7 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
|
||||
]?.includes(groupBy);
|
||||
|
||||
const canEditExpense = (expense) => {
|
||||
debugger;
|
||||
return (
|
||||
(expense?.status?.id === EXPENSE_DRAFT ||
|
||||
EXPENSE_REJECTEDBY.includes(expense?.status?.id)) &&
|
||||
@ -352,8 +353,7 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
|
||||
})
|
||||
}
|
||||
></i>
|
||||
{canDetetExpense(expense) &&
|
||||
canEditExpense(expense) && (
|
||||
{canEditExpense(expense) && (
|
||||
<div className="dropdown z-2">
|
||||
<button
|
||||
type="button"
|
||||
@ -371,7 +371,6 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
|
||||
></i>
|
||||
</button>
|
||||
<ul className="dropdown-menu dropdown-menu-end w-auto">
|
||||
{canDetetExpense(expense) && (
|
||||
<li
|
||||
onClick={() =>
|
||||
setManageExpenseModal({
|
||||
@ -387,7 +386,6 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
)}
|
||||
|
||||
{canDetetExpense(expense) && (
|
||||
<li
|
||||
|
||||
@ -10,7 +10,7 @@ const ALLOWED_TYPES = [
|
||||
"image/jpeg",
|
||||
];
|
||||
|
||||
export const ExpenseSchema = (ExpenseCategories) => {
|
||||
export const ExpenseSchema = (expenseCategories) => {
|
||||
return z
|
||||
.object({
|
||||
projectId: z.string().min(1, { message: "Project is required" }),
|
||||
@ -70,12 +70,12 @@ export const ExpenseSchema = (ExpenseCategories) => {
|
||||
}
|
||||
)
|
||||
.superRefine((data, ctx) => {
|
||||
const ExpenseCategory = ExpenseCategories.find(
|
||||
(et) => et.id === data.expenseCategoryId
|
||||
const ExpenseCategory = expenseCategories?.find(
|
||||
(et) => et.id === data?.expenseCategoryId
|
||||
);
|
||||
if (
|
||||
ExpenseCategory?.noOfPersonsRequired &&
|
||||
(!data.noOfPersons || data.noOfPersons < 1)
|
||||
(!data?.noOfPersons || data?.noOfPersons < 1)
|
||||
) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
@ -168,7 +168,7 @@ export const defaultActionValues = {
|
||||
reimburseDate: null,
|
||||
reimburseById: null,
|
||||
tdsPercentage: null,
|
||||
baseAmount:null,
|
||||
baseAmount: null,
|
||||
taxAmount: null,
|
||||
};
|
||||
|
||||
@ -177,7 +177,7 @@ export const SearchSchema = z.object({
|
||||
statusIds: z.array(z.string()).optional(),
|
||||
createdByIds: z.array(z.string()).optional(),
|
||||
paidById: z.array(z.string()).optional(),
|
||||
ExpenseCategoryIds: z.array(z.string()).optional(),
|
||||
expenseCategoryIds: z.array(z.string()).optional(),
|
||||
startDate: z.string().optional(),
|
||||
endDate: z.string().optional(),
|
||||
isTransactionDate: z.boolean().default(true),
|
||||
@ -188,7 +188,7 @@ export const defaultFilter = {
|
||||
statusIds: [],
|
||||
createdByIds: [],
|
||||
paidById: [],
|
||||
ExpenseCategoryIds: [],
|
||||
expenseCategoryIds: [],
|
||||
isTransactionDate: true,
|
||||
startDate: null,
|
||||
endDate: null,
|
||||
|
||||
@ -7,6 +7,7 @@ import { useProjectName } from "../../hooks/useProjects";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { changeMaster } from "../../slices/localVariablesSlice";
|
||||
import useMaster, {
|
||||
useCurrencies,
|
||||
useExpenseCategory,
|
||||
useExpenseStatus,
|
||||
usePaymentMode,
|
||||
@ -29,6 +30,8 @@ import DatePicker from "../common/DatePicker";
|
||||
import ErrorPage from "../../pages/ErrorPage";
|
||||
import Label from "../common/Label";
|
||||
import EmployeeSearchInput from "../common/EmployeeSearchInput";
|
||||
import Filelist from "./Filelist";
|
||||
import { DEFAULT_CURRENCY } from "../../utils/constants";
|
||||
|
||||
const ManageExpense = ({ closeModal, expenseToEdit = null }) => {
|
||||
const {
|
||||
@ -36,7 +39,7 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => {
|
||||
isLoading,
|
||||
error: ExpenseErrorLoad,
|
||||
} = useExpense(expenseToEdit);
|
||||
const [ExpenseType, setExpenseType] = useState();
|
||||
const [expenseCategory, setExpenseCategory] = useState();
|
||||
const dispatch = useDispatch();
|
||||
const {
|
||||
expenseCategories,
|
||||
@ -65,7 +68,11 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => {
|
||||
error,
|
||||
isError: isProjectError,
|
||||
} = useProjectName();
|
||||
|
||||
const {
|
||||
data: currencies,
|
||||
isLoading: currencyLoading,
|
||||
error: currencyError,
|
||||
} = useCurrencies();
|
||||
const {
|
||||
PaymentModes,
|
||||
loading: PaymentModeLoading,
|
||||
@ -81,6 +88,7 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => {
|
||||
isLoading: EmpLoading,
|
||||
isError: isEmployeeError,
|
||||
} = useEmployeesNameByProject(selectedproject);
|
||||
|
||||
const files = watch("billAttachments");
|
||||
const onFileChange = async (e) => {
|
||||
const newFiles = Array.from(e.target.files);
|
||||
@ -157,6 +165,7 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => {
|
||||
amount: data.amount || "",
|
||||
noOfPersons: data.noOfPersons || "",
|
||||
gstNumber: data.gstNumber || "",
|
||||
currencyId: data.currencyId || DEFAULT_CURRENCY,
|
||||
billAttachments: data.documents
|
||||
? data.documents.map((doc) => ({
|
||||
fileName: doc.fileName,
|
||||
@ -195,7 +204,9 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => {
|
||||
const expenseCategoryId = watch("expenseCategoryId");
|
||||
|
||||
useEffect(() => {
|
||||
setExpenseType(expenseCategories?.find((type) => type.id === expenseCategoryId));
|
||||
setExpenseCategory(
|
||||
expenseCategories?.find((type) => type.id === expenseCategoryId)
|
||||
);
|
||||
}, [expenseCategoryId]);
|
||||
|
||||
const handleClose = () => {
|
||||
@ -238,7 +249,7 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => {
|
||||
|
||||
<div className="col-md-6">
|
||||
<Label htmlFor="expenseCategoryId" className="form-label" required>
|
||||
Expense Type
|
||||
Expense Category
|
||||
</Label>
|
||||
<select
|
||||
className="form-select form-select-sm"
|
||||
@ -246,7 +257,7 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => {
|
||||
{...register("expenseCategoryId")}
|
||||
>
|
||||
<option value="" disabled>
|
||||
Select Type
|
||||
Select Category
|
||||
</option>
|
||||
{ExpenseLoading ? (
|
||||
<option disabled>Loading...</option>
|
||||
@ -258,9 +269,9 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => {
|
||||
))
|
||||
)}
|
||||
</select>
|
||||
{errors.expenseCategoryId && (
|
||||
{errors.expensesCategoryId && (
|
||||
<small className="danger-text">
|
||||
{errors.expenseCategoryId.message}
|
||||
{errors.expensesCategoryId.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
@ -295,34 +306,10 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => {
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="col-12 col-md-6 text-start">
|
||||
<Label htmlFor="paidById" className="form-label" required>
|
||||
Paid By
|
||||
<Label className="form-label" required>
|
||||
Paid By{" "}
|
||||
</Label>
|
||||
{/* <select
|
||||
className="form-select form-select-sm"
|
||||
id="paymentModeId"
|
||||
{...register("paidById")}
|
||||
disabled={!selectedproject}
|
||||
>
|
||||
<option value="" disabled>
|
||||
Select Person
|
||||
</option>
|
||||
{EmpLoading ? (
|
||||
<option disabled>Loading...</option>
|
||||
) : (
|
||||
employees?.map((emp) => (
|
||||
<option key={emp.id} value={emp.id}>
|
||||
{`${emp.firstName} ${emp.lastName} `}
|
||||
</option>
|
||||
))
|
||||
)}
|
||||
</select>
|
||||
{errors.paidById && (
|
||||
<small className="danger-text">{errors.paidById.message}</small>
|
||||
)} */}
|
||||
|
||||
<EmployeeSearchInput
|
||||
control={control}
|
||||
name="paidById"
|
||||
@ -339,6 +326,7 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => {
|
||||
</Label>
|
||||
<DatePicker
|
||||
name="transactionDate"
|
||||
className="w-100"
|
||||
control={control}
|
||||
maxDate={new Date()}
|
||||
/>
|
||||
@ -436,9 +424,37 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{ExpenseType?.noOfPersonsRequired && (
|
||||
<div className="col-md-6 mt-2 text-start">
|
||||
<label className="form-label ">No. of Persons</label>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-md-6 text-start ">
|
||||
<Label htmlFor="currencyId" className="form-label" required>
|
||||
Select Currency
|
||||
</Label>
|
||||
<select
|
||||
className="form-select form-select-sm"
|
||||
id="currencyId"
|
||||
{...register("currencyId")}
|
||||
>
|
||||
<option value="" disabled>
|
||||
Select Currency
|
||||
</option>
|
||||
{currencyLoading ? (
|
||||
<option disabled>Loading...</option>
|
||||
) : (
|
||||
currencies?.map((currency) => (
|
||||
<option key={currency.id} value={currency.id}>
|
||||
{`${currency.currencyName} (${currency.symbol}) `}
|
||||
</option>
|
||||
))
|
||||
)}
|
||||
</select>
|
||||
{errors.currencyId && (
|
||||
<small className="danger-text">{errors.currencyId.message}</small>
|
||||
)}
|
||||
</div>
|
||||
{expenseCategory?.noOfPersonsRequired && (
|
||||
<div className="col-md-6 text-start">
|
||||
<Label className="form-label" required>No. of Persons</Label>
|
||||
<input
|
||||
type="number"
|
||||
id="noOfPersons"
|
||||
@ -510,40 +526,11 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => {
|
||||
</small>
|
||||
)}
|
||||
{files.length > 0 && (
|
||||
<div className="d-block">
|
||||
{files
|
||||
.filter((file) => {
|
||||
if (expenseToEdit) {
|
||||
return file.isActive;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.map((file, idx) => (
|
||||
<a
|
||||
key={idx}
|
||||
className="d-flex justify-content-between text-start p-1"
|
||||
href={file.preSignedUrl || "#"}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<div>
|
||||
<span className="mb-0 text-secondary small d-block">
|
||||
{file.fileName}
|
||||
</span>
|
||||
<span className="text-body-secondary small d-block">
|
||||
{file.fileSize ? formatFileSize(file.fileSize) : ""}
|
||||
</span>
|
||||
</div>
|
||||
<i
|
||||
className="bx bx-trash bx-sm cursor-pointer text-danger"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
removeFile(expenseToEdit ? file.documentId : idx);
|
||||
}}
|
||||
></i>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
<Filelist
|
||||
files={files}
|
||||
removeFile={removeFile}
|
||||
expenseToEdit={expenseToEdit}
|
||||
/>
|
||||
)}
|
||||
|
||||
{Array.isArray(errors.billAttachments) &&
|
||||
|
||||
@ -10,6 +10,16 @@ import {
|
||||
} from "@tanstack/react-query";
|
||||
import showToast from "../../services/toastService";
|
||||
|
||||
export const useCurrencies = () => {
|
||||
return useQuery({
|
||||
queryKey: ["currencies"],
|
||||
queryFn: async () => {
|
||||
const resp = await MasterRespository.getCurrencies();
|
||||
return resp.data;
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const usePaymentAjustmentHead = (isActive) => {
|
||||
return useQuery({
|
||||
queryKey: ["paymentType",isActive],
|
||||
@ -171,7 +181,7 @@ export const useExpenseCategory = () => {
|
||||
},
|
||||
});
|
||||
|
||||
return { ExpenseTypes, loading, error };
|
||||
return { expenseCategories, loading, error };
|
||||
};
|
||||
export const usePaymentMode = () => {
|
||||
const {
|
||||
|
||||
@ -190,7 +190,7 @@ const ExpensePage = () => {
|
||||
{viewExpense.view && (
|
||||
<GlobalModel
|
||||
isOpen
|
||||
size="lg"
|
||||
size="xl"
|
||||
modalType="top"
|
||||
closeModal={() => setViewExpense({ expenseId: null, view: false })}
|
||||
>
|
||||
|
||||
@ -50,7 +50,10 @@ export const MasterRespository = {
|
||||
"Contact Category": (id) => api.delete(`/api/master/contact-category/${id}`),
|
||||
"Contact Tag": (id) => api.delete(`/api/master/contact-tag/${id}`),
|
||||
"Expense Type": (id, isActive) =>
|
||||
api.delete(`/api/Master/expenses-category/delete/${id}`, (isActive = false)),
|
||||
api.delete(
|
||||
`/api/Master/expenses-category/delete/${id}`,
|
||||
(isActive = false)
|
||||
),
|
||||
"Payment Mode": (id, isActive) =>
|
||||
api.delete(`/api/Master/payment-mode/delete/${id}`, (isActive = false)),
|
||||
"Expense Status": (id, isActive) =>
|
||||
@ -58,7 +61,11 @@ export const MasterRespository = {
|
||||
"Document Type": (id) => api.delete(`/api/Master/document-type/delete/${id}`),
|
||||
"Document Category": (id) =>
|
||||
api.delete(`/api/Master/document-category/delete/${id}`),
|
||||
"Payment Adjustment Head":(id,isActive)=>api.delete(`/api/Master/payment-adjustment-head/delete/${id}`,(isActive=false)),
|
||||
"Payment Adjustment Head": (id, isActive) =>
|
||||
api.delete(
|
||||
`/api/Master/payment-adjustment-head/delete/${id}`,
|
||||
(isActive = false)
|
||||
),
|
||||
|
||||
getWorkCategory: () => api.get(`/api/master/work-categories`),
|
||||
createWorkCategory: (data) => api.post(`/api/master/work-category`, data),
|
||||
@ -79,7 +86,8 @@ export const MasterRespository = {
|
||||
getAuditStatus: () => api.get("/api/Master/work-status"),
|
||||
|
||||
getExpenseCategories: () => api.get("/api/Master/expenses-categories"),
|
||||
createExpenseCategory: (data) => api.post("/api/Master/expenses-category", data),
|
||||
createExpenseCategory: (data) =>
|
||||
api.post("/api/Master/expenses-category", data),
|
||||
updateExpenseCategory: (id, data) =>
|
||||
api.put(`/api/Master/expenses-category/edit/${id}`, data),
|
||||
|
||||
@ -134,6 +142,10 @@ export const MasterRespository = {
|
||||
|
||||
getPaymentAdjustmentHead: (isActive) =>
|
||||
api.get(`/api/Master/payment-adjustment-head/list?isActive=${isActive}`),
|
||||
createPaymentAjustmentHead:(data)=>api.post(`/api/Master/payment-adjustment-head`, data),
|
||||
updatePaymentAjustmentHead:(id,data)=>api.put(`/api/Master/payment-adjustment-head/edit/${id}`, data)
|
||||
createPaymentAjustmentHead: (data) =>
|
||||
api.post(`/api/Master/payment-adjustment-head`, data),
|
||||
updatePaymentAjustmentHead: (id, data) =>
|
||||
api.put(`/api/Master/payment-adjustment-head/edit/${id}`, data),
|
||||
|
||||
getCurrencies: () => api.get(`/api/Master/currencies/list`),
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user