Compare commits
4 Commits
main
...
dpr-report
| Author | SHA1 | Date | |
|---|---|---|---|
| b348117f05 | |||
| 1157643916 | |||
| 37212e489e | |||
| b2c0388412 |
@ -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;
|
||||
|
||||
@ -3,6 +3,7 @@ import { useController } from "react-hook-form";
|
||||
|
||||
const DatePicker = ({
|
||||
name,
|
||||
defaultDate,
|
||||
control,
|
||||
placeholder = "DD-MM-YYYY",
|
||||
className = "",
|
||||
|
||||
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;
|
||||
114
src/components/reports/Progress.jsx
Normal file
114
src/components/reports/Progress.jsx
Normal file
@ -0,0 +1,114 @@
|
||||
import React from "react";
|
||||
import Chart from "react-apexcharts";
|
||||
import { formatFigure } from "../../utils/appUtils";
|
||||
|
||||
const Progress = ({
|
||||
color = "#00aaff",
|
||||
series = 0,
|
||||
total = 0,
|
||||
height = 100,
|
||||
width = 100,
|
||||
completed =0,
|
||||
}) => {
|
||||
const options = {
|
||||
chart: {
|
||||
type: "radialBar",
|
||||
},
|
||||
colors: [color],
|
||||
plotOptions: {
|
||||
radialBar: {
|
||||
hollow: { size: "55%" },
|
||||
track: { background: "#f1f1f1" },
|
||||
dataLabels: {
|
||||
name: { show: false },
|
||||
value: {
|
||||
show: true,
|
||||
fontSize: "13px",
|
||||
color: color,
|
||||
fontWeight: 600,
|
||||
offsetY: 7,
|
||||
formatter: () => `${formatFigure(completed,{notation:"compact"})} / ${formatFigure(total,{notation:"compact"})}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
stroke: { lineCap: "round" },
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ width: "fit-content" }}>
|
||||
<Chart
|
||||
options={options}
|
||||
series={[Number(series)]}
|
||||
type="radialBar"
|
||||
height={height}
|
||||
width={width}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
export default Progress;
|
||||
|
||||
|
||||
// const Progress = ({
|
||||
// completed = 0,
|
||||
// inProgress = 0,
|
||||
// total = 100,
|
||||
// height = 140,
|
||||
// width = 140,
|
||||
// }) => {
|
||||
// const completedPercent =
|
||||
// total > 0 ? Math.round((completed / total) * 100) : 0;
|
||||
|
||||
// const progressPercent =
|
||||
// total > 0 ? Math.round((completed / total) * 100) : 0;
|
||||
|
||||
// const options = {
|
||||
// chart: {
|
||||
// type: "radialBar",
|
||||
// },
|
||||
|
||||
// colors: ["#28a745", "#0d6efd"],
|
||||
|
||||
// plotOptions: {
|
||||
// radialBar: {
|
||||
// hollow: {
|
||||
// size: "35%",
|
||||
// },
|
||||
|
||||
// track: {
|
||||
// margin: 4,
|
||||
// },
|
||||
|
||||
// dataLabels: {
|
||||
// name: { show: false },
|
||||
|
||||
// value: {
|
||||
// show: true,
|
||||
// fontSize: "14px",
|
||||
// fontWeight: 600,
|
||||
// offsetY: 5,
|
||||
// formatter: () => `${completed + inProgress}/${total}`,
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
|
||||
// labels: ["Completed", "In Progress"],
|
||||
// stroke: {
|
||||
// lineCap: "round",
|
||||
// },
|
||||
// };
|
||||
|
||||
// return (
|
||||
// <div style={{ width: "fit-content" }}>
|
||||
// <Chart
|
||||
// options={options}
|
||||
// series={[completedPercent, progressPercent]}
|
||||
// type="radialBar"
|
||||
// height={height}
|
||||
// width={width}
|
||||
// />
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
66
src/components/reports/ReportsDonutCard.jsx
Normal file
66
src/components/reports/ReportsDonutCard.jsx
Normal file
@ -0,0 +1,66 @@
|
||||
import { getCompletionPercentage } from "../../utils/dateUtils";
|
||||
import Progress from "./Progress";
|
||||
import ReportsLegend from "./ReportsLegend";
|
||||
|
||||
const ReportsDonutCard = ({
|
||||
title,
|
||||
value,
|
||||
total,
|
||||
donutClass = "",
|
||||
footer = "Team members present on the site",
|
||||
chartColor,
|
||||
}) => {
|
||||
return (
|
||||
<div className="border-top card border-primary py-4 px-2">
|
||||
<h4 className="reports-card-title">{title}</h4>
|
||||
|
||||
<div className="d-flex justify-content-center align-items-center flex-column">
|
||||
<div className="d-inline-flex flex-row align-items-center gap-12 gap-md-3">
|
||||
<Progress
|
||||
color={chartColor}
|
||||
width={120}
|
||||
height={120}
|
||||
series={getCompletionPercentage(value, total)}
|
||||
completed={value}
|
||||
total={total}
|
||||
/>
|
||||
<ReportsLegend />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-center p-2">
|
||||
<p className="text-muted mb-0">{footer}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ReportsDonutCard;
|
||||
|
||||
export const ReportsCard = ({
|
||||
title,
|
||||
value,
|
||||
total,
|
||||
donutClass = "",
|
||||
footer = "Team members present on the site",
|
||||
chartColor,
|
||||
}) => {
|
||||
return (
|
||||
<div className="border-top card border-primary py-4 px-2">
|
||||
<h4 className="reports-card-title">{title}</h4>
|
||||
|
||||
<div className="d-flex justify-content-start align-items-center flex-column">
|
||||
<div className="d-inline-flex flex-row align-items-center gap-12 gap-md-3">
|
||||
|
||||
<ReportsLegend />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-center p-2">
|
||||
<p className="text-muted mb-0">{footer}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
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=" d-inline-flex flex-column text-start gap-2 pe-5">
|
||||
<div className=" d-flex align-items-center gap-2">
|
||||
<span className="reports-legend-color reports-legend-green"></span>
|
||||
<span>Completed</span>
|
||||
</div>
|
||||
|
||||
<div className=" d-flex align-items-center gap-2">
|
||||
<span className="reports-legend-color reports-legend-blue"></span>
|
||||
<span>In Progress</span>
|
||||
</div>
|
||||
|
||||
<div className=" d-flex align-items-center gap-2">
|
||||
<span className="reports-legend-color reports-legend-gray"></span>
|
||||
<span>Pending</span>
|
||||
</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;
|
||||
121
src/components/reports/report-dpr.jsx
Normal file
121
src/components/reports/report-dpr.jsx
Normal file
@ -0,0 +1,121 @@
|
||||
import React from "react";
|
||||
import { useProjectReportByProject } from "../../hooks/useReports";
|
||||
import Progress from "./Progress";
|
||||
import { formatUTCToLocalTime } from "../../utils/dateUtils";
|
||||
import { localToUtc } from "../../utils/appUtils";
|
||||
import ReportsDonutCard, { ReportsCard } from "./ReportsDonutCard";
|
||||
|
||||
const ReportDPR = ({ project, date }) => {
|
||||
const { data, isLoading, isError, error } = useProjectReportByProject(
|
||||
project,
|
||||
localToUtc(date)
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<div className="card">
|
||||
<div className="d-flex text-start px-2 mt-2">
|
||||
Project Status Reported - Generated at{" "}
|
||||
{formatUTCToLocalTime(data?.date, true)}
|
||||
</div>
|
||||
|
||||
{/* <!-- Status Cards */}
|
||||
<div className="d-flex justify-content-between flex-wrap gap-5 px-3 py-2">
|
||||
<ReportsDonutCard
|
||||
title={"TODAY'S ATTENDANCE"}
|
||||
total={data?.totalEmployees}
|
||||
value={data?.todaysAttendances}
|
||||
/>
|
||||
<ReportsDonutCard
|
||||
title={"DAILY TASKS COMPLETED"}
|
||||
total={data?.totalCompletedTask}
|
||||
value={data?.totalPlannedWork}
|
||||
chartColor={"blue"}
|
||||
/>
|
||||
|
||||
<ReportsDonutCard
|
||||
title={"PROJECT COMPLETION STATUS"}
|
||||
total={data?.totalPlannedWork}
|
||||
value={data?.totalCompletedWork}
|
||||
chartColor={"green"}
|
||||
/>
|
||||
|
||||
<div class="card px-3 border-top border-warning">
|
||||
<h4 class="reports-card-title">Attendance Pending Report</h4>
|
||||
<p>Team member present</p>
|
||||
<div className="d-flex flex-column gap-2">
|
||||
<div className="d-flex justify-content-between">
|
||||
<span className="text-secondry"> Regualrization</span>{" "}
|
||||
<span className="text-secondry">
|
||||
{" "}
|
||||
{data?.regularizationPending}
|
||||
</span>{" "}
|
||||
</div>
|
||||
<div className="d-flex justify-content-between">
|
||||
<span className="text-secondry"> Checking</span>{" "}
|
||||
<span className="text-secondry"> {data?.checkoutPending}</span>{" "}
|
||||
</div>
|
||||
<div className="d-flex justify-content-between">
|
||||
<span className="text-secondry"> Total Employee</span>{" "}
|
||||
<span className="text-secondry">
|
||||
{" "}
|
||||
{ data?.todaysAttendances}
|
||||
</span>{" "}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="reports-card">
|
||||
{/* {/* <!-- Row 1: Header */}
|
||||
<div>
|
||||
<h4 class="reports-card-title">Team Strength on Site</h4>
|
||||
</div>
|
||||
<table style={{ width: "100%" }}>
|
||||
<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>
|
||||
|
||||
{/* {/* <!-- Activities */}
|
||||
<div className="reports-activities">
|
||||
<h2>Activities (Tasks) Performed 17-Sep-2025</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>
|
||||
{data?.performedAttendance?.map((att) => (
|
||||
<tr>
|
||||
<td>{att.name}</td>
|
||||
<td>{att.roleName}</td>
|
||||
<td>{formatUTCToLocalTime(att.inTime, true)}</td>
|
||||
<td>
|
||||
{att.outTime
|
||||
? formatUTCToLocalTime(att.outTime, true)
|
||||
: "--"}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ReportDPR;
|
||||
16
src/hooks/useReports.js
Normal file
16
src/hooks/useReports.js
Normal file
@ -0,0 +1,16 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { ReportsRepository } from "../repositories/GlobalRepository";
|
||||
|
||||
export const useProjectReportByProject = (projectId, date) => {
|
||||
return useQuery({
|
||||
queryKey: ["daily_report", projectId, date],
|
||||
queryFn: async () => {
|
||||
const resp = await ReportsRepository.getDailyProgressByProject(
|
||||
projectId,
|
||||
date
|
||||
);
|
||||
return resp.data;
|
||||
},
|
||||
enabled: !!projectId && !!date,
|
||||
});
|
||||
};
|
||||
282
src/pages/reports/Reports.css
Normal file
282
src/pages/reports/Reports.css
Normal file
@ -0,0 +1,282 @@
|
||||
/* .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;
|
||||
padding: 20px;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.reports-header h1 {
|
||||
font-size: 22px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.reports-header .project-info {
|
||||
font-size: 14px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.reports-status-note {
|
||||
font-size: 12px;
|
||||
color: #555;
|
||||
padding: 15px 20px 0 20px;
|
||||
}
|
||||
|
||||
.reports-status-cards {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 15px;
|
||||
padding: 20px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.reports-card {
|
||||
flex: 1;
|
||||
min-width: 200px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
text-align: center;
|
||||
background: #fff;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
|
||||
/* <-- added shadow */
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
border-top: 1px solid #e63946;
|
||||
}
|
||||
|
||||
.reports-card:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.reports-card h3 {
|
||||
font-size: 14px;
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
|
||||
.reports-card p {
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.reports-card .value {
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.reports-card-title {
|
||||
font-size: 0.9rem;
|
||||
text-transform: uppercase;
|
||||
font-weight: 600;
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
.reports-attendance {
|
||||
color: #b10000;
|
||||
}
|
||||
|
||||
.reports-tasks {
|
||||
color: #007bff;
|
||||
}
|
||||
|
||||
.reports-completion {
|
||||
color: #28a745;
|
||||
}
|
||||
|
||||
.reports-activities {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.reports-activities h2 {
|
||||
font-size: 18px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.reports-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.reports-table th,
|
||||
.reports-table td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.reports-table th {
|
||||
background: #f0f0f0;
|
||||
}
|
||||
|
||||
/* .footer {
|
||||
background: #b10000;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
padding: 15px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.footer a {
|
||||
color: #fff;
|
||||
margin: 0 8px;
|
||||
text-decoration: none;
|
||||
} */
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 600px) {
|
||||
.reports-header {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.reports-header .reports-project-info {
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.reports-status-cards {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.reports-legend {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
font-size: 12px;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.reports-legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.reports-legend-color {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 2px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.reports-legend-red {
|
||||
background: #b10000;
|
||||
}
|
||||
|
||||
.reports-legend-blue {
|
||||
background: #007bff;
|
||||
}
|
||||
|
||||
.reports-legend-green {
|
||||
background: #28a745;
|
||||
}
|
||||
|
||||
.reports-legend-gray {
|
||||
background: #ccc;
|
||||
}
|
||||
|
||||
.reports-donut {
|
||||
--percentage: 65;
|
||||
/* Change this per chart */
|
||||
--danger: #e63946;
|
||||
--primary: #007bff;
|
||||
--warning: #ffc107;
|
||||
--success: #198754;
|
||||
/* Fill color */
|
||||
--track: #e9ecef;
|
||||
/* Background track */
|
||||
--size: 120px;
|
||||
/* Default size */
|
||||
--thickness: 20px;
|
||||
/* Default thickness */
|
||||
|
||||
width: var(--size);
|
||||
height: var(--size);
|
||||
border-radius: 50%;
|
||||
background: conic-gradient(
|
||||
var(--danger) calc(var(--percentage) * 1%),
|
||||
var(--track) 0
|
||||
);
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: Arial, sans-serif;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.reports-donut::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: calc(var(--size) - var(--thickness));
|
||||
height: calc(var(--size) - var(--thickness));
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
/* Inner cut-out */
|
||||
}
|
||||
|
||||
.reports-donut span {
|
||||
position: absolute;
|
||||
font-size: calc(var(--size) / 6);
|
||||
}
|
||||
|
||||
/* Variants */
|
||||
.reports-donut.thin {
|
||||
--size: 80px;
|
||||
--thickness: 12px;
|
||||
}
|
||||
|
||||
.reports-donut.medium {
|
||||
--size: 120px;
|
||||
--thickness: 25px;
|
||||
}
|
||||
|
||||
.reports-donut.large {
|
||||
--size: 180px;
|
||||
--thickness: 35px;
|
||||
}
|
||||
|
||||
/* Color variants */
|
||||
.reports-donut-success {
|
||||
background: conic-gradient(
|
||||
var(--success) calc(var(--percentage) * 1%),
|
||||
var(--track) 0
|
||||
);
|
||||
color: var(--success);
|
||||
}
|
||||
|
||||
.reports-donut-warning {
|
||||
background: conic-gradient(
|
||||
var(--warning) calc(var(--percentage) * 1%),
|
||||
var(--track) 0
|
||||
);
|
||||
color: var(--warning);
|
||||
}
|
||||
|
||||
.reports-donut-danger {
|
||||
background: conic-gradient(
|
||||
var(--danger) calc(var(--percentage) * 1%),
|
||||
var(--track) 0
|
||||
);
|
||||
color: var(--danger);
|
||||
}
|
||||
|
||||
.reports-donut-primary {
|
||||
background: conic-gradient(
|
||||
var(--primary) calc(var(--percentage) * 1%),
|
||||
var(--track) 0
|
||||
);
|
||||
color: var(--primary);
|
||||
}
|
||||
@ -1,8 +1,69 @@
|
||||
import React from "react";
|
||||
import React, { useEffect, 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 = () => {
|
||||
return <ComingSoonPage></ComingSoonPage>;
|
||||
const [selectedProject, setSelectedProject] = useState();
|
||||
const { projectNames, isError, loading } = useProjectName(true);
|
||||
const yesterday = new Date();
|
||||
yesterday.setDate(yesterday.getDate() - 1);
|
||||
const { control, watch } = useForm({
|
||||
defaultValues: {
|
||||
startDate: yesterday.toISOString().split("T")[0],
|
||||
},
|
||||
});
|
||||
const selelectedDate = watch("startDate");
|
||||
|
||||
|
||||
useEffect(()=>{
|
||||
if(!selectedProject && projectNames){
|
||||
setSelectedProject(projectNames[0]?.id)
|
||||
}
|
||||
},[projectNames])
|
||||
return (
|
||||
<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 project={selectedProject} date={selelectedDate} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Reports;
|
||||
|
||||
@ -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,date) =>
|
||||
api.get(`/api/Market/get/project/report/${projectId}?date=${date}`),
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user