63 lines
1.9 KiB
JavaScript
63 lines
1.9 KiB
JavaScript
import React, { useEffect } from "react";
|
|
import { useDashboardProjectsCardData } from "../../hooks/useDashboard_Data";
|
|
import eventBus from "../../services/eventBus";
|
|
|
|
const Projects = () => {
|
|
const {
|
|
data: projectsCardData,
|
|
isLoading,
|
|
isError,
|
|
error,
|
|
refetch,
|
|
} = useDashboardProjectsCardData();
|
|
|
|
useEffect(() => {
|
|
// When "project" event happens, just refetch
|
|
const handler = () => {
|
|
refetch();
|
|
};
|
|
|
|
eventBus.on("project", handler);
|
|
return () => eventBus.off("project", handler);
|
|
}, [refetch]);
|
|
|
|
const totalProjects = projectsCardData?.totalProjects ?? 0;
|
|
const ongoingProjects = projectsCardData?.ongoingProjects ?? 0;
|
|
|
|
return (
|
|
<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 text-primary"></i>{" "}
|
|
Projects
|
|
</h5>
|
|
</div>
|
|
|
|
{isLoading ? (
|
|
<div className="d-flex justify-content-center align-items-center flex-grow-1">
|
|
<div className="spinner-border text-primary" role="status">
|
|
<span className="visually-hidden">Loading...</span>
|
|
</div>
|
|
</div>
|
|
) : isError ? (
|
|
<div className="text-danger flex-grow-1 d-flex justify-content-center align-items-center">
|
|
{error?.message || "Error loading data"}
|
|
</div>
|
|
) : (
|
|
<div className="d-flex justify-content-around align-items-start mt-n2">
|
|
<div>
|
|
<h4 className="mb-0 fw-bold">{totalProjects.toLocaleString()}</h4>
|
|
<small className="text-muted">Total</small>
|
|
</div>
|
|
<div>
|
|
<h4 className="mb-0 fw-bold">{ongoingProjects.toLocaleString()}</h4>
|
|
<small className="text-muted">Ongoing</small>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Projects;
|