splitted code and added server data
This commit is contained in:
parent
b2c0388412
commit
37212e489e
@ -3,11 +3,16 @@ import HorizontalBarChart from "../Charts/HorizontalBarChart";
|
|||||||
import { useProjects } from "../../hooks/useProjects";
|
import { useProjects } from "../../hooks/useProjects";
|
||||||
|
|
||||||
const ProjectCompletionChart = () => {
|
const ProjectCompletionChart = () => {
|
||||||
const { data: projects = [], isLoading: loading, isError, error } = useProjects();
|
const { data, isLoading: loading } = useProjects();
|
||||||
|
|
||||||
|
const projects = Array.isArray(data)
|
||||||
|
? data
|
||||||
|
: data?.data && Array.isArray(data.data)
|
||||||
|
? data.data
|
||||||
|
: [];
|
||||||
|
|
||||||
// Bar chart logic
|
// Bar chart logic
|
||||||
const projectNames = projects?.map((p) => p.name) || [];
|
const projectNames = projects?.map((p) => p.name) ?? [];
|
||||||
const projectProgress =
|
const projectProgress =
|
||||||
projects?.map((p) => {
|
projects?.map((p) => {
|
||||||
const completed = p.completedWork || 0;
|
const completed = p.completedWork || 0;
|
||||||
|
|||||||
31
src/components/reports/ActivitiesTable.jsx
Normal file
31
src/components/reports/ActivitiesTable.jsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
const ActivitiesTable = ({ date, rows }) => {
|
||||||
|
return (
|
||||||
|
<div className="reports-activities">
|
||||||
|
<h2>Activities (Tasks) Performed {date}</h2>
|
||||||
|
|
||||||
|
<table className="reports-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>NAME</th>
|
||||||
|
<th>JOB ROLE</th>
|
||||||
|
<th>CHECK IN</th>
|
||||||
|
<th>CHECK OUT</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{rows.map((row, i) => (
|
||||||
|
<tr key={i}>
|
||||||
|
<td>{row.name}</td>
|
||||||
|
<td>{row.role}</td>
|
||||||
|
<td>{row.in}</td>
|
||||||
|
<td>{row.out}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ActivitiesTable;
|
||||||
52
src/components/reports/Progress.jsx
Normal file
52
src/components/reports/Progress.jsx
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import React from "react";
|
||||||
|
import Chart from "react-apexcharts";
|
||||||
|
|
||||||
|
const Progress = ({
|
||||||
|
color = "#00aaff",
|
||||||
|
series = 40,
|
||||||
|
progress_variant = "success",
|
||||||
|
height = 130,
|
||||||
|
}) => {
|
||||||
|
const options = {
|
||||||
|
chart: {
|
||||||
|
type: "radialBar",
|
||||||
|
},
|
||||||
|
colors: [color],
|
||||||
|
|
||||||
|
plotOptions: {
|
||||||
|
radialBar: {
|
||||||
|
hollow: {
|
||||||
|
size: "55%",
|
||||||
|
},
|
||||||
|
track: {
|
||||||
|
background: "#f1f1f1",
|
||||||
|
},
|
||||||
|
|
||||||
|
dataLabels: {
|
||||||
|
name: { show: false },
|
||||||
|
value: {
|
||||||
|
show: true,
|
||||||
|
fontSize: "18px",
|
||||||
|
fontWeight: 600,
|
||||||
|
offsetY: 7,
|
||||||
|
offsetY:7,
|
||||||
|
formatter: () => `${series}%`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
stroke: { lineCap: "round" },
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Chart
|
||||||
|
options={options}
|
||||||
|
series={[Number(series)]}
|
||||||
|
type="radialBar"
|
||||||
|
height={height}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Progress;
|
||||||
41
src/components/reports/ReportsDonutCard.jsx
Normal file
41
src/components/reports/ReportsDonutCard.jsx
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import ReportsLegend from "./ReportsLegend";
|
||||||
|
|
||||||
|
const ReportsDonutCard = ({
|
||||||
|
title,
|
||||||
|
percentage,
|
||||||
|
value,
|
||||||
|
donutClass = "",
|
||||||
|
footer = "Team members present on the site"
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div className="reports-card">
|
||||||
|
<h4 className="reports-card-title">{title}</h4>
|
||||||
|
|
||||||
|
<div style={{ display: "flex", flexWrap: "wrap" }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: "50%",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={`reports-donut thin ${donutClass}`}
|
||||||
|
style={{ percentage: percentage }}
|
||||||
|
>
|
||||||
|
<span>{value}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ReportsLegend />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ padding: "10px", textAlign: "center" }}>
|
||||||
|
<p className="text-muted">{footer}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ReportsDonutCard;
|
||||||
22
src/components/reports/ReportsLegend.jsx
Normal file
22
src/components/reports/ReportsLegend.jsx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
const ReportsLegend = () => {
|
||||||
|
return (
|
||||||
|
<div className="reports-legend" style={{ width: "50%", padding: "15px" }}>
|
||||||
|
<div className="reports-legend-item">
|
||||||
|
<span className="reports-legend-color reports-legend-green" />
|
||||||
|
Completed
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="reports-legend-item">
|
||||||
|
<span className="reports-legend-color reports-legend-blue" />
|
||||||
|
In Progress
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="reports-legend-item">
|
||||||
|
<span className="reports-legend-color reports-legend-gray" />
|
||||||
|
Pending
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ReportsLegend;
|
||||||
20
src/components/reports/TeamStrengthCard.jsx
Normal file
20
src/components/reports/TeamStrengthCard.jsx
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
const TeamStrengthCard = ({ data }) => {
|
||||||
|
return (
|
||||||
|
<div className="reports-card">
|
||||||
|
<h4 className="reports-card-title">Team Strength on Site</h4>
|
||||||
|
|
||||||
|
<table style={{ width: "100%" }}>
|
||||||
|
<tbody>
|
||||||
|
{data.map((item, i) => (
|
||||||
|
<tr key={i}>
|
||||||
|
<td style={{ textAlign: "left" }}>{item.role}</td>
|
||||||
|
<td style={{ textAlign: "right" }}>{item.count}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TeamStrengthCard;
|
||||||
@ -1,12 +1,19 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { useProjectReportByProject } from "../../hooks/useReports";
|
||||||
|
import Progress from "./Progress";
|
||||||
|
import { formatUTCToLocalTime } from "../../utils/dateUtils";
|
||||||
|
|
||||||
const ReportDPR = () => {
|
const ReportDPR = ({ project, day }) => {
|
||||||
|
const { data, isLoading, isError, error } =
|
||||||
|
useProjectReportByProject(project);
|
||||||
|
console.log(data);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{" "}
|
{" "}
|
||||||
<div class="reports-container">
|
<div className="card">
|
||||||
|
{/* <div class="reports-container"> */}
|
||||||
{/* <!-- Header */}
|
{/* <!-- Header */}
|
||||||
<div class="reports-header">
|
{/* <div class="reports-header">
|
||||||
<div class="d-flex flex-wrap align-items-start reports-project-info">
|
<div class="d-flex flex-wrap align-items-start reports-project-info">
|
||||||
<strong>Project:</strong>
|
<strong>Project:</strong>
|
||||||
<select class="form-select" aria-label="Default select example">
|
<select class="form-select" aria-label="Default select example">
|
||||||
@ -390,11 +397,15 @@ const ReportDPR = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
{/* <!-- Status Note */}
|
{/* <!-- Status Note */}
|
||||||
<div class="reports-status-note">
|
{/* <div class="reports-status-note">
|
||||||
* Project Status Reported - Generated at 18-Sep-2025 03:30:03 UTC
|
* Project Status Reported - Generated at 18-Sep-2025 03:30:03 UTC
|
||||||
|
</div> */}
|
||||||
|
<div className="d-flex text-start px-6 mt-2">
|
||||||
|
Project Status Reported - Generated at{" "}
|
||||||
|
{formatUTCToLocalTime(data?.date, true)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* <!-- Status Cards */}
|
{/* <!-- Status Cards */}
|
||||||
@ -406,14 +417,14 @@ const ReportDPR = () => {
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
width: "50%",
|
width: "50%",
|
||||||
boxSizing: "border-box",
|
boxSizing: "bordtarter-box",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* <!-- Medium */}
|
{/* <!-- Medium */}
|
||||||
<div class="reports-donut thin" style={{ percentage: "66" }}>
|
<div class="reports-donut thin" style={{ percentage: 90 }}>
|
||||||
<span>20 / 30</span>
|
<span>20 / 30</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -784,22 +795,17 @@ const ReportDPR = () => {
|
|||||||
<h4 class="reports-card-title">Team Strength on Site</h4>
|
<h4 class="reports-card-title">Team Strength on Site</h4>
|
||||||
</div>
|
</div>
|
||||||
<table style={{ width: "100%" }}>
|
<table style={{ width: "100%" }}>
|
||||||
<tr>
|
<tbody>
|
||||||
<td style={{ textAlign: "left" }}>Site Engineer</td>
|
{data?.teamOnSite?.map((member, index) => (
|
||||||
<td style={{ textAlign: "right" }}>1</td>
|
<tr key={index}>
|
||||||
</tr>
|
<td style={{ textAlign: "left" }}>{member?.roleName}</td>
|
||||||
<tr>
|
|
||||||
<td style={{ textAlign: "left" }}>Weilder</td>
|
<td style={{ textAlign: "right" }}>
|
||||||
<td style={{ textAlign: "right" }}>15</td>
|
{member?.numberofEmployees}
|
||||||
</tr>
|
</td>
|
||||||
<tr>
|
</tr>
|
||||||
<td style={{ textAlign: "left" }}>Helper</td>
|
))}
|
||||||
<td style={{ textAlign: "right" }}>2</td>
|
</tbody>
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td style={{ textAlign: "left" }}>Painter</td>
|
|
||||||
<td style={{ textAlign: "right" }}>1</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
14
src/hooks/useReports.js
Normal file
14
src/hooks/useReports.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { useQuery } from "@tanstack/react-query"
|
||||||
|
import { ReportsRepository } from "../repositories/GlobalRepository"
|
||||||
|
|
||||||
|
|
||||||
|
export const useProjectReportByProject = (projectId)=>{
|
||||||
|
return useQuery({
|
||||||
|
queryKey:["daily_report",projectId],
|
||||||
|
queryFn:async()=>{
|
||||||
|
const resp = await ReportsRepository.getDailyProgressByProject(projectId);
|
||||||
|
return resp.data;
|
||||||
|
},
|
||||||
|
enabled:!!projectId
|
||||||
|
})
|
||||||
|
}
|
||||||
@ -1,10 +1,10 @@
|
|||||||
.reports-container {
|
/* .reports-container {
|
||||||
margin: 20px auto;
|
margin: 20px auto;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
|
||||||
}
|
} */
|
||||||
|
|
||||||
.reports-header {
|
.reports-header {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
|||||||
@ -1,17 +1,60 @@
|
|||||||
import React from "react";
|
import React, { useState } from "react";
|
||||||
import { ComingSoonPage } from "../Misc/ComingSoonPage";
|
import { ComingSoonPage } from "../Misc/ComingSoonPage";
|
||||||
import ReportDPR from "../../components/reports/report-dpr";
|
import ReportDPR from "../../components/reports/report-dpr";
|
||||||
import "./Reports.css";
|
import "./Reports.css";
|
||||||
|
import Breadcrumb from "../../components/common/Breadcrumb";
|
||||||
|
import { useProjectName } from "../../hooks/useProjects";
|
||||||
|
import DatePicker from "../../components/common/DatePicker";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
|
||||||
const Reports = () => {
|
const Reports = () => {
|
||||||
|
const [selectedProject, setSelectedProject] = useState("");
|
||||||
|
const { projectNames, isError, loading } = useProjectName(true);
|
||||||
|
const { control, watch } = useForm({
|
||||||
|
defaultValues: {
|
||||||
|
startDate: "",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const selelectedDate = watch("startDate");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="container-fluid">
|
||||||
{" "}
|
<Breadcrumb
|
||||||
<div class="reports-header text-end">
|
data={[
|
||||||
<h1>Daily Progress Report</h1>
|
{ label: "Home", link: "/dashboard" },
|
||||||
|
{ label: "Daily Progress Report", link: null },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<div className="card my-3 px-sm-4 px-0">
|
||||||
|
<div className="card-body py-2 px-1 mx-2">
|
||||||
|
<div className="row align-items-center mb-0">
|
||||||
|
<div className="col-12 col-md-6 ">
|
||||||
|
<div className="w-max">
|
||||||
|
<select
|
||||||
|
className="form-select form-select-sm"
|
||||||
|
onChange={(e) => setSelectedProject(e.target.value)}
|
||||||
|
>
|
||||||
|
{projectNames?.map((project) => (
|
||||||
|
<option key={project.id} value={project.id}>
|
||||||
|
{project.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-12 col-md-6 d-flex justify-content-end">
|
||||||
|
<DatePicker
|
||||||
|
name="startDate"
|
||||||
|
control={control}
|
||||||
|
placeholder="Select Date"
|
||||||
|
maxDate={new Date()}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ReportDPR></ReportDPR>;
|
<ReportDPR project={selectedProject} day={selelectedDate} />
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
import { api } from "../utils/axiosClient";
|
import { api } from "../utils/axiosClient";
|
||||||
|
|
||||||
const GlobalRepository = {
|
const GlobalRepository = {
|
||||||
getDashboardProgressionData: ({ days = '', FromDate = '', projectId = '' }) => {
|
getDashboardProgressionData: ({
|
||||||
|
days = "",
|
||||||
|
FromDate = "",
|
||||||
|
projectId = "",
|
||||||
|
}) => {
|
||||||
let params;
|
let params;
|
||||||
if (projectId == null) {
|
if (projectId == null) {
|
||||||
params = new URLSearchParams({
|
params = new URLSearchParams({
|
||||||
@ -20,8 +24,9 @@ const GlobalRepository = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getDashboardAttendanceData: (date, projectId) => {
|
getDashboardAttendanceData: (date, projectId) => {
|
||||||
|
return api.get(
|
||||||
return api.get(`/api/Dashboard/project-attendance/${projectId}?date=${date}`);
|
`/api/Dashboard/project-attendance/${projectId}?date=${date}`
|
||||||
|
);
|
||||||
},
|
},
|
||||||
getDashboardProjectsCardData: () => {
|
getDashboardProjectsCardData: () => {
|
||||||
return api.get(`/api/Dashboard/projects`);
|
return api.get(`/api/Dashboard/projects`);
|
||||||
@ -42,7 +47,7 @@ const GlobalRepository = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getExpenseData: (projectId, startDate, endDate) => {
|
getExpenseData: (projectId, startDate, endDate) => {
|
||||||
let url = `api/Dashboard/expense/type`
|
let url = `api/Dashboard/expense/type`;
|
||||||
const queryParams = [];
|
const queryParams = [];
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
queryParams.push(`projectId=${projectId}`);
|
queryParams.push(`projectId=${projectId}`);
|
||||||
@ -60,10 +65,15 @@ const GlobalRepository = {
|
|||||||
return api.get(url);
|
return api.get(url);
|
||||||
},
|
},
|
||||||
|
|
||||||
getExpenseStatus: (projectId) => api.get(`/api/Dashboard/expense/pendings${projectId ? `?projectId=${projectId}` : ""}`),
|
getExpenseStatus: (projectId) =>
|
||||||
|
api.get(
|
||||||
|
`/api/Dashboard/expense/pendings${
|
||||||
|
projectId ? `?projectId=${projectId}` : ""
|
||||||
|
}`
|
||||||
|
),
|
||||||
|
|
||||||
getExpenseDataByProject: (projectId, categoryId, months) => {
|
getExpenseDataByProject: (projectId, categoryId, months) => {
|
||||||
let url = `api/Dashboard/expense/monthly`
|
let url = `api/Dashboard/expense/monthly`;
|
||||||
const queryParams = [];
|
const queryParams = [];
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
queryParams.push(`projectId=${projectId}`);
|
queryParams.push(`projectId=${projectId}`);
|
||||||
@ -80,11 +90,13 @@ const GlobalRepository = {
|
|||||||
return api.get(url);
|
return api.get(url);
|
||||||
},
|
},
|
||||||
|
|
||||||
getAttendanceOverview: (projectId, days) => api.get(`/api/dashboard/attendance-overview/${projectId}?days=${days}`)
|
getAttendanceOverview: (projectId, days) =>
|
||||||
|
api.get(`/api/dashboard/attendance-overview/${projectId}?days=${days}`),
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export default GlobalRepository;
|
export default GlobalRepository;
|
||||||
|
|
||||||
|
export const ReportsRepository = {
|
||||||
|
getDailyProgressByProject: (projectId) =>
|
||||||
|
api.get(`/api/Market/get/project/report/${projectId}`),
|
||||||
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user