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";
|
||||
|
||||
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
|
||||
const projectNames = projects?.map((p) => p.name) || [];
|
||||
const projectNames = projects?.map((p) => p.name) ?? [];
|
||||
const projectProgress =
|
||||
projects?.map((p) => {
|
||||
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 { 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 (
|
||||
<>
|
||||
{" "}
|
||||
<div class="reports-container">
|
||||
<div className="card">
|
||||
{/* <div class="reports-container"> */}
|
||||
{/* <!-- Header */}
|
||||
<div class="reports-header">
|
||||
{/* <div class="reports-header">
|
||||
<div class="d-flex flex-wrap align-items-start reports-project-info">
|
||||
<strong>Project:</strong>
|
||||
<select class="form-select" aria-label="Default select example">
|
||||
@ -390,11 +397,15 @@ const ReportDPR = () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
|
||||
{/* <!-- Status Note */}
|
||||
<div class="reports-status-note">
|
||||
{/* <div class="reports-status-note">
|
||||
* 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>
|
||||
|
||||
{/* <!-- Status Cards */}
|
||||
@ -406,14 +417,14 @@ const ReportDPR = () => {
|
||||
<div
|
||||
style={{
|
||||
width: "50%",
|
||||
boxSizing: "border-box",
|
||||
boxSizing: "bordtarter-box",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
{/* <!-- Medium */}
|
||||
<div class="reports-donut thin" style={{ percentage: "66" }}>
|
||||
<div class="reports-donut thin" style={{ percentage: 90 }}>
|
||||
<span>20 / 30</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -784,22 +795,17 @@ const ReportDPR = () => {
|
||||
<h4 class="reports-card-title">Team Strength on Site</h4>
|
||||
</div>
|
||||
<table style={{ width: "100%" }}>
|
||||
<tr>
|
||||
<td style={{ textAlign: "left" }}>Site Engineer</td>
|
||||
<td style={{ textAlign: "right" }}>1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={{ textAlign: "left" }}>Weilder</td>
|
||||
<td style={{ textAlign: "right" }}>15</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={{ textAlign: "left" }}>Helper</td>
|
||||
<td style={{ textAlign: "right" }}>2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={{ textAlign: "left" }}>Painter</td>
|
||||
<td style={{ textAlign: "right" }}>1</td>
|
||||
</tr>
|
||||
<tbody>
|
||||
{data?.teamOnSite?.map((member, index) => (
|
||||
<tr key={index}>
|
||||
<td style={{ textAlign: "left" }}>{member?.roleName}</td>
|
||||
|
||||
<td style={{ textAlign: "right" }}>
|
||||
{member?.numberofEmployees}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</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;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
} */
|
||||
|
||||
.reports-header {
|
||||
color: #fff;
|
||||
|
||||
@ -1,17 +1,60 @@
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import { ComingSoonPage } from "../Misc/ComingSoonPage";
|
||||
import ReportDPR from "../../components/reports/report-dpr";
|
||||
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 [selectedProject, setSelectedProject] = useState("");
|
||||
const { projectNames, isError, loading } = useProjectName(true);
|
||||
const { control, watch } = useForm({
|
||||
defaultValues: {
|
||||
startDate: "",
|
||||
},
|
||||
});
|
||||
const selelectedDate = watch("startDate");
|
||||
|
||||
return (
|
||||
<>
|
||||
{" "}
|
||||
<div class="reports-header text-end">
|
||||
<h1>Daily Progress Report</h1>
|
||||
<div className="container-fluid">
|
||||
<Breadcrumb
|
||||
data={[
|
||||
{ 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>
|
||||
<ReportDPR></ReportDPR>;
|
||||
</>
|
||||
<ReportDPR project={selectedProject} day={selelectedDate} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -1,7 +1,11 @@
|
||||
import { api } from "../utils/axiosClient";
|
||||
|
||||
const GlobalRepository = {
|
||||
getDashboardProgressionData: ({ days = '', FromDate = '', projectId = '' }) => {
|
||||
getDashboardProgressionData: ({
|
||||
days = "",
|
||||
FromDate = "",
|
||||
projectId = "",
|
||||
}) => {
|
||||
let params;
|
||||
if (projectId == null) {
|
||||
params = new URLSearchParams({
|
||||
@ -20,8 +24,9 @@ const GlobalRepository = {
|
||||
},
|
||||
|
||||
getDashboardAttendanceData: (date, projectId) => {
|
||||
|
||||
return api.get(`/api/Dashboard/project-attendance/${projectId}?date=${date}`);
|
||||
return api.get(
|
||||
`/api/Dashboard/project-attendance/${projectId}?date=${date}`
|
||||
);
|
||||
},
|
||||
getDashboardProjectsCardData: () => {
|
||||
return api.get(`/api/Dashboard/projects`);
|
||||
@ -42,7 +47,7 @@ const GlobalRepository = {
|
||||
},
|
||||
|
||||
getExpenseData: (projectId, startDate, endDate) => {
|
||||
let url = `api/Dashboard/expense/type`
|
||||
let url = `api/Dashboard/expense/type`;
|
||||
const queryParams = [];
|
||||
if (projectId) {
|
||||
queryParams.push(`projectId=${projectId}`);
|
||||
@ -60,10 +65,15 @@ const GlobalRepository = {
|
||||
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) => {
|
||||
let url = `api/Dashboard/expense/monthly`
|
||||
let url = `api/Dashboard/expense/monthly`;
|
||||
const queryParams = [];
|
||||
if (projectId) {
|
||||
queryParams.push(`projectId=${projectId}`);
|
||||
@ -80,11 +90,13 @@ const GlobalRepository = {
|
||||
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 const ReportsRepository = {
|
||||
getDailyProgressByProject: (projectId) =>
|
||||
api.get(`/api/Market/get/project/report/${projectId}`),
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user