fixed dashboard graph

This commit is contained in:
pramod.mahajan 2025-10-01 16:21:08 +05:30
parent 49b597c833
commit 2531d91209
3 changed files with 67 additions and 125 deletions

View File

@ -4,6 +4,7 @@ import ReactApexChart from "react-apexcharts";
import { useAttendanceOverviewData } from "../../hooks/useDashboard_Data";
import flatColors from "../Charts/flatColor";
import ChartSkeleton from "../Charts/Skelton";
import { useSelectedProject } from "../../slices/apiDataManager";
const formatDate = (dateStr) => {
const date = new Date(dateStr);
@ -13,16 +14,20 @@ const formatDate = (dateStr) => {
});
};
const AttendanceOverview = ({projectId}) => {
const AttendanceOverview = () => {
const [dayRange, setDayRange] = useState(7);
const [view, setView] = useState("chart");
const { attendanceOverviewData, loading, error } = useAttendanceOverviewData(
projectId,
const selectedProject = useSelectedProject()
const { data: attendanceOverviewData, isLoading, isError, error } = useAttendanceOverviewData(
selectedProject,
dayRange
);
const { tableData, roles, dates } = useMemo(() => {
if (!attendanceOverviewData || attendanceOverviewData.length === 0) {
return { tableData: [], roles: [], dates: [] };
}
const map = new Map();
attendanceOverviewData.forEach((entry) => {
@ -35,7 +40,8 @@ const AttendanceOverview = ({projectId}) => {
...new Set(attendanceOverviewData.map((e) => e.role.trim())),
];
const sortedDates = [...map.keys()];
const data = sortedDates.map((date) => {
const tableData = sortedDates.map((date) => {
const row = { date };
uniqueRoles.forEach((role) => {
row[role] = map.get(date)?.[role] ?? 0;
@ -43,12 +49,8 @@ const AttendanceOverview = ({projectId}) => {
return row;
});
return {
tableData: data,
roles: uniqueRoles,
dates: sortedDates,
};
}, [attendanceOverviewData]);
return { tableData, roles: uniqueRoles, dates: sortedDates };
}, [attendanceOverviewData,isLoading,selectedProject,dayRange]);
const chartSeries = roles.map((role) => ({
name: role,
@ -62,41 +64,21 @@ const AttendanceOverview = ({projectId}) => {
height: 400,
toolbar: { show: false },
},
plotOptions: {
bar: {
borderRadius: 2,
columnWidth: "60%",
},
},
xaxis: {
categories: tableData.map((row) => row.date),
},
plotOptions: { bar: { borderRadius: 2, columnWidth: "60%" } },
xaxis: { categories: tableData.map((row) => row.date) },
yaxis: {
show: true,
axisBorder: {
show: true,
color: "#78909C",
offsetX: 0,
offsetY: 0,
},
axisTicks: {
show: true,
borderType: "solid",
color: "#78909C",
width: 6,
offsetX: 0,
offsetY: 0,
},
},
legend: {
position: "bottom",
},
fill: {
opacity: 1,
axisBorder: { show: true, color: "#78909C" },
axisTicks: { show: true, color: "#78909C", width: 6 },
},
legend: { position: "bottom" },
fill: { opacity: 1 },
colors: roles.map((_, i) => flatColors[i % flatColors.length]),
};
if (isLoading) return <div>Loading...</div>;
if (isError) return <p className="text-danger">{error.message}</p>;
return (
<div className="bg-white p-4 rounded shadow d-flex flex-column">
{/* Header */}
@ -116,18 +98,14 @@ const AttendanceOverview = ({projectId}) => {
<option value={30}>Last 30 Days</option>
</select>
<button
className={`btn btn-sm p-1 ${
view === "chart" ? "btn-primary" : "btn-outline-primary"
}`}
className={`btn btn-sm p-1 ${view === "chart" ? "btn-primary" : "btn-outline-primary"}`}
onClick={() => setView("chart")}
title="Chart View"
>
<i className="bx bx-bar-chart-alt-2"></i>
</button>
<button
className={`btn btn-sm p-1 ${
view === "table" ? "btn-primary" : "btn-outline-primary"
}`}
className={`btn btn-sm p-1 ${view === "table" ? "btn-primary" : "btn-outline-primary"}`}
onClick={() => setView("table")}
title="Table View"
>
@ -138,57 +116,30 @@ const AttendanceOverview = ({projectId}) => {
{/* Content */}
<div className="flex-grow-1 d-flex align-items-center justify-content-center">
{loading ? (
<ChartSkeleton />
) : error ? (
<p className="text-danger">{error}</p>
) : view === "chart" ? (
{view === "chart" ? (
<div className="w-100">
<ReactApexChart
options={chartOptions}
series={chartSeries}
type="bar"
height={400}
/>
<ReactApexChart options={chartOptions} series={chartSeries} type="bar" height={400} />
</div>
) : (
<div
className="table-responsive w-100"
style={{ maxHeight: "350px", overflowY: "auto" }}
>
<div className="table-responsive w-100" style={{ maxHeight: "350px", overflowY: "auto" }}>
<table className="table table-bordered table-sm text-start align-middle mb-0">
<thead
className="table-light"
style={{ position: "sticky", top: 0, zIndex: 1 }}
>
<thead className="table-light" style={{ position: "sticky", top: 0, zIndex: 1 }}>
<tr>
<th style={{ background: "#f8f9fa", textTransform: "none" }}>
Role
</th>
<th style={{ background: "#f8f9fa", textTransform: "none" }}>Role</th>
{dates.map((date, idx) => (
<th
key={idx}
style={{ background: "#f8f9fa", textTransform: "none" }}
>
<th key={idx} style={{ background: "#f8f9fa", textTransform: "none" }}>
{date}
</th>
))}
</tr>
</thead>
<tbody>
{roles.map((role) => (
<tr key={role}>
<td>{role}</td>
{tableData.map((row, idx) => {
const value = row[role];
const cellStyle =
value > 0 ? { backgroundColor: "#d5d5d5" } : {};
return (
<td key={idx} style={cellStyle}>
{value}
</td>
);
return <td key={idx} style={value > 0 ? { backgroundColor: "#d5d5d5" } : {}}>{value}</td>;
})}
</tr>
))}

View File

@ -18,30 +18,20 @@ import { useSelectedProject } from "../../slices/apiDataManager";
import { useProjectName } from "../../hooks/useProjects";
const Dashboard = () => {
const { projectNames, loading: projectLoading } = useProjectName();
const selectedProject = useSelectedProject();
const dispatch = useDispatch();
// const { projectsCardData } = useDashboardProjectsCardData();
// const { teamsCardData } = useDashboardTeamsCardData();
// const { tasksCardData } = useDashboardTasksCardData();
// Get the selected project ID from Redux store
useEffect(() => {
if (!projectLoading && projectNames.length === 1 && !selectedProject) {
dispatch(setProjectId(projectNames[0].id));
}
}, [projectNames, projectLoading, selectedProject, dispatch]);
console.log(projectNames)
// Show attendance if project selected or single project exists
const shouldShowAttendance =
!projectLoading && (selectedProject || projectNames.length === 1);
return (
<div className="container-fluid mt-5">
<div className="row gy-4">
{/* {shouldShowAttendance && ( */}
<div className="col-xxl-6 col-lg-6">
<AttendanceOverview projectId={selectedProject} />
<AttendanceOverview />
</div>
</div>
</div>

View File

@ -155,32 +155,32 @@ export const useDashboard_Data = ({ days, FromDate, projectId }) => {
// };
export const useAttendanceOverviewData = (projectId, days) => {
const [attendanceOverviewData, setAttendanceOverviewData] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
// export const useAttendanceOverviewData = (projectId, days) => {
// const [attendanceOverviewData, setAttendanceOverviewData] = useState([]);
// const [loading, setLoading] = useState(false);
// const [error, setError] = useState("");
useEffect(() => {
if (!projectId || !days) return;
const fetchAttendanceOverview = async () => {
setLoading(true);
setError("");
// useEffect(() => {
// if (!projectId || !days) return;
// const fetchAttendanceOverview = async () => {
// setLoading(true);
// setError("");
try {
const response = await GlobalRepository.getAttendanceOverview(projectId, days);
setAttendanceOverviewData(response.data);
} catch (err) {
setError("Failed to fetch attendance overview data.");
} finally {
setLoading(false);
}
};
// try {
// const response = await GlobalRepository.getAttendanceOverview(projectId, days);
// setAttendanceOverviewData(response.data);
// } catch (err) {
// setError("Failed to fetch attendance overview data.");
// } finally {
// setLoading(false);
// }
// };
fetchAttendanceOverview();
}, [projectId, days]);
// fetchAttendanceOverview();
// }, [projectId, days]);
return { attendanceOverviewData, loading, error };
};
// return { attendanceOverviewData, loading, error };
// };
// -------------------Query----------------------------
@ -232,16 +232,17 @@ export const useDashboardTasksCardData = (projectId) => {
}
})
}
// export const useAttendanceOverviewData = (projectId, days) => {
// return useQuery({
// queryKey:["dashboardAttendanceOverView",projectId],
// queryFn:async()=> {
export const useAttendanceOverviewData = (projectId, days) => {
return useQuery({
queryKey:["dashboardAttendanceOverView",projectId,days],
queryFn:async()=> {
// const resp = await GlobalRepository.getAttendanceOverview(projectId, days);
// return resp.data;
// }
// })
// }
const resp = await GlobalRepository.getAttendanceOverview(projectId, days);
return resp.data;
},
enabled:!!projectId
})
}
export const useDashboardProjectsCardData = () => {
return useQuery({