127 lines
4.0 KiB
JavaScript
127 lines
4.0 KiB
JavaScript
import React, { useState } from "react";
|
||
import LineChart from "../Charts/LineChart";
|
||
import { useProjects } from "../../hooks/useProjects";
|
||
import { useDashboard_Data } from "../../hooks/useDashboard_Data";
|
||
|
||
const ProjectProgressChart = () => {
|
||
const { projects } = useProjects();
|
||
const [selectedProjectId, setSelectedProjectId] = useState("all");
|
||
const [range, setRange] = useState("1W");
|
||
|
||
const getDaysFromRange = (range) => {
|
||
switch (range) {
|
||
case "1D": return 1;
|
||
case "1W": return 7;
|
||
case "15D": return 15;
|
||
case "1M": return 30;
|
||
case "3M": return 90;
|
||
case "1Y": return 365;
|
||
case "5Y": return 1825;
|
||
default: return 7;
|
||
}
|
||
};
|
||
|
||
const days = getDaysFromRange(range);
|
||
const today = new Date();
|
||
const FromDate = today.toLocaleDateString('en-CA');
|
||
|
||
const { dashboard_data, loading: isLineChartLoading } = useDashboard_Data({
|
||
days,
|
||
FromDate,
|
||
projectId: selectedProjectId === "all" ? null : selectedProjectId,
|
||
});
|
||
|
||
const sortedDashboardData = [...dashboard_data].sort(
|
||
(a, b) => new Date(a.date) - new Date(b.date)
|
||
);
|
||
|
||
const lineChartSeries = [
|
||
{
|
||
name: "Planned Work",
|
||
data: sortedDashboardData.map((d) => d.plannedTask || 0),
|
||
},
|
||
{
|
||
name: "Completed Work",
|
||
data: sortedDashboardData.map((d) => d.completedTask || 0),
|
||
},
|
||
];
|
||
|
||
const lineChartCategories = sortedDashboardData.map((d) =>
|
||
new Date(d.date).toLocaleDateString("en-US", { month: "short", day: "numeric" })
|
||
);
|
||
const lineChartCategoriesDates = sortedDashboardData.map((d) =>
|
||
new Date(d.date).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })
|
||
);
|
||
|
||
return (
|
||
<div className="card h-100">
|
||
<div className="card-header">
|
||
{/* Row 1: Title + Project Selector */}
|
||
<div className="d-flex flex-wrap justify-content-between align-items-center mb-2">
|
||
<div className="card-title mb-0 text-start">
|
||
<h5 className="mb-1">Project Progress</h5>
|
||
<p className="card-subtitle">Progress Overview by Project</p>
|
||
</div>
|
||
|
||
<div className="btn-group">
|
||
<button
|
||
className="btn btn-outline-primary btn-sm dropdown-toggle"
|
||
type="button"
|
||
data-bs-toggle="dropdown"
|
||
aria-expanded="false"
|
||
>
|
||
{selectedProjectId === "all"
|
||
? "All Projects"
|
||
: projects?.find((p) => p.id === selectedProjectId)?.name || "Select Project"}
|
||
</button>
|
||
|
||
<ul className="dropdown-menu">
|
||
<li>
|
||
<button className="dropdown-item" onClick={() => setSelectedProjectId("all")}>
|
||
All Projects
|
||
</button>
|
||
</li>
|
||
{projects?.map((project) => (
|
||
<li key={project.id}>
|
||
<button
|
||
className="dropdown-item"
|
||
onClick={() => setSelectedProjectId(project.id)}
|
||
>
|
||
{project.name}
|
||
</button>
|
||
</li>
|
||
))}
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Row 2: Time Range Buttons */}
|
||
<div className="d-flex flex-wrap mt-2">
|
||
{["1D", "1W", "15D", "1M", "3M", "1Y", "5Y"].map((key) => (
|
||
<button
|
||
key={key}
|
||
className={`border-0 bg-transparent px-2 py-1 text-sm rounded ${
|
||
range === key ? " border-bottom border-primary text-primary" : "text-muted"
|
||
}`}
|
||
style={{ cursor: "pointer", transition: "all 0.2s ease" }}
|
||
onClick={() => setRange(key)}
|
||
>
|
||
{key}
|
||
</button>
|
||
))}
|
||
</div>
|
||
</div>
|
||
<div className="card-body ">
|
||
<LineChart
|
||
seriesData={lineChartSeries}
|
||
categories={lineChartCategories}
|
||
loading={isLineChartLoading}
|
||
lineChartCategoriesDates={lineChartCategoriesDates}
|
||
/>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default ProjectProgressChart;
|