Move all the project-related code from the Dashboard component into a new component named 'Progress Overview by Project'.
This commit is contained in:
parent
396706dcf5
commit
cf11e995de
@ -8,53 +8,18 @@ import {
|
||||
useDashboardTeamsCardData,
|
||||
useDashboardTasksCardData,
|
||||
} from "../../hooks/useDashboard_Data";
|
||||
import ProjectProgressChart from "./ProjectProgressChart";
|
||||
|
||||
const Dashboard = () => {
|
||||
const { projects, loading } = 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.toISOString().split("T")[0];
|
||||
const FromDate = today.toLocaleDateString('en-CA'); // Always today
|
||||
|
||||
const { projectsCardData } = useDashboardProjectsCardData();
|
||||
const { teamsCardData } = useDashboardTeamsCardData();
|
||||
const { tasksCardData } = useDashboardTasksCardData();
|
||||
|
||||
const { dashboard_data, loading: isLineChartLoading } = useDashboard_Data({
|
||||
days,
|
||||
FromDate,
|
||||
projectId: selectedProjectId === "all" ? null : selectedProjectId,
|
||||
});
|
||||
|
||||
// Sort dashboard_data by date ascending
|
||||
const sortedDashboardData = [...dashboard_data].sort(
|
||||
(a, b) => new Date(a.date) - new Date(b.date)
|
||||
);
|
||||
|
||||
// Bar chart logic
|
||||
const projectNames = projects?.map((p) => p.name) || [];
|
||||
const projectProgress =
|
||||
@ -65,31 +30,7 @@ const Dashboard = () => {
|
||||
return Math.min(Math.round(percent), 100);
|
||||
}) || [];
|
||||
|
||||
// Line chart data
|
||||
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="container-xxl flex-grow-1 container-p-y">
|
||||
<div className="row gy-4">
|
||||
@ -190,78 +131,7 @@ const Dashboard = () => {
|
||||
|
||||
{/* Line Chart */}
|
||||
<div className="col-xxl-6 col-lg-6">
|
||||
<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>
|
||||
<ProjectProgressChart />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
126
src/components/Dashboard/ProjectProgressChart.jsx
Normal file
126
src/components/Dashboard/ProjectProgressChart.jsx
Normal file
@ -0,0 +1,126 @@
|
||||
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;
|
Loading…
x
Reference in New Issue
Block a user