221 lines
8.4 KiB
JavaScript

import React, { useState } from 'react';
import HorizontalBarChart from '../Charts/HorizontalBarChart';
import LineChart from '../Charts/LineChart';
import { useProjects } from '../../hooks/useProjects';
import {
useDashboard_Data,
useDashboardProjectsCardData,
useDashboardTeamsCardData,
useDashboardTasksCardData,
} from "../../hooks/useDashboard_Data";
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]; // Always today
const { projectsCardData } = useDashboardProjectsCardData();
const { teamsCardData } = useDashboardTeamsCardData();
const { tasksCardData } = useDashboardTasksCardData();
const { dashboard_data, loading: isLineChartLoading } = useDashboard_Data({
days,
FromDate,
projectId: selectedProjectId === 'all' ? 0 : 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' })
);
return (
<div className="container-xxl flex-grow-1 container-p-y">
<div className="row gy-4">
{/* Projects Card */}
<div className="col-sm-6 col-lg-4">
<div className="card p-3 h-100 text-center d-flex justify-content-between">
<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"></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>
{/* Teams Card */}
<div className="col-sm-6 col-lg-4">
<div className="card p-3 h-100 text-center d-flex justify-content-between">
<div className="d-flex justify-content-start align-items-center mb-3">
<h5 className="fw-bold mb-0 ms-2"><i className="bx bx-group text-warning"></i> Teams</h5>
</div>
<div className="d-flex justify-content-around align-items-start mt-n2">
<div>
<h4 className="mb-0 fw-bold">{teamsCardData.totalEmployees?.toLocaleString()}</h4>
<small className="text-muted">Total Employees</small>
</div>
<div>
<h4 className="mb-0 fw-bold">{teamsCardData.inToday?.toLocaleString()}</h4>
<small className="text-muted">In Today</small>
</div>
</div>
</div>
</div>
{/* Tasks Card */}
<div className="col-sm-6 col-lg-4">
<div className="card p-3 h-100 text-center d-flex justify-content-between">
<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>
{/* Bar Chart */}
<div className="col-xxl-6 col-lg-6">
<div className="card h-100">
<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">Total Projects Overview</p>
</div>
</div>
<div className="card-body">
<HorizontalBarChart
categories={projectNames}
seriesData={projectProgress}
loading={loading}
/>
</div>
</div>
</div>
{/* 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 type="button" className="btn btn-label-primary btn-sm">
{selectedProjectId === 'all'
? 'All Projects'
: projects?.find(p => p.id === selectedProjectId)?.name || 'Select Project'}
</button>
<button
type="button"
className="btn btn-label-primary dropdown-toggle dropdown-toggle-split"
data-bs-toggle="dropdown"
aria-expanded="false"
>
<span className="visually-hidden">Toggle Dropdown</span>
</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 gap-2 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 ? 'fw-bold 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} />
</div>
</div>
</div>
</div>
</div>
);
};
export default Dashboard;