update attendnace and expense
This commit is contained in:
parent
4ea1e06a9c
commit
4e48478fbc
@ -33,7 +33,7 @@ const createSchema = (modeldata) => {
|
|||||||
const checkOut = new Date(checkIn);
|
const checkOut = new Date(checkIn);
|
||||||
checkOut.setHours(hour, minute, 0, 0);
|
checkOut.setHours(hour, minute, 0, 0);
|
||||||
|
|
||||||
return checkOut > checkIn;
|
return checkOut >= checkIn;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}, {
|
}, {
|
||||||
@ -83,7 +83,7 @@ const CheckInCheckOut = ({ modeldata, closeModal, handleSubmitForm }) => {
|
|||||||
Id: modeldata?.id || null,
|
Id: modeldata?.id || null,
|
||||||
comment: data.description,
|
comment: data.description,
|
||||||
employeeID: modeldata.employeeId,
|
employeeID: modeldata.employeeId,
|
||||||
projectId: projectId,
|
// projectId: projectId,
|
||||||
date: new Date().toISOString(),
|
date: new Date().toISOString(),
|
||||||
markTime: data.markTime,
|
markTime: data.markTime,
|
||||||
latitude: coords.latitude.toString(),
|
latitude: coords.latitude.toString(),
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import React, { useState, useMemo } from "react";
|
|||||||
import ApexChart from "../Charts/Circle";
|
import ApexChart from "../Charts/Circle";
|
||||||
import { useProjects } from "../../hooks/useProjects";
|
import { useProjects } from "../../hooks/useProjects";
|
||||||
import { useDashboard_AttendanceData } from "../../hooks/useDashboard_Data";
|
import { useDashboard_AttendanceData } from "../../hooks/useDashboard_Data";
|
||||||
import { useSelectedProject } from "../../hooks/useSelectedProject"; // ✅ your custom hook
|
import { useSelectedProject } from "../../hooks/useSelectedProject";
|
||||||
|
|
||||||
const Attendance = () => {
|
const Attendance = () => {
|
||||||
const { projects } = useProjects();
|
const { projects } = useProjects();
|
||||||
|
|||||||
50
src/components/Expenses/ActiveFilters.jsx
Normal file
50
src/components/Expenses/ActiveFilters.jsx
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
const ActiveFilters = ({ filters, optionsLookup = {}, onRemove }) => {
|
||||||
|
const entries = Object.entries(filters || {});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="d-flex flex-wrap gap-2">
|
||||||
|
{entries.map(([key, value]) => {
|
||||||
|
if (!value || (Array.isArray(value) && value.length === 0)) return null;
|
||||||
|
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value.map((v) => {
|
||||||
|
const label = optionsLookup[key]?.[v] || v;
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
key={`${key}-${v}`}
|
||||||
|
className="badge bg-label-primary cursor-pointer"
|
||||||
|
onClick={() => onRemove(key, v)}
|
||||||
|
>
|
||||||
|
{label} <i className="bx bx-x ms-1"></i>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value === "boolean") {
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
key={key}
|
||||||
|
className="badge bg-label-success cursor-pointer"
|
||||||
|
onClick={() => onRemove(key)}
|
||||||
|
>
|
||||||
|
{key}: {value ? "Yes" : "No"} <i className="bx bx-x ms-1"></i>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span className="badge bg-primary">
|
||||||
|
{data?.startDate && data?.endDate
|
||||||
|
? `${formatUTCToLocalTime(
|
||||||
|
data.startDate
|
||||||
|
)} - ${formatUTCToLocalTime(data.endDate)}`
|
||||||
|
: "No dates"}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ActiveFilters;
|
||||||
@ -61,33 +61,33 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
|
|||||||
let key;
|
let key;
|
||||||
switch (field) {
|
switch (field) {
|
||||||
case "transactionDate":
|
case "transactionDate":
|
||||||
key = item.transactionDate?.split("T")[0];
|
key = item?.transactionDate?.split("T")[0];
|
||||||
break;
|
break;
|
||||||
case "status":
|
case "status":
|
||||||
key = item.status?.displayName || "Unknown";
|
key = item?.status?.displayName || "Unknown";
|
||||||
break;
|
break;
|
||||||
case "submittedBy":
|
case "submittedBy":
|
||||||
key = `${item.createdBy?.firstName ?? ""} ${
|
key = `${item?.createdBy?.firstName ?? ""} ${
|
||||||
item.createdBy?.lastName ?? ""
|
item.createdBy?.lastName ?? ""
|
||||||
}`.trim();
|
}`.trim();
|
||||||
break;
|
break;
|
||||||
case "project":
|
case "project":
|
||||||
key = item.project?.name || "Unknown Project";
|
key = item?.project?.name || "Unknown Project";
|
||||||
break;
|
break;
|
||||||
case "paymentMode":
|
case "paymentMode":
|
||||||
key = item.paymentMode?.name || "Unknown Mode";
|
key = item?.paymentMode?.name || "Unknown Mode";
|
||||||
break;
|
break;
|
||||||
case "expensesType":
|
case "expensesType":
|
||||||
key = item.expensesType?.name || "Unknown Type";
|
key = item?.expensesType?.name || "Unknown Type";
|
||||||
break;
|
break;
|
||||||
case "createdAt":
|
case "createdAt":
|
||||||
key = item.createdAt?.split("T")[0] || "Unknown Type";
|
key = item?.createdAt?.split("T")[0] || "Unknown Type";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
key = "Others";
|
key = "Others";
|
||||||
}
|
}
|
||||||
if (!acc[key]) acc[key] = [];
|
if (!acc[key]) acc[key] = [];
|
||||||
acc[key].push(item);
|
acc[key]?.push(item);
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
};
|
};
|
||||||
@ -163,23 +163,23 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
if (isInitialLoading) return <ExpenseTableSkeleton />;
|
if (isInitialLoading) return <ExpenseTableSkeleton />;
|
||||||
if (isError) return <div>{error.message}</div>;
|
if (isError) return <div>{error?.message}</div>;
|
||||||
|
|
||||||
const grouped = groupBy
|
const grouped = groupBy
|
||||||
? groupByField(data?.data ?? [], groupBy)
|
? groupByField(data?.data ?? [], groupBy)
|
||||||
: { All: data?.data ?? [] };
|
: { All: data?.data ?? [] };
|
||||||
const IsGroupedByDate = ["transactionDate", "createdAt"].includes(groupBy);
|
const IsGroupedByDate = ["transactionDate", "createdAt"]?.includes(groupBy);
|
||||||
const canEditExpense = (expense) => {
|
const canEditExpense = (expense) => {
|
||||||
return (
|
return (
|
||||||
(expense.status.id === EXPENSE_DRAFT ||
|
(expense?.status?.id === EXPENSE_DRAFT ||
|
||||||
EXPENSE_REJECTEDBY.includes(expense.status.id)) &&
|
EXPENSE_REJECTEDBY.includes(expense?.status?.id)) &&
|
||||||
expense.createdBy?.id === SelfId
|
expense?.createdBy?.id === SelfId
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const canDetetExpense = (expense) => {
|
const canDetetExpense = (expense) => {
|
||||||
return (
|
return (
|
||||||
expense.status.id === EXPENSE_DRAFT && expense.createdBy.id === SelfId
|
expense?.status?.id === EXPENSE_DRAFT && expense?.createdBy?.id === SelfId
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -198,7 +198,7 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="card px-0 px-sm-4">
|
<div className="card page-min-h px-sm-4">
|
||||||
<div
|
<div
|
||||||
className="card-datatable table-responsive "
|
className="card-datatable table-responsive "
|
||||||
id="horizontal-example"
|
id="horizontal-example"
|
||||||
@ -292,8 +292,10 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
|
|||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={8} className="text-center py-4">
|
<td colSpan={8} className="text-center border-0 ">
|
||||||
No Expense Found
|
<div className="py-8">
|
||||||
|
<p>No Expense Found</p>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -296,13 +296,13 @@ const Header = () => {
|
|||||||
<li>
|
<li>
|
||||||
<div className="dropdown-divider"></div>
|
<div className="dropdown-divider"></div>
|
||||||
</li>
|
</li>
|
||||||
<li onClick={() => onOpen()}>
|
{/* <li onClick={() => onOpen()}>
|
||||||
{" "}
|
{" "}
|
||||||
<a className="dropdown-item cusor-pointer">
|
<a className="dropdown-item cusor-pointer">
|
||||||
<i className="bx bx-transfer-alt me-2"></i>
|
<i className="bx bx-transfer-alt me-2"></i>
|
||||||
<span className="align-middle">Switch Workspace</span>
|
<span className="align-middle">Switch Workspace</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li> */}
|
||||||
<li onClick={handleProfilePage}>
|
<li onClick={handleProfilePage}>
|
||||||
<a
|
<a
|
||||||
aria-label="go to profile"
|
aria-label="go to profile"
|
||||||
|
|||||||
@ -37,7 +37,6 @@ const ServiceGroups = ({ service }) => {
|
|||||||
|
|
||||||
<div className="w-100 my-2">
|
<div className="w-100 my-2">
|
||||||
|
|
||||||
<p className="fs-5 fw-semibold">Manage Service</p>
|
|
||||||
<div className="accordion" id="accordionExample">
|
<div className="accordion" id="accordionExample">
|
||||||
<div className="accordion-item active shadow-none">
|
<div className="accordion-item active shadow-none">
|
||||||
{/* Service Header */}
|
{/* Service Header */}
|
||||||
|
|||||||
@ -12,38 +12,9 @@ import { setDefaultDateRange } from "../slices/localVariablesSlice";
|
|||||||
// ----------------------------Query-----------------------------
|
// ----------------------------Query-----------------------------
|
||||||
|
|
||||||
|
|
||||||
// export const useAttendance = (projectId) => {
|
|
||||||
// const dispatch = useDispatch()
|
|
||||||
// const {
|
|
||||||
// data: attendance = [],
|
|
||||||
// isLoading: loading,
|
|
||||||
// error,
|
|
||||||
// refetch: recall,
|
|
||||||
// isFetching
|
|
||||||
// } = useQuery({
|
|
||||||
// queryKey: ["attendance", projectId],
|
|
||||||
// queryFn: async () => {
|
|
||||||
// const response = await AttendanceRepository.getAttendance(projectId);
|
|
||||||
// return response.data;
|
|
||||||
// },
|
|
||||||
// enabled: !!projectId,
|
|
||||||
// onError: (error) => {
|
|
||||||
// showToast(error.message || "Error while fetching Attendance", "error");
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
|
|
||||||
// return {
|
|
||||||
// attendance,
|
|
||||||
// loading,
|
|
||||||
// error,
|
|
||||||
// recall,
|
|
||||||
// isFetching
|
|
||||||
// };
|
|
||||||
// };
|
|
||||||
|
|
||||||
export const useAttendance = (projectId, organizationId, includeInactive = false, date = null) => {
|
export const useAttendance = (projectId, organizationId, includeInactive = false, date = null) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
// queryKey: ["attendance", projectId, organizationId, includeInactive, date],
|
||||||
const {
|
const {
|
||||||
data: attendance = [],
|
data: attendance = [],
|
||||||
isLoading: loading,
|
isLoading: loading,
|
||||||
@ -51,7 +22,7 @@ export const useAttendance = (projectId, organizationId, includeInactive = false
|
|||||||
refetch: recall,
|
refetch: recall,
|
||||||
isFetching,
|
isFetching,
|
||||||
} = useQuery({
|
} = useQuery({
|
||||||
queryKey: ["attendance", projectId, organizationId, includeInactive, date], // include filters in cache key
|
queryKey: ["attendance", projectId ],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const response = await AttendanceRepository.getAttendance(
|
const response = await AttendanceRepository.getAttendance(
|
||||||
projectId,
|
projectId,
|
||||||
@ -61,7 +32,7 @@ export const useAttendance = (projectId, organizationId, includeInactive = false
|
|||||||
);
|
);
|
||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
enabled: !!projectId, // only run if projectId exists
|
enabled: !!projectId,
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
showToast(error.message || "Error while fetching Attendance", "error");
|
showToast(error.message || "Error while fetching Attendance", "error");
|
||||||
},
|
},
|
||||||
@ -142,31 +113,6 @@ export const useAttendanceByEmployee = (employeeId, fromDate, toDate) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// export const useRegularizationRequests = (projectId) => {
|
|
||||||
// const {
|
|
||||||
// data: regularizes = [],
|
|
||||||
// isLoading: loading,
|
|
||||||
// error,
|
|
||||||
// refetch,
|
|
||||||
// } = useQuery({
|
|
||||||
// queryKey: ["regularizedList", projectId],
|
|
||||||
// queryFn: async () => {
|
|
||||||
// const response = await AttendanceRepository.getRegularizeList(projectId);
|
|
||||||
// return response.data;
|
|
||||||
// },
|
|
||||||
// enabled: !!projectId,
|
|
||||||
// onError: (error) => {
|
|
||||||
// showToast(error.message || "Error while fetching Regularization Requests", "error");
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
|
|
||||||
// return {
|
|
||||||
// regularizes,
|
|
||||||
// loading,
|
|
||||||
// error,
|
|
||||||
// refetch,
|
|
||||||
// };
|
|
||||||
// };
|
|
||||||
|
|
||||||
export const useRegularizationRequests = (projectId, organizationId, IncludeInActive = false) => {
|
export const useRegularizationRequests = (projectId, organizationId, IncludeInActive = false) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@ -218,10 +164,11 @@ export const useMarkAttendance = () => {
|
|||||||
emp.employeeId === data.employeeId ? { ...emp, ...data } : emp
|
emp.employeeId === data.employeeId ? { ...emp, ...data } : emp
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
// queryClient.invalidateQueries({queryKey:["attendance"]})
|
||||||
}else if(variables.forWhichTab == 2){
|
}else if(variables.forWhichTab == 2){
|
||||||
// queryClient.invalidateQueries({
|
queryClient.invalidateQueries({
|
||||||
// queryKey: ["attendanceLogs"],
|
queryKey: ["attendanceLogs"],
|
||||||
// });
|
});
|
||||||
queryClient.setQueryData(["attendanceLogs",selectedProject,selectedDateRange.startDate,selectedDateRange.endDate], (oldData) => {
|
queryClient.setQueryData(["attendanceLogs",selectedProject,selectedDateRange.startDate,selectedDateRange.endDate], (oldData) => {
|
||||||
if (!oldData) return oldData;
|
if (!oldData) return oldData;
|
||||||
return oldData.map((record) =>
|
return oldData.map((record) =>
|
||||||
|
|||||||
@ -174,7 +174,7 @@ const AttendancePage = () => {
|
|||||||
{/* Search + Organization filter */}
|
{/* Search + Organization filter */}
|
||||||
<div className="col-12 col-md-auto mt-2 mt-md-0 ms-md-auto d-flex gap-2 align-items-center">
|
<div className="col-12 col-md-auto mt-2 mt-md-0 ms-md-auto d-flex gap-2 align-items-center">
|
||||||
{/* Organization Dropdown */}
|
{/* Organization Dropdown */}
|
||||||
<select
|
{/* <select
|
||||||
className="form-select form-select-sm"
|
className="form-select form-select-sm"
|
||||||
style={{ minWidth: "180px" }}
|
style={{ minWidth: "180px" }}
|
||||||
value={appliedFilters.selectedOrganization}
|
value={appliedFilters.selectedOrganization}
|
||||||
@ -192,7 +192,7 @@ const AttendancePage = () => {
|
|||||||
{org.name}
|
{org.name}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select> */}
|
||||||
|
|
||||||
{/* Search Input */}
|
{/* Search Input */}
|
||||||
<input
|
<input
|
||||||
|
|||||||
@ -289,7 +289,7 @@ const EmployeeList = () => {
|
|||||||
|
|
||||||
{ViewTeamMember ? (
|
{ViewTeamMember ? (
|
||||||
// <div className="row">
|
// <div className="row">
|
||||||
<div className="card p-1">
|
<div className="card page-min-h p-1">
|
||||||
<div className="card-datatable table-responsive pt-5 mx-5 py-10">
|
<div className="card-datatable table-responsive pt-5 mx-5 py-10">
|
||||||
<div
|
<div
|
||||||
id="DataTables_Table_0_wrapper"
|
id="DataTables_Table_0_wrapper"
|
||||||
@ -537,9 +537,11 @@ const EmployeeList = () => {
|
|||||||
<tr>
|
<tr>
|
||||||
<td
|
<td
|
||||||
colSpan={8}
|
colSpan={8}
|
||||||
style={{ paddingTop: "20px", textAlign: "center" }}
|
className="border-0"
|
||||||
>
|
>
|
||||||
No Data Found
|
<div className="py-1">
|
||||||
|
No Employeee Found
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
@ -181,7 +181,7 @@ const ProjectPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{HasManageProject && ( <button
|
{/* {HasManageProject && ( <button
|
||||||
className="btn btn-sm btn-primary"
|
className="btn btn-sm btn-primary"
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@ -192,7 +192,7 @@ const ProjectPage = () => {
|
|||||||
<span className="d-none d-md-inline-block">
|
<span className="d-none d-md-inline-block">
|
||||||
Add New Project
|
Add New Project
|
||||||
</span>
|
</span>
|
||||||
</button>)}
|
</button>)} */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user