+
navigate(`/employee/${e.createdBy?.id}`)}>
+
{
lastName={e.createdBy?.lastName}
/>
- {`${e.createdBy?.firstName ?? ""} ${
- e.createdBy?.lastName ?? ""
- }`.trim() || "N/A"}
+ {`${e.createdBy?.firstName ?? ""} ${e.createdBy?.lastName ?? ""
+ }`.trim() || "N/A"}
),
@@ -152,9 +153,8 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => {
align: "text-center",
getValue: (e) => (
{e.status?.name || "Unknown"}
diff --git a/src/hooks/useDashboard_Data.jsx b/src/hooks/useDashboard_Data.jsx
index b9c393b7..5f8f4319 100644
--- a/src/hooks/useDashboard_Data.jsx
+++ b/src/hooks/useDashboard_Data.jsx
@@ -200,35 +200,35 @@ export const useAttendanceOverviewData = (projectId, days) => {
// })
// }
-export const useDashboard_AttendanceData = (date,projectId)=>{
- return useQuery({
- queryKey:["dashboardAttendances",date,projectId],
- queryFn:async()=> {
-
- const resp = await await GlobalRepository.getDashboardAttendanceData(date, projectId)
- return resp.data;
+export const useDashboard_AttendanceData = (date, projectId) => {
+ return useQuery({
+ queryKey: ["dashboardAttendances", date, projectId],
+ queryFn: async () => {
+
+ const resp = await await GlobalRepository.getDashboardAttendanceData(date, projectId)
+ return resp.data;
}
})
}
-export const useDashboardTeamsCardData =(projectId)=>{
- return useQuery({
- queryKey:["dashboardTeams",projectId],
- queryFn:async()=> {
-
- const resp = await GlobalRepository.getDashboardTeamsCardData(projectId)
- return resp.data;
+export const useDashboardTeamsCardData = (projectId) => {
+ return useQuery({
+ queryKey: ["dashboardTeams", projectId],
+ queryFn: async () => {
+
+ const resp = await GlobalRepository.getDashboardTeamsCardData(projectId)
+ return resp.data;
}
})
}
export const useDashboardTasksCardData = (projectId) => {
- return useQuery({
- queryKey:["dashboardTasks",projectId],
- queryFn:async()=> {
-
- const resp = await GlobalRepository.getDashboardTasksCardData(projectId)
- return resp.data;
+ return useQuery({
+ queryKey: ["dashboardTasks", projectId],
+ queryFn: async () => {
+
+ const resp = await GlobalRepository.getDashboardTasksCardData(projectId)
+ return resp.data;
}
})
}
@@ -236,7 +236,7 @@ export const useDashboardTasksCardData = (projectId) => {
// return useQuery({
// queryKey:["dashboardAttendanceOverView",projectId],
// queryFn:async()=> {
-
+
// const resp = await GlobalRepository.getAttendanceOverview(projectId, days);
// return resp.data;
// }
@@ -244,12 +244,53 @@ export const useDashboardTasksCardData = (projectId) => {
// }
export const useDashboardProjectsCardData = () => {
- return useQuery({
- queryKey:["dashboardProjects"],
- queryFn:async()=> {
-
- const resp = await GlobalRepository.getDashboardProjectsCardData();
- return resp.data;
+ return useQuery({
+ queryKey: ["dashboardProjects"],
+ queryFn: async () => {
+
+ const resp = await GlobalRepository.getDashboardProjectsCardData();
+ return resp.data;
}
})
-}
\ No newline at end of file
+}
+
+export const useExpenseAnalysis = (projectId, startDate, endDate) => {
+ const hasBothDates = !!startDate && !!endDate;
+ const noDatesSelected = !startDate && !endDate;
+
+ const shouldFetch =
+ noDatesSelected ||
+ hasBothDates;
+ return useQuery({
+ queryKey: ["expenseAnalysis", projectId, startDate, endDate],
+ queryFn: async () => {
+ const resp = await GlobalRepository.getExpenseData(projectId, startDate, endDate);
+ return resp.data;
+ },
+ enabled: shouldFetch,
+ refetchOnWindowFocus: true, // refetch when you come back
+ refetchOnMount: "always", // always refetch on remount
+ staleTime: 0,
+ });
+};
+
+export const useExpenseStatus = (projectId) => {
+ return useQuery({
+ queryKey: ["expense_stauts", projectId],
+ queryFn: async () => {
+ const resp = await GlobalRepository.getExpenseStatus(projectId);
+ return resp.data;
+ }
+ })
+}
+
+export const useExpenseDataByProject = (projectId, categoryId, months) => {
+ return useQuery({
+ queryKey: ["expenseByProject", projectId, categoryId, months],
+ queryFn: async () => {
+ const resp = await GlobalRepository.getExpenseDataByProject(projectId, categoryId, months);
+ return resp.data;
+ },
+
+ });
+};
\ No newline at end of file
diff --git a/src/repositories/GlobalRepository.jsx b/src/repositories/GlobalRepository.jsx
index d3367fa6..ec90d25d 100644
--- a/src/repositories/GlobalRepository.jsx
+++ b/src/repositories/GlobalRepository.jsx
@@ -3,12 +3,12 @@ import { api } from "../utils/axiosClient";
const GlobalRepository = {
getDashboardProgressionData: ({ days = '', FromDate = '', projectId = '' }) => {
let params;
- if(projectId == null){
+ if (projectId == null) {
params = new URLSearchParams({
days: days.toString(),
FromDate,
});
- }else{
+ } else {
params = new URLSearchParams({
days: days.toString(),
FromDate,
@@ -19,30 +19,72 @@ const GlobalRepository = {
return api.get(`/api/Dashboard/Progression?${params.toString()}`);
},
- getDashboardAttendanceData: ( date,projectId ) => {
+ getDashboardAttendanceData: (date, projectId) => {
- return api.get(`/api/Dashboard/project-attendance/${projectId}?date=${date}`);
-},
+ return api.get(`/api/Dashboard/project-attendance/${projectId}?date=${date}`);
+ },
getDashboardProjectsCardData: () => {
return api.get(`/api/Dashboard/projects`);
},
-
+
getDashboardTeamsCardData: (projectId) => {
- const url = projectId
- ? `/api/Dashboard/teams?projectId=${projectId}`
- : `/api/Dashboard/teams`;
- return api.get(url);
-},
+ const url = projectId
+ ? `/api/Dashboard/teams?projectId=${projectId}`
+ : `/api/Dashboard/teams`;
+ return api.get(url);
+ },
getDashboardTasksCardData: (projectId) => {
- const url = projectId
- ? `/api/Dashboard/tasks?projectId=${projectId}`
- : `/api/Dashboard/tasks`;
- return api.get(url);
-},
+ const url = projectId
+ ? `/api/Dashboard/tasks?projectId=${projectId}`
+ : `/api/Dashboard/tasks`;
+ return api.get(url);
+ },
+
+ getExpenseData: (projectId, startDate, endDate) => {
+ let url = `api/Dashboard/expense/type`
+ const queryParams = [];
+ if (projectId) {
+ queryParams.push(`projectId=${projectId}`);
+ }
+ if (startDate) {
+ queryParams.push(`startDate=${startDate}`);
+ }
+ if (endDate) {
+ queryParams.push(`endDate=${endDate}`);
+ }
+
+ if (queryParams.length > 0) {
+ url += `?${queryParams.join("&")}`;
+ }
+ return api.get(url);
+ },
+
+ getExpenseStatus: (projectId) => api.get(`/api/Dashboard/expense/pendings${projectId ? `?projectId=${projectId}` : ""}`),
+
+ getExpenseDataByProject: (projectId, categoryId, months) => {
+ let url = `api/Dashboard/expense/monthly`
+ const queryParams = [];
+ if (projectId) {
+ queryParams.push(`projectId=${projectId}`);
+ }
+ if (categoryId) {
+ queryParams.push(`categoryId=${categoryId}`);
+ }
+ if (months) {
+ queryParams.push(`months=${months}`);
+ }
+ if (queryParams.length > 0) {
+ url += `?${queryParams.join("&")}`;
+ }
+ return api.get(url);
+ },
+
+ getAttendanceOverview: (projectId, days) => api.get(`/api/dashboard/attendance-overview/${projectId}?days=${days}`)
+
- getAttendanceOverview:(projectId,days)=>api.get(`/api/dashboard/attendance-overview/${projectId}?days=${days}`)
};
+
export default GlobalRepository;
diff --git a/src/router/AppRoutes.jsx b/src/router/AppRoutes.jsx
index c0787e95..025b05b8 100644
--- a/src/router/AppRoutes.jsx
+++ b/src/router/AppRoutes.jsx
@@ -94,7 +94,7 @@ const router = createBrowserRouter(
{ path: "/activities/task", element:
},
{ path: "/activities/reports", element:
},
{ path: "/gallary", element:
},
- { path: "/expenses", element:
},
+ { path: "/expenses/:status?/:project?", element:
},
{ path: "/masters", element:
},
{ path: "/tenants", element:
},
{ path: "/tenants/new-tenant", element:
},
diff --git a/src/utils/appUtils.js b/src/utils/appUtils.js
index f9be1ebd..d2a45132 100644
--- a/src/utils/appUtils.js
+++ b/src/utils/appUtils.js
@@ -69,30 +69,6 @@ export const normalizeAllowedContentTypes = (allowedContentType) => {
return allowedContentType.split(",");
return [];
};
-export function localToUtc(dateString) {
-if (!dateString || typeof dateString !== "string") return null;
-
-const parts = dateString.trim().split("-");
-if (parts.length !== 3) return null;
-
-let day, month, year;
-
-if (parts[0].length === 4) {
-// Format: yyyy-mm-dd
-[year, month, day] = parts;
-} else {
-// Format: dd-mm-yyyy
-[day, month, year] = parts;
-}
-
-if (!day || !month || !year) return null;
-
-const date = new Date(
-Date.UTC(Number(year), Number(month) - 1, Number(day), 0, 0, 0)
-);
-return isNaN(date.getTime()) ? null : date.toISOString();
-}
-
/**
* Flexible number formatter for currency, numbers, or percentages.
@@ -135,3 +111,42 @@ export const formatFigure = (
return new Intl.NumberFormat(locale, formatterOptions).format(amount);
};
+
+export function localToUtc(dateString) {
+ if (!dateString || typeof dateString !== "string") return null;
+
+ const parts = dateString.trim().split("-");
+ if (parts.length !== 3) return null;
+
+ let day, month, year;
+
+ if (parts[0].length === 4) {
+ // Format: yyyy-mm-dd
+ [year, month, day] = parts;
+ } else {
+ // Format: dd-mm-yyyy
+ [day, month, year] = parts;
+ }
+
+ if (!day || !month || !year) return null;
+
+ const date = new Date(
+ Date.UTC(Number(year), Number(month) - 1, Number(day), 0, 0, 0)
+ );
+ return isNaN(date.getTime()) ? null : date.toISOString();
+}
+
+export const formatCurrency = (amount, currency = "INR", locale = "en-US") => {
+ return new Intl.NumberFormat(locale, {
+ style: "currency",
+ notation: "compact",
+ compactDisplay: "short",
+ currency: currency,
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 2,
+ }).format(amount);
+};
+
+export const countDigit = (num) => {
+ return Math.abs(num).toString().length;
+};
diff --git a/src/utils/constants.jsx b/src/utils/constants.jsx
index 8d190f15..77bfcdbd 100644
--- a/src/utils/constants.jsx
+++ b/src/utils/constants.jsx
@@ -145,5 +145,14 @@ export const PROJECT_STATUS = [
label: "Completed",
},
];
+
+export const EXPENSE_STATUS = {
+ daft:"297e0d8f-f668-41b5-bfea-e03b354251c8",
+ review_pending:"6537018f-f4e9-4cb3-a210-6c3b2da999d7",
+ payment_pending:"f18c5cfd-7815-4341-8da2-2c2d65778e27",
+ approve_pending:"4068007f-c92f-4f37-a907-bc15fe57d4d8",
+ process_pending:"61578360-3a49-4c34-8604-7b35a3787b95"
+
+}
export const DEFAULT_EMPTY_STATUS_ID = "00000000-0000-0000-0000-000000000000";
diff --git a/src/utils/dateUtils.jsx b/src/utils/dateUtils.jsx
index 388f7563..b5f59537 100644
--- a/src/utils/dateUtils.jsx
+++ b/src/utils/dateUtils.jsx
@@ -51,7 +51,7 @@ export const convertShortTime = (dateString) => {
};
export const timeElapsed = (checkInTime, timeElapsedInHours) => {
- const checkInDate = new Date( checkInTime.split( "T" )[ 0 ] );
+ const checkInDate = new Date(checkInTime.split("T")[0]);
const currentTime = new Date();
@@ -72,7 +72,7 @@ export const checkIfCurrentDate = (dateString) => {
return currentDate?.getTime() === inputDate?.getTime();
};
-export const formatNumber = (num) => {
+export const formatNumber = (num) => {
if (num == null || isNaN(num)) return "NA";
return Number.isInteger(num) ? num : num.toFixed(2);
};
@@ -84,15 +84,25 @@ export const formatUTCToLocalTime = (datetime, timeRequired = false) => {
: moment.utc(datetime).local().format("DD MMM YYYY");
};
-export const getCompletionPercentage = (completedWork, plannedWork)=> {
+export const getCompletionPercentage = (completedWork, plannedWork) => {
if (!plannedWork || plannedWork === 0) return 0;
const percentage = (completedWork / plannedWork) * 100;
const clamped = Math.min(Math.max(percentage, 0), 100);
- return clamped.toFixed(2);
+ return clamped.toFixed(2);
}
-export const getTenantStatus =(statusId)=>{
- return ActiveTenant === statusId ? " bg-label-success":"bg-label-secondary"
+export const formatDate_DayMonth = (monthName, year) => {
+ if (!monthName || !year) return "";
+ try {
+ const shortMonth = monthName.substring(0, 3);
+ return `${shortMonth} ${year}`;
+ } catch {
+ return "";
+ }
+};
+
+export const getTenantStatus = (statusId) => {
+ return ActiveTenant === statusId ? " bg-label-success" : "bg-label-secondary"
}
\ No newline at end of file