fixed dashboard graph
This commit is contained in:
parent
49b597c833
commit
2531d91209
@ -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>
|
||||
))}
|
||||
@ -201,4 +152,4 @@ const AttendanceOverview = ({projectId}) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default AttendanceOverview;
|
||||
export default AttendanceOverview;
|
@ -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>
|
||||
|
@ -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({
|
||||
|
Loading…
x
Reference in New Issue
Block a user