Dashboard Component View. #146
@ -1,252 +1,50 @@
|
|||||||
import React, { useState } from "react";
|
import React from "react";
|
||||||
import HorizontalBarChart from "../Charts/HorizontalBarChart";
|
|
||||||
import LineChart from "../Charts/LineChart";
|
|
||||||
import { useProjects } from "../../hooks/useProjects";
|
|
||||||
import {
|
import {
|
||||||
useDashboard_Data,
|
|
||||||
useDashboardProjectsCardData,
|
useDashboardProjectsCardData,
|
||||||
useDashboardTeamsCardData,
|
useDashboardTeamsCardData,
|
||||||
useDashboardTasksCardData,
|
useDashboardTasksCardData,
|
||||||
} from "../../hooks/useDashboard_Data";
|
} from "../../hooks/useDashboard_Data";
|
||||||
|
import Projects from "./Projects";
|
||||||
import Teams from "./Teams";
|
import Teams from "./Teams";
|
||||||
|
import TasksCard from "./Tasks";
|
||||||
|
import ProjectCompletionChart from "./ProjectCompletionChart";
|
||||||
|
import ProjectProgressChart from "./ProjectProgressChart";
|
||||||
|
|
||||||
const Dashboard = () => {
|
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 { projectsCardData } = useDashboardProjectsCardData();
|
||||||
const { teamsCardData } = useDashboardTeamsCardData();
|
const { teamsCardData } = useDashboardTeamsCardData();
|
||||||
const { tasksCardData } = useDashboardTasksCardData();
|
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 =
|
|
||||||
projects?.map((p) => {
|
|
||||||
const completed = p.completedWork || 0;
|
|
||||||
const planned = p.plannedWork || 1;
|
|
||||||
const percent = (completed / planned) * 100;
|
|
||||||
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 (
|
return (
|
||||||
<div className="container-xxl flex-grow-1 container-p-y">
|
<div className="container-xxl flex-grow-1 container-p-y">
|
||||||
<div className="row gy-4">
|
<div className="row gy-4">
|
||||||
{/* Projects Card */}
|
{/* Projects Card */}
|
||||||
<div className="col-sm-6 col-lg-4">
|
<div className="col-sm-6 col-lg-4">
|
||||||
<div className="card p-3 h-100 text-center d-flex justify-content-between">
|
<Projects projectsCardData={projectsCardData} />
|
||||||
<div className="d-flex justify-content-start align-items-center mb-3">
|
|
||||||
<h5 className="fw-bold mb-0 ms-2">
|
|
||||||
<i className="rounded-circle bx bx-building-house text-primary"></i>{" "}
|
|
||||||
Projects
|
|
||||||
</h5>
|
|
||||||
</div>
|
|
||||||
<div className="d-flex justify-content-around align-items-start mt-n2">
|
|
||||||
<div>
|
|
||||||
<h4 className="mb-0 fw-bold">
|
|
||||||
{projectsCardData.totalProjects?.toLocaleString()}
|
|
||||||
</h4>
|
|
||||||
<small className="text-muted">Total</small>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4 className="mb-0 fw-bold">
|
|
||||||
{projectsCardData.ongoingProjects?.toLocaleString()}
|
|
||||||
</h4>
|
|
||||||
<small className="text-muted">Ongoing</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Teams Card */}
|
{/* Teams Card */}
|
||||||
<div className="col-sm-6 col-lg-4">
|
<div className="col-sm-6 col-lg-4">
|
||||||
<Teams teamsCardData={teamsCardData} /> {/* Use the Teams component */}
|
<Teams teamsCardData={teamsCardData} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Tasks Card */}
|
{/* Tasks Card */}
|
||||||
<div className="col-sm-6 col-lg-4">
|
<div className="col-sm-6 col-lg-4">
|
||||||
<div className="card p-3 h-100 text-center d-flex justify-content-between">
|
<TasksCard tasksCardData={tasksCardData} />
|
||||||
<div className="d-flex justify-content-start align-items-center mb-3">
|
|
||||||
<h5 className="fw-bold mb-0 ms-2">
|
|
||||||
<i className="bx bx-task text-success"></i> Tasks
|
|
||||||
</h5>
|
|
||||||
</div>
|
|
||||||
<div className="d-flex justify-content-around align-items-start mt-n2">
|
|
||||||
<div>
|
|
||||||
<h4 className="mb-0 fw-bold">
|
|
||||||
{tasksCardData.totalTasks?.toLocaleString()}
|
|
||||||
</h4>
|
|
||||||
<small className="text-muted">Total</small>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4 className="mb-0 fw-bold">
|
|
||||||
{tasksCardData.completedTasks?.toLocaleString()}
|
|
||||||
</h4>
|
|
||||||
<small className="text-muted">Completed</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Bar Chart */}
|
{/* Bar Chart (Project Completion) */}
|
||||||
<div className="col-xxl-6 col-lg-6">
|
<div className="col-xxl-6 col-lg-6">
|
||||||
<div className="card h-100">
|
<ProjectCompletionChart />
|
||||||
<div className="card-header d-flex align-items-start justify-content-between">
|
|
||||||
<div className="card-title mb-0 text-start">
|
|
||||||
<h5 className="mb-1">Projects</h5>
|
|
||||||
<p className="card-subtitle">Projects Completion Status</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="card-body">
|
|
||||||
<HorizontalBarChart
|
|
||||||
categories={projectNames}
|
|
||||||
seriesData={projectProgress}
|
|
||||||
loading={loading}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Line Chart */}
|
{/* Line Chart (Project Progress) */}
|
||||||
<div className="col-xxl-6 col-lg-6">
|
<div className="col-xxl-6 col-lg-6">
|
||||||
<div className="card h-100">
|
<ProjectProgressChart />
|
||||||
<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>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Dashboard;
|
export default Dashboard;
|
Loading…
x
Reference in New Issue
Block a user