diff --git a/src/components/Dashboard/CollectionOverview.jsx b/src/components/Dashboard/CollectionOverview.jsx
new file mode 100644
index 00000000..448072b4
--- /dev/null
+++ b/src/components/Dashboard/CollectionOverview.jsx
@@ -0,0 +1,345 @@
+import React from "react";
+import Chart from "react-apexcharts";
+import { useGetCollectionOverview } from "../../hooks/useDashboard_Data";
+import { formatFigure } from "../../utils/appUtils";
+
+const CollectionOverview = ({ data }) => {
+ const borderColor = "#ddd";
+ const labelColor = "#6c757d";
+
+ // Extract bucket values
+ const labels = ["0–30 Days", "30–60 Days", "60–90 Days", "90+ Days"];
+
+ const amounts = [
+ data.bucket0To30Amount,
+ data.bucket30To60Amount,
+ data.bucket60To90Amount,
+ data.bucket90PlusAmount,
+ ];
+
+ // Colors (Zoho-style distributed)
+ const colors = ["#7367F0", "#00cfe8", "#28c76f", "#ea5455"];
+
+ const options = {
+ chart: {
+ type: "bar",
+ height: 260,
+ toolbar: { show: false },
+ },
+
+ plotOptions: {
+ bar: {
+ horizontal: true,
+ barHeight: "65%",
+ distributed: true,
+ borderRadius: 8,
+ startingShape: "rounded",
+ },
+ },
+
+ colors: colors,
+
+ grid: {
+ borderColor: borderColor,
+ strokeDashArray: 6,
+ padding: { top: -10, bottom: -10 },
+ xaxis: { lines: { show: true } },
+ },
+
+ dataLabels: {
+ enabled: true,
+ formatter: (_, opts) => labels[opts.dataPointIndex],
+ style: {
+ colors: ["#fff"],
+ fontSize: "13px",
+ fontWeight: 500,
+ },
+ offsetX: 0,
+ },
+
+ xaxis: {
+ categories: amounts.map((a) => a),
+ labels: {
+ style: { colors: labelColor, fontSize: "12px" },
+ formatter: (val) => `₹${val.toLocaleString()}`,
+ },
+ },
+
+ yaxis: {
+ labels: {
+ style: {
+ colors: labelColor,
+ fontSize: "13px",
+ },
+ formatter: () => "", // hide duplicate labels
+ },
+ },
+
+ tooltip: {
+ custom: ({ series, seriesIndex, dataPointIndex }) => {
+ return `
+
+ ${labels[dataPointIndex]}
+ ₹${series[seriesIndex][dataPointIndex].toLocaleString()}
+
+ `;
+ },
+ },
+
+ legend: { show: false },
+ };
+
+ const series = [
+ {
+ name: "Amount",
+ data: amounts,
+ },
+ ];
+
+ return (
+
+
+
+ );
+};
+
+export default CollectionOverview;
+export const TopicBarChart = ({ data }) => {
+ const data1 = {
+ totalDueAmount: 213590,
+ totalCollectedAmount: 5000,
+ totalValue: 218590,
+ pendingPercentage: 97.71,
+ collectedPercentage: 2.29,
+
+ bucket0To30Invoices: 10,
+ bucket30To60Invoices: 4,
+ bucket60To90Invoices: 2,
+ bucket90PlusInvoices: 1,
+
+ bucket0To30Amount: 2130,
+ bucket30To60Amount: 2003,
+ bucket60To90Amount: 4500,
+ bucket90PlusAmount: 8800,
+
+ topClientBalance: 55300,
+ topClient: {
+ id: "4e3a6d31-c640-40f7-8d67-6c109fcdb9ea",
+ name: "Marco Secure Solutions Ltd.",
+ email: "admin@marcoaiot.com",
+ contactPerson: "Admin",
+ address:
+ "2nd Floor, Fullora Building, Tejas CHS, behind Kothrud Stand, Tejas Society, Dahanukar Colony, Kothrud, Pune, Maharashtra 411038",
+ gstNumber: null,
+ contactNumber: "123456789",
+ sprid: 5400,
+ },
+ };
+
+ const borderColor = "#ddd";
+ const labelColor = "#6c757d";
+
+ // COLORS
+ const config = {
+ colors: {
+ b0: "#7367F0",
+ b30: "#00cfe8",
+ b60: "#28c76f",
+ b90: "#ea5455",
+ },
+ };
+
+ // NEW LABELS (BUCKETS)
+ const chartLabels = ["0–30 Days", "30–60 Days", "60–90 Days", "90+ Days"];
+
+ // NEW VALUES (BUCKET AMOUNT)
+ const chartValues = [
+ data.bucket0To30Amount,
+ data.bucket30To60Amount,
+ data.bucket60To90Amount,
+ data.bucket90PlusAmount,
+ ];
+
+ const options = {
+ chart: {
+ height: 300,
+ type: "bar",
+ toolbar: { show: false },
+ },
+
+ plotOptions: {
+ bar: {
+ horizontal: true,
+ barHeight: "40%",
+ distributed: true,
+ startingShape: "rounded",
+ borderRadius: 7,
+ },
+ },
+
+ grid: {
+ strokeDashArray: 10,
+ borderColor,
+ xaxis: { lines: { show: true } },
+ yaxis: { lines: { show: false } },
+ padding: { top: -35, bottom: -12 },
+ },
+
+ colors: [
+ config.colors.b0,
+ config.colors.b30,
+ config.colors.b60,
+ config.colors.b90,
+ ],
+
+ labels: chartLabels,
+
+ fill: { opacity: 1 },
+
+ dataLabels: {
+ enabled: true,
+ style: {
+ colors: ["#fff"],
+ fontWeight: 400,
+ fontSize: "13px",
+ fontFamily: "Public Sans",
+ },
+ formatter: (_, opts) => chartLabels[opts.dataPointIndex],
+ },
+
+ xaxis: {
+ categories: chartValues.map((x) => formatFigure(x, { type: "currency" })),
+ axisBorder: { show: false },
+ axisTicks: { show: false },
+ labels: {
+ style: {
+ colors: labelColor,
+ fontFamily: "Public Sans",
+ fontSize: "13px",
+ },
+ formatter: (val) => `₹${Number(val).toLocaleString()}`,
+ },
+ },
+
+ yaxis: {
+ labels: {
+ style: {
+ colors: labelColor,
+ fontFamily: "Public Sans",
+ fontSize: "13px",
+ },
+ },
+ },
+
+ tooltip: {
+ enabled: true,
+ custom: ({ series, seriesIndex, dataPointIndex }) => {
+ return `
+
+ ₹${series[seriesIndex][
+ dataPointIndex
+ ].toLocaleString()}
+
+ `;
+ },
+ },
+
+ legend: { show: false },
+ };
+
+ const series = [
+ {
+ data: chartValues,
+ },
+ ];
+
+ return (
+
+
+
+
+
Due Amount
+
+ {formatFigure(data.totalDueAmount, { type: "currency" })}
+
+
Collected Amount
+
+ {formatFigure(data.totalCollectedAmount, { type: "currency" })}
+
+
+
+
+
+
+
+
+
+ {/*
Top Client
+
{data.topClient.name} */}
+
+
+ {/* 0–30 Days */}
+
+
+ {formatFigure(data.bucket0To30Amount, { type: "currency" })}
+
+
0–30 Days
+
+
+ {/* 30–60 Days */}
+
+
+ {formatFigure(data.bucket30To60Amount, { type: "currency" })}
+
+
30–60 Days
+
+
+ {/* 60–90 Days */}
+
+
+ {formatFigure(data.bucket60To90Amount, { type: "currency" })}
+
+
60–90 Days
+
+
+ {/* 90+ Days */}
+
+
+ {formatFigure(data.bucket90PlusAmount, { type: "currency" })}
+
+
90+ Days
+
+
+
+ );
+};
diff --git a/src/components/Dashboard/Dashboard.jsx b/src/components/Dashboard/Dashboard.jsx
index e918629d..a400d7a8 100644
--- a/src/components/Dashboard/Dashboard.jsx
+++ b/src/components/Dashboard/Dashboard.jsx
@@ -1,10 +1,11 @@
import React from "react";
import { useSelector } from "react-redux";
import {
- useDashboardProjectsCardData,
- useDashboardTeamsCardData,
- useDashboardTasksCardData,
- useAttendanceOverviewData
+ useDashboardProjectsCardData,
+ useDashboardTeamsCardData,
+ useDashboardTasksCardData,
+ useAttendanceOverviewData,
+ useGetCollectionOverview,
} from "../../hooks/useDashboard_Data";
import Projects from "./Projects";
@@ -19,77 +20,171 @@ import ExpenseByProject from "./ExpenseByProject";
import ProjectStatistics from "../Project/ProjectStatistics";
import ServiceJobs from "./ServiceJobs";
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
-import { REGULARIZE_ATTENDANCE, SELF_ATTENDANCE, TEAM_ATTENDANCE } from "../../utils/constants";
+import {
+ REGULARIZE_ATTENDANCE,
+ SELF_ATTENDANCE,
+ TEAM_ATTENDANCE,
+} from "../../utils/constants";
+import CollectionOverview, { TopicBarChart } from "./CollectionOverview";
const Dashboard = () => {
+ // Get the selected project ID from Redux store
+ const projectId = useSelector((store) => store.localVariables.projectId);
+ const isAllProjectsSelected = projectId === null;
+ const canRegularize = useHasUserPermission(REGULARIZE_ATTENDANCE);
+ const canTeamAttendance = useHasUserPermission(TEAM_ATTENDANCE);
+ const canSelfAttendance = useHasUserPermission(SELF_ATTENDANCE);
- // Get the selected project ID from Redux store
- const projectId = useSelector((store) => store.localVariables.projectId);
- const isAllProjectsSelected = projectId === null;
- const canRegularize = useHasUserPermission(REGULARIZE_ATTENDANCE);
- const canTeamAttendance = useHasUserPermission(TEAM_ATTENDANCE);
- const canSelfAttendance = useHasUserPermission(SELF_ATTENDANCE);
+ const { data } = useGetCollectionOverview();
+ console.log("data-->", data);
+ return (
+
+
+ {isAllProjectsSelected && (
+
+ )}
-
- return (
-
-
- {isAllProjectsSelected && (
-
- )}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {isAllProjectsSelected && (
-
- )}
-
- {!isAllProjectsSelected && (canRegularize || canTeamAttendance || canSelfAttendance) && (
-
- )}
-
- {!isAllProjectsSelected && (
-
- )}
-
- {/*
-
-
*/}
-
+
+
- );
+
+
+
+
+
+
+
+
+
+
+
+ {isAllProjectsSelected && (
+
+ )}
+
+ {!isAllProjectsSelected &&
+ (canRegularize || canTeamAttendance || canSelfAttendance) && (
+
+ )}
+
+ {!isAllProjectsSelected && (
+
+ )}
+
+
+
+
+
+
+ );
};
-export default Dashboard;
\ No newline at end of file
+export default Dashboard;
+
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
UI Design
+//
35%
+//
+//
+//
+//
+//
+
+//
+//
+//
+//
+//
UX Design
+//
20%
+//
+//
+//
+//
+//
+//
Animation
+//
12%
+//
+//
+//
+//
+//
+//
+//
+//
diff --git a/src/hooks/useDashboard_Data.jsx b/src/hooks/useDashboard_Data.jsx
index 1a9d724a..8b3863df 100644
--- a/src/hooks/useDashboard_Data.jsx
+++ b/src/hooks/useDashboard_Data.jsx
@@ -192,3 +192,13 @@ export const useExpenseDataByProject = (projectId, categoryId, months) => {
},
});
};
+
+export const useGetCollectionOverview = (projectId) => {
+ return useQuery({
+ queryKey: ["collection_overview", projectId],
+ queryFn: async () => {
+ const resp = await GlobalRepository.getCollectionOverview(projectId);
+ return resp.data;
+ },
+ });
+};
diff --git a/src/repositories/GlobalRepository.jsx b/src/repositories/GlobalRepository.jsx
index 2516020a..e95a109a 100644
--- a/src/repositories/GlobalRepository.jsx
+++ b/src/repositories/GlobalRepository.jsx
@@ -82,9 +82,9 @@ const GlobalRepository = {
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}`),
+ getCollectionOverview:(projectId) =>api.get(`/api/Dashboard/collection-overview`)
};