239 lines
7.8 KiB
JavaScript
239 lines
7.8 KiB
JavaScript
import React, { useState,useEffect } from "react";
|
|
import { formatDate } from "../../utils/dateUtils";
|
|
import { useForm } from "react-hook-form";
|
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
import { z } from "zod";
|
|
import showToast from "../../services/toastService";
|
|
import { TasksRepository } from "../../repositories/TaskRepository";
|
|
|
|
export const ReportTask = ({ report, closeModal, refetch }) => {
|
|
const [loading, setloading] = useState(false);
|
|
|
|
const maxPending =
|
|
report?.workItem?.plannedWork - report?.workItem?.completedWork;
|
|
|
|
const schema = z.object({
|
|
completedTask: z
|
|
.preprocess(
|
|
(val) => (val === "" || val === null || Number.isNaN(val) ? undefined : Number(val)),
|
|
z
|
|
.number({
|
|
required_error: "Completed Work must be a number",
|
|
invalid_type_error: "Completed Work must be a number",
|
|
})
|
|
.min(0, "Completed Work must be greater than 0")
|
|
.max(maxPending, {
|
|
message: `Completed task cannot exceed total pending tasks: ${maxPending}`,
|
|
})
|
|
),
|
|
comment: z.string().min(1, "Comment cannot be empty"),
|
|
});
|
|
|
|
|
|
const {
|
|
register,
|
|
handleSubmit,
|
|
formState: {errors},
|
|
reset
|
|
} = useForm({
|
|
resolver: zodResolver(schema),
|
|
defaultValues: { completedTask: 0, comment: "" },
|
|
});
|
|
|
|
|
|
useEffect(() => {
|
|
if (report) {
|
|
reset({ completedTask: 0, comment: "" }); // optional: customize default if needed
|
|
}
|
|
}, [report, reset]);
|
|
|
|
|
|
const onSubmit = async (data) => {
|
|
try {
|
|
setloading(true);
|
|
const reportData = {
|
|
...data,
|
|
id: report?.id,
|
|
reportedDate: new Date().toISOString(),
|
|
checkList: [],
|
|
};
|
|
|
|
let response = await TasksRepository.reportTask(reportData);
|
|
showToast("Task Reported Successfully.", "success");
|
|
refetch();
|
|
reset()
|
|
setloading(false);
|
|
closeModal();
|
|
} catch ( error )
|
|
{
|
|
const msg = error.response.data.message || error.message || "Error Occur During Api Call"
|
|
showToast(msg, "error");
|
|
}
|
|
};
|
|
const handleClose = () => {
|
|
closeModal();
|
|
reset();
|
|
};
|
|
|
|
return (
|
|
<div
|
|
className="modal-dialog modal-md modal-simple report-task-modal"
|
|
role="document"
|
|
>
|
|
<div className="modal-content">
|
|
<div className="modal-body px-1">
|
|
<button
|
|
type="button"
|
|
className="btn-close"
|
|
onClick={handleClose}
|
|
aria-label="Close"
|
|
></button>
|
|
|
|
<div className="container m-0">
|
|
<div className="mb-1 row text-start">
|
|
<label
|
|
htmlFor="html5-text-input"
|
|
className="col-md-4 col-form-label"
|
|
>
|
|
Assigned Date :{" "}
|
|
</label>
|
|
<div className="col-md-8 text-start">
|
|
<label className="col-md-2 col-form-label">
|
|
{formatDate(report?.assignmentDate)}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div className="mb-1 row text-start">
|
|
<label
|
|
htmlFor="html5-search-input"
|
|
className="col-md-4 col-form-label"
|
|
>
|
|
Assigned By :{" "}
|
|
</label>
|
|
<div className="col-md-8 text-start">
|
|
<label className=" col-form-label">{` ${report?.assignedBy.firstName} ${report?.assignedBy.lastName}`}</label>
|
|
</div>
|
|
</div>
|
|
<div className="mb-1 row text-start">
|
|
<label
|
|
htmlFor="html5-email-input"
|
|
className="col-md-4 col-form-label"
|
|
>
|
|
Wrok Area :
|
|
</label>
|
|
<div className="col-md-8 text-start text-wrap">
|
|
<label className=" col-form-label">
|
|
{" "}
|
|
{report?.workItem?.workArea?.floor?.building?.name}{" "}
|
|
<i className="bx bx-chevron-right"></i>{" "}
|
|
{report?.workItem?.workArea?.floor?.floorName}{" "}
|
|
<i className="bx bx-chevron-right"> </i>
|
|
{report?.workItem?.workArea?.areaName}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div className="mb-1 row text-start">
|
|
<label
|
|
htmlFor="html5-email-input"
|
|
className="col-md-4 col-form-label"
|
|
>
|
|
Activity :
|
|
</label>
|
|
<div className="col-md-8 text-start text-wrap">
|
|
<label className=" col-form-label">
|
|
{report?.workItem?.activityMaster.activityName}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div className="mb-1 row text-start">
|
|
<label
|
|
htmlFor="html5-email-input"
|
|
className="col-md-4 col-form-label"
|
|
>
|
|
Team Size :
|
|
</label>
|
|
<div className="col-md-8 text-start text-wrap">
|
|
<label className=" col-form-label">
|
|
{report?.teamMembers?.length}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div className="mb-1 row text-start">
|
|
<label
|
|
htmlFor="html5-email-input"
|
|
className="col-md-4 col-form-label"
|
|
>
|
|
Assigned :
|
|
</label>
|
|
<div className="col-md-8 text-start text-wrap">
|
|
<label className=" col-form-label">
|
|
{report?.plannedTask} of{" "}
|
|
{report?.workItem.plannedWork -
|
|
report?.workItem.completedWork}{" "}
|
|
Pending
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<form onSubmit={handleSubmit(onSubmit)}>
|
|
<div className="mb-1 row text-start">
|
|
<label
|
|
htmlFor="html5-email-input"
|
|
className="col-md-4 col-form-label"
|
|
>
|
|
Completed Work
|
|
</label>
|
|
<div className="col-md-8 text-start text-wrap">
|
|
<input
|
|
{...register("completedTask", { valueAsNumber: true })}
|
|
id="smallInput"
|
|
className="form-control form-control-sm"
|
|
type="number"
|
|
placeholder="Completed Work"
|
|
/>
|
|
{errors.completedTask && (
|
|
<div className="danger-text">
|
|
{errors.completedTask.message}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
<div className="mb-1 row text-start">
|
|
<label
|
|
htmlFor="html5-email-input"
|
|
className="col-md-4 col-form-label"
|
|
>
|
|
Comment
|
|
</label>
|
|
<div className="col-md-8 text-start text-wrap">
|
|
<textarea
|
|
{...register("comment")}
|
|
className="form-control"
|
|
id="exampleFormControlTextarea1"
|
|
rows="1"
|
|
placeholder="Enter comment"
|
|
/>
|
|
{errors.comment && (
|
|
<div className="danger-text">{errors.comment.message}</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
<div className="col-12 text-center my-2">
|
|
<button type="submit" className="btn btn-sm btn-primary me-3">
|
|
{loading ? "Please wait" : "Submit Report"}
|
|
</button>
|
|
<button
|
|
type="button"
|
|
className="btn btn-sm btn-label-secondary"
|
|
onClick={handleClose}
|
|
>
|
|
Cancel
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|