Compare commits
4 Commits
main
...
UI_Changes
| Author | SHA1 | Date | |
|---|---|---|---|
| 44bcb773ef | |||
| 6391fcc888 | |||
| 4fa112b43a | |||
| 96d349818a |
32
src/components/Charts/ProjectCompletionChartSkeleton.jsx
Normal file
32
src/components/Charts/ProjectCompletionChartSkeleton.jsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const ProjectCompletionChartSkeleton = () => {
|
||||||
|
return (
|
||||||
|
<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 fw-bold placeholder-glow">
|
||||||
|
<span className="placeholder col-6 bg-light"></span>
|
||||||
|
</h5>
|
||||||
|
<p className="card-subtitle placeholder-glow">
|
||||||
|
<span className="placeholder col-8 bg-light"></span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* Keep a fixed height so card doesn't shrink */}
|
||||||
|
<div className="card-body" >
|
||||||
|
<div className="placeholder-glow">
|
||||||
|
{Array.from({ length: 5 }).map((_, i) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className="placeholder col-12 mb-2 bg-light"
|
||||||
|
style={{ height: "20px", borderRadius: "4px" }}
|
||||||
|
></div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProjectCompletionChartSkeleton;
|
||||||
44
src/components/Charts/ProjectProgressChartSkeleton.jsx
Normal file
44
src/components/Charts/ProjectProgressChartSkeleton.jsx
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// ProjectProgressChartSkeleton.jsx
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const ProjectProgressChartSkeleton = () => {
|
||||||
|
return (
|
||||||
|
<div className="card" style={{ minHeight: "400px" }}>
|
||||||
|
<div className="card-header">
|
||||||
|
<div className="d-flex flex-wrap justify-content-between align-items-start mb-2">
|
||||||
|
{/* Left: Title */}
|
||||||
|
<div className="card-title text-start">
|
||||||
|
<div className="placeholder-glow">
|
||||||
|
<span className="placeholder col-6 mb-2"></span>
|
||||||
|
<span className="placeholder col-4"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Row 2: Time Range Buttons */}
|
||||||
|
<div className="d-flex flex-wrap mt-2">
|
||||||
|
{Array(7)
|
||||||
|
.fill(0)
|
||||||
|
.map((_, idx) => (
|
||||||
|
<span
|
||||||
|
key={idx}
|
||||||
|
className="placeholder bg-light col-1 me-2"
|
||||||
|
style={{ height: "25px", borderRadius: "5px" }}
|
||||||
|
></span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="card-body">
|
||||||
|
<div
|
||||||
|
className="placeholder-glow"
|
||||||
|
style={{ height: "250px", width: "100%" }}
|
||||||
|
>
|
||||||
|
<span className="placeholder bg-light col-12 h-100"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProjectProgressChartSkeleton;
|
||||||
18
src/components/Charts/TeamsSkeleton.jsx
Normal file
18
src/components/Charts/TeamsSkeleton.jsx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const TeamsSkeleton = () => {
|
||||||
|
return (
|
||||||
|
<div className="d-flex justify-content-around align-items-start mt-n2 flex-grow-1">
|
||||||
|
<div>
|
||||||
|
<div className="bg-light rounded" style={{ width: "80px", height: "24px", marginBottom: "5px" }}></div>
|
||||||
|
<div className="bg-light rounded" style={{ width: "60px", height: "12px" }}></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="bg-light rounded" style={{ width: "80px", height: "24px", marginBottom: "5px" }}></div>
|
||||||
|
<div className="bg-light rounded" style={{ width: "60px", height: "12px" }}></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TeamsSkeleton;
|
||||||
@ -99,7 +99,9 @@ const AttendanceOverview = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-white p-4 rounded shadow d-flex flex-column">
|
<div
|
||||||
|
className="bg-white p-4 rounded shadow d-flex flex-column"
|
||||||
|
>
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="d-flex justify-content-between align-items-center mb-3">
|
<div className="d-flex justify-content-between align-items-center mb-3">
|
||||||
<div className="card-title mb-0 text-start">
|
<div className="card-title mb-0 text-start">
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import HorizontalBarChart from "../Charts/HorizontalBarChart";
|
import HorizontalBarChart from "../Charts/HorizontalBarChart";
|
||||||
import { useProjects } from "../../hooks/useProjects";
|
import { useProjects } from "../../hooks/useProjects";
|
||||||
|
import ProjectCompletionChartSkeleton from "../Charts/ProjectCompletionChartSkeleton";
|
||||||
|
|
||||||
const ProjectCompletionChart = () => {
|
const ProjectCompletionChart = () => {
|
||||||
const { projects, loading } = useProjects();
|
const { projects, loading } = useProjects();
|
||||||
|
|
||||||
// Bar chart logic
|
if (loading) return <ProjectCompletionChartSkeleton />;
|
||||||
|
|
||||||
const projectNames = projects?.map((p) => p.name) || [];
|
const projectNames = projects?.map((p) => p.name) || [];
|
||||||
const projectProgress =
|
const projectProgress =
|
||||||
projects?.map((p) => {
|
projects?.map((p) => {
|
||||||
@ -16,14 +18,15 @@ const ProjectCompletionChart = () => {
|
|||||||
}) || [];
|
}) || [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card h-100">
|
<div className="card" style={{ minHeight: "490px" }}>
|
||||||
<div className="card-header d-flex align-items-start justify-content-between">
|
<div className="card-header d-flex align-items-start justify-content-between">
|
||||||
<div className="card-title mb-0 text-start">
|
<div className="card-title mb-0 text-start">
|
||||||
<h5 className="mb-1 fw-bold ">Projects</h5>
|
<h5 className="mb-1 fw-bold">Projects</h5>
|
||||||
<p className="card-subtitle">Projects Completion Status</p>
|
<p className="card-subtitle">Projects Completion Status</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="card-body">
|
{/* Keep same minHeight as skeleton to avoid shrinking */}
|
||||||
|
<div className="card-body" >
|
||||||
<HorizontalBarChart
|
<HorizontalBarChart
|
||||||
categories={projectNames}
|
categories={projectNames}
|
||||||
seriesData={projectProgress}
|
seriesData={projectProgress}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import LineChart from "../Charts/LineChart";
|
|||||||
import { useProjects } from "../../hooks/useProjects";
|
import { useProjects } from "../../hooks/useProjects";
|
||||||
import { useDashboard_Data } from "../../hooks/useDashboard_Data";
|
import { useDashboard_Data } from "../../hooks/useDashboard_Data";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
|
import ProjectProgressChartSkeleton from "../Charts/ProjectProgressChartSkeleton";
|
||||||
|
|
||||||
const ProjectProgressChart = ({
|
const ProjectProgressChart = ({
|
||||||
ShowAllProject = true,
|
ShowAllProject = true,
|
||||||
@ -85,7 +86,7 @@ const ProjectProgressChart = ({
|
|||||||
: selectedProjectData?.name;
|
: selectedProjectData?.name;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card">
|
<div className="card" style={{ minHeight: "490px" }}>
|
||||||
<div className="card-header">
|
<div className="card-header">
|
||||||
<div className="d-flex flex-wrap justify-content-between align-items-start mb-2">
|
<div className="d-flex flex-wrap justify-content-between align-items-start mb-2">
|
||||||
{/* Left: Title */}
|
{/* Left: Title */}
|
||||||
@ -100,8 +101,7 @@ const ProjectProgressChart = ({
|
|||||||
{["1D", "1W", "15D", "1M", "3M", "1Y", "5Y"].map((key) => (
|
{["1D", "1W", "15D", "1M", "3M", "1Y", "5Y"].map((key) => (
|
||||||
<button
|
<button
|
||||||
key={key}
|
key={key}
|
||||||
className={`border-0 bg-transparent px-2 py-1 text-sm rounded ${
|
className={`border-0 bg-transparent px-2 py-1 text-sm rounded ${range === key
|
||||||
range === key
|
|
||||||
? "border-bottom border-primary text-primary"
|
? "border-bottom border-primary text-primary"
|
||||||
: "text-muted"
|
: "text-muted"
|
||||||
}`}
|
}`}
|
||||||
@ -114,14 +114,17 @@ const ProjectProgressChart = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="card-body">
|
{isLineChartLoading ? (
|
||||||
|
<ProjectProgressChartSkeleton />
|
||||||
|
) : (
|
||||||
<LineChart
|
<LineChart
|
||||||
seriesData={lineChartSeries}
|
seriesData={lineChartSeries}
|
||||||
categories={lineChartCategories}
|
categories={lineChartCategories}
|
||||||
loading={isLineChartLoading}
|
loading={isLineChartLoading}
|
||||||
lineChartCategoriesDates={lineChartCategoriesDates}
|
lineChartCategoriesDates={lineChartCategoriesDates}
|
||||||
/>
|
/>
|
||||||
</div>
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,9 +2,10 @@ import React, { useCallback, useEffect, useState } from "react";
|
|||||||
import { useDashboardProjectsCardData } from "../../hooks/useDashboard_Data";
|
import { useDashboardProjectsCardData } from "../../hooks/useDashboard_Data";
|
||||||
import eventBus from "../../services/eventBus";
|
import eventBus from "../../services/eventBus";
|
||||||
import GlobalRepository from "../../repositories/GlobalRepository";
|
import GlobalRepository from "../../repositories/GlobalRepository";
|
||||||
|
import TeamsSkeleton from "../Charts/TeamsSkeleton";
|
||||||
|
|
||||||
const Projects = () => {
|
const Projects = () => {
|
||||||
const { projectsCardData } = useDashboardProjectsCardData();
|
const { projectsCardData,loading } = useDashboardProjectsCardData();
|
||||||
const [projectData, setProjectsData] = useState(projectsCardData);
|
const [projectData, setProjectsData] = useState(projectsCardData);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -37,6 +38,9 @@ const Projects = () => {
|
|||||||
Projects
|
Projects
|
||||||
</h5>
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
|
{loading ? (
|
||||||
|
<TeamsSkeleton />
|
||||||
|
) : (
|
||||||
<div className="d-flex justify-content-around align-items-start mt-n2">
|
<div className="d-flex justify-content-around align-items-start mt-n2">
|
||||||
<div>
|
<div>
|
||||||
<h4 className="mb-0 fw-bold">
|
<h4 className="mb-0 fw-bold">
|
||||||
@ -51,6 +55,7 @@ const Projects = () => {
|
|||||||
<small className="text-muted">Ongoing</small>
|
<small className="text-muted">Ongoing</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { useDashboardTasksCardData } from "../../hooks/useDashboard_Data";
|
import { useDashboardTasksCardData } from "../../hooks/useDashboard_Data";
|
||||||
|
import TeamsSkeleton from "../Charts/TeamsSkeleton";
|
||||||
const TasksCard = () => {
|
const TasksCard = () => {
|
||||||
const projectId = useSelector((store) => store.localVariables?.projectId);
|
const projectId = useSelector((store) => store.localVariables?.projectId);
|
||||||
const { tasksCardData, loading, error } = useDashboardTasksCardData(projectId);
|
const { tasksCardData, loading, error } = useDashboardTasksCardData(projectId);
|
||||||
@ -16,11 +16,7 @@ const TasksCard = () => {
|
|||||||
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
// Loader will be displayed when loading is true
|
// Loader will be displayed when loading is true
|
||||||
<div className="d-flex justify-content-center align-items-center flex-grow-1">
|
<TeamsSkeleton/>
|
||||||
<div className="spinner-border text-primary" role="status">
|
|
||||||
<span className="visually-hidden">Loading...</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : error ? (
|
) : error ? (
|
||||||
// Error message if there's an error
|
// Error message if there's an error
|
||||||
<div className="text-danger flex-grow-1 d-flex justify-content-center align-items-center">{error}</div>
|
<div className="text-danger flex-grow-1 d-flex justify-content-center align-items-center">{error}</div>
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import React, { useCallback, useEffect, useState } from "react";
|
|||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { useDashboardTeamsCardData } from "../../hooks/useDashboard_Data";
|
import { useDashboardTeamsCardData } from "../../hooks/useDashboard_Data";
|
||||||
import eventBus from "../../services/eventBus";
|
import eventBus from "../../services/eventBus";
|
||||||
|
import TeamsSkeleton from "../Charts/TeamsSkeleton";
|
||||||
|
|
||||||
const Teams = () => {
|
const Teams = () => {
|
||||||
const projectId = useSelector((store) => store.localVariables?.projectId);
|
const projectId = useSelector((store) => store.localVariables?.projectId);
|
||||||
@ -38,11 +39,7 @@ const Teams = () => {
|
|||||||
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
// Blue spinner loader
|
// Blue spinner loader
|
||||||
<div className="d-flex justify-content-center align-items-center flex-grow-1">
|
<TeamsSkeleton/>
|
||||||
<div className="spinner-border text-primary" role="status">
|
|
||||||
<span className="visually-hidden">Loading...</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : error ? (
|
) : error ? (
|
||||||
// Error message if data fetching fails
|
// Error message if data fetching fails
|
||||||
<div className="text-danger flex-grow-1 d-flex justify-content-center align-items-center">{error}</div>
|
<div className="text-danger flex-grow-1 d-flex justify-content-center align-items-center">{error}</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user