implement partial react-query in task assignment flow

This commit is contained in:
Pramod Mahajan 2025-06-30 20:20:52 +05:30
parent 7fbbe98373
commit f848f97d87
9 changed files with 601 additions and 472 deletions

View File

@ -21,17 +21,13 @@ const InfraPlanning = () =>
{
const {profile: LoggedUser, refetch : fetchData} = useProfile()
const dispatch = useDispatch()
const {projects,loading:project_listLoader,error:projects_error} = useProjects()
// const {projects,loading:project_listLoader,error:projects_error} = useProjects()
const selectedProject = useSelector((store)=>store.localVariables.projectId)
const ManageInfra = useHasUserPermission( MANAGE_PROJECT_INFRA )
const {projects_Details, loading: project_deatilsLoader, error: project_error,refetch} = useProjectDetails( selectedProject )
const reloadedData = useSelector( ( store ) => store.localVariables.reload )
// useEffect( () =>
// {
// dispatch(setProjectId(projects[0]?.id))
// }, [ projects ] )
useEffect( () =>
{
@ -48,24 +44,6 @@ const InfraPlanning = () =>
<div className="card">
<div className="card-body" style={{ padding: "0.5rem" }}>
<div className="align-items-center">
{/* <div className="row ">
<div className="col-sm-3 col-8 text-start mb-1">
<select name="DataTables_Table_0_length"
aria-controls="DataTables_Table_0"
className="form-select form-select-sm"
value={selectedProject}
onChange={(e)=>dispatch(setProjectId(e.target.value))}
aria-label=""
>
{(project_listLoader || projects.length < 0) && <option value="Loading..." disabled>Loading...</option> }
{!project_listLoader && projects?.map((project)=>(
<option key={project.id} value={project.id}>{project.name}</option>
))}
</select>
</div>
</div> */}
<div className="row ">
{project_deatilsLoader && ( <p>Loading...</p> )}
{( !project_deatilsLoader && projects_Details?.buildings.length === 0 ) && ( <p>No Result Found</p> )}

View File

@ -5,9 +5,21 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import showToast from "../../services/toastService";
import { TasksRepository } from "../../repositories/TaskRepository";
import {useReportTask} from "../../hooks/useTasks";
export const ReportTask = ({ report, closeModal, refetch }) => {
const [loading, setloading] = useState(false);
export const ReportTask = ({ report, closeModal }) => {
const [ loading, setloading ] = useState( false );
const { mutate: reportTask, isPending } = useReportTask({
onSuccessCallback: () => {
// refetch();
reset();
setloading(false);
closeModal();
},
onErrorCallback: () => {
setloading(false);
},
} );
const maxPending =
report?.workItem?.plannedWork - report?.workItem?.completedWork;
@ -43,33 +55,45 @@ export const ReportTask = ({ report, closeModal, refetch }) => {
useEffect(() => {
if (report) {
reset({ completedTask: 0, comment: "" }); // optional: customize default if needed
reset({ completedTask: 0, comment: "" });
}
}, [report, reset]);
const onSubmit = async (data) => {
try {
setloading(true);
const reportData = {
...data,
id: report?.id,
reportedDate: new Date().toISOString(),
checkList: [],
};
// 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");
}
// 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 onSubmit = (data) => {
setloading(true);
const reportData = {
...data,
id: report?.id,
reportedDate: new Date().toISOString(),
checkList: [],
};
reportTask(reportData);
};
const handleClose = () => {
closeModal();
reset();

View File

@ -9,7 +9,7 @@ import Avatar from "../common/Avatar";
import { getBgClassFromHash } from "../../utils/projectStatus";
import { cacheData, getCachedData } from "../../slices/apiDataManager";
import ImagePreview from "../common/ImagePreview";
import { useAuditStatus } from "../../hooks/useTasks";
import { useAuditStatus, useSubmitTaskComment } from "../../hooks/useTasks";
const ReportTaskComments = ({
commentsData,
@ -48,7 +48,18 @@ const ReportTaskComments = ({
const [loading, setloading] = useState(false);
const [comments, setComment] = useState([]);
const { status, loading: auditStatusLoading } = useAuditStatus();
const [IsNeededSubTask, setIsNeededSubTask] = useState(false);
const [ IsNeededSubTask, setIsNeededSubTask ] = useState( false );
const { submitComment, isPending } = useSubmitTaskComment({
actionAllow,
onSuccessCallback: (data) => {
setComment((prev) => [...prev, data]);
reset();
if ( actionAllow )
{
handleCloseAction(IsNeededSubTask);
}
},
});
const {
watch,
@ -88,70 +99,73 @@ const ReportTaskComments = ({
}
}, [comments]);
const onSubmit = async (data) => {
let payload = {
...data,
[actionAllow ? "id" : "taskAllocationId"]: commentsData?.id,
...(actionAllow ? {} : { commentDate: new Date().toISOString() }),
};
// const onSubmit = async (data) => {
// let payload = {
// ...data,
// [actionAllow ? "id" : "taskAllocationId"]: commentsData?.id,
// ...(actionAllow ? {} : { commentDate: new Date().toISOString() }),
// };
try {
setloading(true);
const resp = actionAllow
? await TasksRepository.auditTask(payload)
: await TasksRepository.taskComments(payload);
// try {
// setloading(true);
// const resp = actionAllow
// ? await TasksRepository.auditTask(payload)
// : await TasksRepository.taskComments(payload);
setComment((prevItems) => [...prevItems, resp.data]);
// setComment((prevItems) => [...prevItems, resp.data]);
const taskList = getCachedData("taskList");
// const taskList = getCachedData("taskList");
if (actionAllow) {
handleCloseAction(IsNeededSubTask);
showToast(
"Review submitted successfully. Record has been updated.",
"success"
);
} else {
if (taskList && taskList.data) {
const updatedTaskList = taskList.data.map((task) => {
if (task.id === resp.data.taskAllocationId) {
const existingComments = Array.isArray(task.comments)
? task.comments
: [];
return {
...task,
comments: [...existingComments, resp.data],
};
}
return task;
});
// if (actionAllow) {
// handleCloseAction(IsNeededSubTask);
// showToast(
// "Review submitted successfully. Record has been updated.",
// "success"
// );
// } else {
// if (taskList && taskList.data) {
// const updatedTaskList = taskList.data.map((task) => {
// if (task.id === resp.data.taskAllocationId) {
// const existingComments = Array.isArray(task.comments)
// ? task.comments
// : [];
// return {
// ...task,
// comments: [...existingComments, resp.data],
// };
// }
// return task;
// });
cacheData("taskList", {
data: updatedTaskList,
projectId: taskList.projectId,
});
}
showToast("Successfully Sent", "success");
}
// cacheData("taskList", {
// data: updatedTaskList,
// projectId: taskList.projectId,
// });
// }
// showToast("Successfully Sent", "success");
// }
reset();
setloading(false);
} catch (error) {
setloading(false);
showToast(
error.response.data?.message || "Something went wrong",
"error"
);
}
// reset();
// setloading(false);
// } catch (error) {
// setloading(false);
// showToast(
// error.response.data?.message || "Something went wrong",
// "error"
// );
// }
// };
const onSubmit = (formData) => {
submitComment({ data: formData, commentsData });
};
const selectedAuditStatus = watch("workStatus");
useEffect(() => {
reset({
approvedTask: defaultCompletedTask || 0,
});
}, [ defaultCompletedTask ] );
}, [defaultCompletedTask]);
return (
<div className="p-2 p-sm-1">
<div className="modal-body p-sm-4 p-0">
@ -234,7 +248,6 @@ const ReportTaskComments = ({
</div>
</div>
<div className="d-flex align-items-center flex-wrap">
<p className="fw-bold text-start m-0 me-1">
<i className="fa-solid me-2 fs-6 fa-users-gear"></i>Team :
@ -260,49 +273,49 @@ const ReportTaskComments = ({
<div className="fw-normal ms-2">{commentsData?.description}</div>
</div>
{commentsData?.approvedBy && (
<>
<hr className="my-1"/>
<div className="row">
<div className="col-12 col-sm-6">
{commentsData.approvedBy && (
<div className="fw-bold text-start d-flex align-items-center">
<i className="bx bx-user-check bx-lg me-1"></i>
<span className="me-2">Approved By:</span>
<div className="d-flex align-items-center fw-normal">
<Avatar
firstName={commentsData.approvedBy.firstName}
lastName={commentsData.approvedBy.lastName}
size="xs"
className="me-1"
/>
{commentsData.approvedBy.firstName +
" " +
commentsData.approvedBy.lastName}
</div>
<hr className="my-1" />
<div className="row">
<div className="col-12 col-sm-6">
{commentsData.approvedBy && (
<div className="fw-bold text-start d-flex align-items-center">
<i className="bx bx-user-check bx-lg me-1"></i>
<span className="me-2">Approved By:</span>
<div className="d-flex align-items-center fw-normal">
<Avatar
firstName={commentsData.approvedBy.firstName}
lastName={commentsData.approvedBy.lastName}
size="xs"
className="me-1"
/>
{commentsData.approvedBy.firstName +
" " +
commentsData.approvedBy.lastName}
</div>
</div>
)}
</div>
)}
</div>
<div className="col-12 col-sm-6">
{commentsData?.workStatus != null && (
<div className="fw-bold my-2 text-start d-flex align-items-center">
<i className="bx bx-time-five me-2"></i>
<span className="me-2">Work Status :</span>
<span className="fw-normal">
{commentsData?.workStatus.name}
{/* {commentsData?.} */}
</span>
<div className="col-12 col-sm-6">
{commentsData?.workStatus != null && (
<div className="fw-bold my-2 text-start d-flex align-items-center">
<i className="bx bx-time-five me-2"></i>
<span className="me-2">Work Status :</span>
<span className="fw-normal">
{commentsData?.workStatus.name}
{/* {commentsData?.} */}
</span>
</div>
)}
</div>
)}
</div>
</div>
<div className="col-12 d-flex">
<span className="fw-bold">Total Approved : </span><span className="ms-2">{commentsData?.completedTask }</span>
</div>
</> )}
<div className="col-12 d-flex">
<span className="fw-bold">Total Approved : </span>
<span className="ms-2">{commentsData?.completedTask}</span>
</div>
</>
)}
{commentsData?.reportedPreSignedUrls?.length > 0 && (
<>
@ -319,54 +332,53 @@ const ReportTaskComments = ({
)}
<form onSubmit={handleSubmit(onSubmit)} className="text-start">
{( actionAllow && !commentsData.approvedBy ) && (
{actionAllow && !commentsData.approvedBy && (
<>
<div className="row align-items-end my-1">
<div className="col-6 col-sm-4 text-start">
<label>Completed</label>
<input
className="form-control form-control-sm"
{...register("approvedTask")}
type="number"
/>
{errors.approvedTask && (
<p className="danger-text m-0">
{errors.approvedTask.message}
</p>
)}
</div>
<div className="col-6 col-sm-4 text-center align-items-end m-0">
<label htmlFor="workStatus" className="form-label">
Audit Status
</label>
<select
id="workStatus"
className={`form-select form-select-sm`}
{...register("workStatus")}
defaultValue=""
onChange={(e) => setValue("workStatus", e.target.value)}
>
<option value="" disabled>
Select Status
</option>
{auditStatusLoading ? (
<option disabled>Loading...</option>
) : (
status.map((stat) => (
<option key={stat.id} value={stat.id}>
{stat.name}
</option>
))
<div className="row align-items-end my-1">
<div className="col-6 col-sm-4 text-start">
<label>Completed</label>
<input
className="form-control form-control-sm"
{...register("approvedTask")}
type="number"
/>
{errors.approvedTask && (
<p className="danger-text m-0">
{errors.approvedTask.message}
</p>
)}
</select>
{errors.workStatus && (
<div className="danger-text">
{errors.workStatus.message}
</div>
)}
</div>
<div className="col-6 col-sm-4 text-center align-items-end m-0">
<label htmlFor="workStatus" className="form-label">
Audit Status
</label>
<select
id="workStatus"
className={`form-select form-select-sm`}
{...register("workStatus")}
defaultValue=""
onChange={(e) => setValue("workStatus", e.target.value)}
>
<option value="" disabled>
Select Status
</option>
{auditStatusLoading ? (
<option disabled>Loading...</option>
) : (
status.map((stat) => (
<option key={stat.id} value={stat.id}>
{stat.name}
</option>
))
)}
</select>
{errors.workStatus && (
<div className="danger-text">
{errors.workStatus.message}
</div>
)}
</div>
</div>
</div>
</>
)}
<i className="bx bx-comment-detail me-2"></i>
@ -382,10 +394,16 @@ const ReportTaskComments = ({
)}
<div
className={` ${
(actionAllow && !commentsData.approvedBy)? " d-flex justify-content-between" : "text-end"
actionAllow && !commentsData.approvedBy
? " d-flex justify-content-between"
: "text-end"
} mt-2`}
>
<div className={`form-check ${!(actionAllow && !commentsData.approvedBy) && "d-none"} `}>
<div
className={`form-check ${
!(actionAllow && !commentsData.approvedBy) && "d-none"
} `}
>
<input
className="form-check-input"
type="checkbox"

View File

@ -120,10 +120,10 @@ const Header = () => {
[fetchData,projectNames,selectedProject]
);
useEffect(() => {
eventBus.on("assign_project_one", handler);
return () => eventBus.off("assign_project_one", handler);
}, [handler]);
// useEffect(() => {
// eventBus.on("assign_project_one", handler);
// return () => eventBus.off("assign_project_one", handler);
// }, [handler]);
const newProjectHandler = useCallback(
async (msg) => {
@ -139,10 +139,23 @@ const Header = () => {
[HasManageProjectPermission,projectNames]
);
// useEffect(() => {
// eventBus.on("project", newProjectHandler);
// return () => eventBus.off("project", newProjectHandler);
// }, [handler]);
useEffect(() => {
eventBus.on("project", newProjectHandler);
return () => eventBus.off("project", newProjectHandler);
}, [handler]);
eventBus.on("assign_project_one", handler);
eventBus.on("project", newProjectHandler);
return () => {
eventBus.off("assign_project_one", handler);
eventBus.off("project", newProjectHandler);
};
}, [handler, newProjectHandler]);
return (
<nav
className="layout-navbar container-xxl navbar navbar-expand-xl navbar-detached align-items-center bg-navbar-theme"

View File

@ -11,6 +11,7 @@ import { TasksRepository } from "../../repositories/ProjectRepository";
import showToast from "../../services/toastService";
import { useProjectDetails } from "../../hooks/useProjects";
import eventBus from "../../services/eventBus";
import { useCreateTask } from "../../hooks/useTasks";
const AssignTask = ({ assignData, onClose, setAssigned }) => {
const maxPlanned =
@ -41,9 +42,12 @@ const AssignTask = ({ assignData, onClose, setAssigned }) => {
const [isHelpVisibleTarget, setIsHelpVisibleTarget] = useState(false);
const helpPopupRefTarget = useRef(null);
const [isHelpVisible, setIsHelpVisible] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const { mutate: assignTask, isPending: isSubmitting } = useCreateTask({
onSuccessCallback: () => {
closedModel();
},
});
// Refs for Bootstrap Popovers
const infoRef = useRef(null);
const infoRef1 = useRef(null);
@ -149,34 +153,49 @@ const AssignTask = ({ assignData, onClose, setAssigned }) => {
);
// Form submission handler
const onSubmit = async (data) => {
const selectedEmployeeIds = data.selectedEmployees;
setIsSubmitting(true);
// Prepare taskTeam data (only IDs are needed for the backend based on previous context)
const taskTeamWithDetails = selectedEmployeeIds
.map((empId) => {
return empId; // Return just the ID as per previous discussions
})
.filter(Boolean); // Ensure no nulls if employee not found (though unlikely with current logic)
// const onSubmit = async (data) => {
// const selectedEmployeeIds = data.selectedEmployees;
// setIsSubmitting(true);
// // Prepare taskTeam data (only IDs are needed for the backend based on previous context)
// const taskTeamWithDetails = selectedEmployeeIds
// .map((empId) => {
// return empId; // Return just the ID as per previous discussions
// })
// .filter(Boolean); // Ensure no nulls if employee not found (though unlikely with current logic)
// Format data for API call
// // Format data for API call
// const formattedData = {
// taskTeam: taskTeamWithDetails,
// plannedTask: data.plannedTask,
// description: data.description,
// assignmentDate: new Date().toISOString(), // Current date/time
// workItemId: assignData?.workItem?.workItem.id,
// };
// try {
// await TasksRepository.assignTask(formattedData);
// setIsSubmitting( false );
// showToast("Task Assined Successfully.", "success");
// closedModel();
// } catch (error) {
// setIsSubmitting(false);
// showToast("Something went wrong. Please try again.", "error");
// }
// };
const onSubmit = (data) => {
const selectedEmployeeIds = data.selectedEmployees;
const taskTeamWithDetails = selectedEmployeeIds?.map((empId) => empId)?.filter(Boolean);
const formattedData = {
taskTeam: taskTeamWithDetails,
plannedTask: data.plannedTask,
description: data.description,
assignmentDate: new Date().toISOString(), // Current date/time
assignmentDate: new Date().toISOString(),
workItemId: assignData?.workItem?.workItem.id,
};
try {
await TasksRepository.assignTask(formattedData);
setIsSubmitting( false );
showToast("Task Assined Successfully.", "success");
closedModel();
} catch (error) {
setIsSubmitting(false);
showToast("Something went wrong. Please try again.", "error");
}
assignTask(formattedData);
};
// Handler to close the modal and reset form

View File

@ -2,103 +2,282 @@ import { useEffect, useState } from "react";
import { TasksRepository } from "../repositories/TaskRepository";
import { cacheData, getCachedData } from "../slices/apiDataManager";
import {MasterRespository} from "../repositories/MastersRepository";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import showToast from "../services/toastService";
import {useSelector} from "react-redux";
// import {formatDate} from "../utils/dateUtils";
// export const useTaskList = (projectId, dateFrom, toDate) => {
// const [TaskList, setTaskList] = useState([]);
// const [loading, setLoading] = useState(false);
// const [error, setError] = useState(null);
// const fetchList = async (projectId, dateFrom, toDate) => {
// const taskList_cached = getCachedData("taskList");
// // if (!taskList_cached || taskList_cached?.projectId !== projectId) {
// try {
// setLoading(true);
// const resp = await TasksRepository.getTaskList(
// projectId,
// dateFrom,
// toDate
// );
// setTaskList(resp.data);
// cacheData("taskList", { projectId: projectId, data: resp.data });
// setLoading(false);
// } catch (err) {
// setLoading(false);
// setError(err);
// }
// // } else {
// // setTaskList(taskList_cached.data);
// // }
// };
// useEffect( () =>
// {
// if (projectId && dateFrom && toDate) {
// fetchList(projectId, dateFrom, toDate);
// }
// }, [projectId, dateFrom, toDate]);
// return { TaskList, loading, error, refetch:fetchList};
// };
// export const useTaskById = (TaskId) =>
// {
// const [Task, setTask] = useState([]);
// const [loading, setLoading] = useState(false);
// const [ error, setError ] = useState( null );
// const fetchTask = async(TaskId) =>
// {
// try
// {
// let res = await TasksRepository.getTaskById( TaskId );
// setTask( res.data );
// } catch ( error )
// {
// setError(err)
// }
// }
// useEffect( () =>
// {
// if ( TaskId )
// {
// fetchTask(TaskId)
// }
// }, [ TaskId ] )
// return { Task,loading}
// }
// export const useAuditStatus = () =>
// {
// const [ status, setStatus ] = useState( [] );
// const [ error, setError ] = useState( '' );
// const [ loading, setLoading ] = useState( false )
// const fetchStatus = async() =>
// {
// try
// {
// const res = await MasterRespository.getAuditStatus()
// setStatus( res.data )
// cacheData("AuditStatus",res.data)
// } catch ( err )
// {
// setError(err)
// }
// }
// useEffect(() => {
// const cache_status = getCachedData('AuditStatus');
// if (cache_status) {
// setStatus(cache_status);
// } else {
// fetchStatus();
// }
// }, []);
// return {status,error,loading}
// }
// ---------Query---------------------------------
export const useTaskList = (projectId, dateFrom, toDate) => {
const [TaskList, setTaskList] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const enabled = !!projectId && !!dateFrom && !!toDate;
const fetchList = async (projectId, dateFrom, toDate) => {
const taskList_cached = getCachedData("taskList");
// if (!taskList_cached || taskList_cached?.projectId !== projectId) {
try {
setLoading(true);
const resp = await TasksRepository.getTaskList(
projectId,
dateFrom,
toDate
);
setTaskList(resp.data);
cacheData("taskList", { projectId: projectId, data: resp.data });
setLoading(false);
} catch (err) {
setLoading(false);
setError(err);
}
// } else {
// setTaskList(taskList_cached.data);
// }
};
useEffect( () =>
{
const {
data: TaskList = [],
isLoading: loading,
error,
refetch,
} = useQuery({
queryKey: ["taskList", projectId, dateFrom, toDate],
queryFn: async () => {
const response = await TasksRepository.getTaskList(
projectId,
dateFrom,
toDate
);
return response.data;
},
enabled,
if (projectId && dateFrom && toDate) {
fetchList(projectId, dateFrom, toDate);
}
});
}, [projectId, dateFrom, toDate]);
return { TaskList, loading, error, refetch };
};
return { TaskList, loading, error, refetch:fetchList};
export const useTaskById = (TaskId) => {
const {
data: Task = null,
isLoading: loading,
error,
refetch,
} = useQuery({
queryKey: ["taskDetails", TaskId],
queryFn: async () => {
const res = await TasksRepository.getTaskById(TaskId);
return res.data;
},
enabled: !!TaskId,
});
return { Task, loading, error, refetch };
};
// export const useActivities = () => {
// return useQuery({
// queryKey: ["activitiesMaster"],
// queryFn: async () => {
// const response = await ActivityRepository.getActivities();
// return response.data;
// },
// });
// };
export const useAuditStatus = () => {
const {
data: status = [],
isLoading: loading,
error,
refetch,
} = useQuery({
queryKey: ["AuditStatus"],
queryFn: async () => {
const res = await MasterRespository.getAuditStatus();
return res.data;
},
});
return { status, loading, error, refetch };
};
export const useTaskById = (TaskId) =>
// -----------------------Mutation------------------------
const toDate = new Date().toISOString().split('T')[0];
const dateFrom = new Date(Date.now() - 6 * 24 * 60 * 60 * 1000).toISOString().split('T')[0];
export const useReportTask = ( {onSuccessCallback, onErrorCallback} = {} ) =>
{
const [Task, setTask] = useState([]);
const [loading, setLoading] = useState(false);
const [ error, setError ] = useState( null );
const queryClient = useQueryClient();
const {
mutate,
isPending,
isSuccess,
isError,
error,
} = useMutation({
mutationFn: async (reportData) => {
return await TasksRepository.reportTask(reportData);
},
onSuccess: (data) => {
showToast( "Task Reported Successfully.", "success" );
queryClient.invalidateQueries({ queryKey: ["taskList"] });
if (onSuccessCallback) onSuccessCallback(data);
},
onError: (error) => {
const msg =
error?.response?.data?.message || error.message || "Error occurred during API call";
showToast( msg, "error" );
if (onErrorCallback) onErrorCallback(error);
},
});
return {
mutate,
isPending,
isSuccess,
isError,
error,
};
};
export const useSubmitTaskComment = ({ actionAllow, onSuccessCallback }) => {
const queryClient = useQueryClient();
const { mutate, isPending } = useMutation({
mutationFn: async ({ data, commentsData }) => {
const payload = {
...data,
[actionAllow ? "id" : "taskAllocationId"]: commentsData?.id,
...(actionAllow ? {} : { commentDate: new Date().toISOString() }),
};
const fetchTask = async(TaskId) =>
{
try
const response = actionAllow
? await TasksRepository.auditTask(payload)
: await TasksRepository.taskComments(payload);
return response.data;
},
onSuccess: ( data ) =>
{
let res = await TasksRepository.getTaskById( TaskId );
setTask( res.data );
queryClient.invalidateQueries({ queryKey: ["taskList"] });
if (actionAllow) {
showToast("Review submitted successfully.", "success");
} else
{
showToast("Comment sent successfully.", "success");
}
} catch ( error )
{
setError(err)
}
}
useEffect( () =>
{
if ( TaskId )
{
fetchTask(TaskId)
}
}, [ TaskId ] )
return { Task,loading}
}
onSuccessCallback?.(data);
},
export const useAuditStatus = () =>
onError: (error) => {
const msg = error?.response?.data?.message || error.message || "Error during API call";
showToast(msg, "error");
},
});
return { submitComment: mutate, isPending };
};
export const useCreateTask = ( {onSuccessCallback, onErrorCallback} = {} ) =>
{
const [ status, setStatus ] = useState( [] );
const [ error, setError ] = useState( '' );
const [ loading, setLoading ] = useState( false )
const fetchStatus = async() =>
{
try
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (payload) => {
return await TasksRepository.assignTask(payload);
},
onSuccess: ( _, variables ) =>
{
const res = await MasterRespository.getAuditStatus()
setStatus( res.data )
cacheData("AuditStatus",res.data)
} catch ( err )
queryClient.invalidateQueries({ queryKey: ["taskList"] });
showToast("Task Assigned Successfully.", "success");
if (onSuccessCallback) onSuccessCallback(variables);
},
onError: ( error ) =>
{
setError(err)
}
}
useEffect(() => {
const cache_status = getCachedData('AuditStatus');
if (cache_status) {
setStatus(cache_status);
} else {
fetchStatus();
}
}, []);
return {status,error,loading}
}
showToast("Something went wrong. Please try again.", "error");
if (onErrorCallback) onErrorCallback(error);
},
});
};

View File

@ -9,7 +9,7 @@ import ReportTaskComments from "../../components/Activities/ReportTaskComments";
import DateRangePicker from "../../components/common/DateRangePicker";
import { useSearchParams } from "react-router-dom";
import moment from "moment";
import FilterIcon from "../../components/common/FilterIcon"; // Import the FilterIcon component
import FilterIcon from "../../components/common/FilterIcon";
import GlobalModel from "../../components/common/GlobalModel";
import AssignTask from "../../components/Project/AssignTask";
import SubTask from "../../components/Activities/SubTask";
@ -20,14 +20,14 @@ const DailyTask = () => {
const selectedProject = useSelector(
(store) => store.localVariables.projectId
);
const {
projects,
loading: project_loading,
error: projects_Error,
} = useProjects();
// const {
// projects,
// loading: project_loading,
// error: projects_Error,
// } = useProjects();
const [initialized, setInitialized] = useState(false);
const dispatch = useDispatch();
// const [initialized, setInitialized] = useState(false);
// const dispatch = useDispatch();
const [filters, setFilters] = useState({
selectedBuilding: "",
@ -35,23 +35,23 @@ const DailyTask = () => {
selectedActivities: [],
});
useEffect(() => {
if (!project_loading && projects.length > 0 && !initialized) {
if (projectIdFromUrl) {
dispatch(setProjectId(projectIdFromUrl));
} else if (selectedProject === 1 || selectedProject === undefined) {
dispatch(setProjectId(projects[0].id));
}
setInitialized(true);
}
}, [
project_loading,
projects,
projectIdFromUrl,
selectedProject,
initialized,
dispatch,
]);
// useEffect(() => {
// if (!project_loading && projects.length > 0 && !initialized) {
// if (projectIdFromUrl) {
// dispatch(setProjectId(projectIdFromUrl));
// } else if (selectedProject === 1 || selectedProject === undefined) {
// dispatch(setProjectId(projects[0].id));
// }
// setInitialized(true);
// }
// }, [
// project_loading,
// projects,
// projectIdFromUrl,
// selectedProject,
// initialized,
// dispatch,
// ]);
const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" });
@ -61,10 +61,11 @@ const DailyTask = () => {
error: task_error,
refetch,
} = useTaskList(
initialized ? selectedProject : null,
initialized ? dateRange.startDate : null,
initialized ? dateRange.endDate : null
);
selectedProject || null,
dateRange?.startDate || null,
dateRange?.endDate || null
);
const [TaskLists, setTaskLists] = useState([]);
const [dates, setDates] = useState([]);
@ -83,8 +84,8 @@ const DailyTask = () => {
}
if (filters.selectedFloors.length > 0) {
filteredTasks = filteredTasks.filter((task) =>
filters.selectedFloors.includes(
filteredTasks = filteredTasks?.filter((task) =>
filters.selectedFloors?.includes(
task?.workItem?.workArea?.floor?.floorName
)
);
@ -103,9 +104,9 @@ const DailyTask = () => {
}
}, [
TaskList,
filters.selectedBuilding,
filters.selectedFloors,
filters.selectedActivities,
filters?.selectedBuilding,
filters?.selectedFloors,
filters?.selectedActivities,
]);
useEffect(() => {
@ -150,43 +151,41 @@ const DailyTask = () => {
const handlecloseModal = () =>
{
setIsModalOpen( false )
refetch(selectedProject, dateRange.startDate, dateRange.endDate);
// refetch();
}
const handleProjectChange = (e) => {
const newProjectId = e.target.value;
dispatch(setProjectId(newProjectId));
setTaskLists([]);
setFilters({
selectedBuilding: "",
selectedFloors: [],
selectedActivities: [],
});
};
// const handleProjectChange = (e) => {
// const newProjectId = e.target.value;
// dispatch(setProjectId(newProjectId));
// setTaskLists([]);
// setFilters({
// selectedBuilding: "",
// selectedFloors: [],
// selectedActivities: [],
// });
// };
const handleCloseAction = (IsSubTask) => {
if (IsSubTask) {
setIsSubTaskNeeded(true);
setIsModalOpenComment(false);
} else {
refetch(selectedProject, dateRange.startDate, dateRange.endDate);
// refetch();
setIsModalOpenComment(false);
}
};
const hanleCloseSubTask = () => {
setIsSubTaskNeeded(false);
setComment( null );
refetch(selectedProject, dateRange.startDate, dateRange.endDate);
// refetch();
};
return (
<>
{isModalOpen && <GlobalModel isOpen={isModalOpen} size="md" closeModal={handlecloseModal} >
<ReportTask
report={selectedTask}
closeModal={handlecloseModal}
refetch={refetch}
// refetch={refetch}
/>
</GlobalModel>}
@ -255,7 +254,7 @@ const DailyTask = () => {
</thead>
<tbody className="table-border-bottom-0">
{/* --- Spinner when tasks are loading --- */}
{(task_loading || project_loading) && (
{task_loading && (
<tr>
<td colSpan={6} className="text-center">
{" "}
@ -272,7 +271,6 @@ const DailyTask = () => {
</tr>
)}
{!task_loading &&
!project_loading &&
TaskLists.length === 0 && (
<tr>
<td colSpan={6} className="text-center">
@ -413,7 +411,7 @@ const DailyTask = () => {
} more`}
>
<span className="avatar-initial rounded-circle bg-label-secondary pull-up">
+{task.teamMembers.length - 3}
+ {task.teamMembers.length - 3}
</span>
</div>
)}

View File

@ -1,110 +1,9 @@
import React, { useState, useEffect } from "react";
import "../../components/Project/ProjectInfra.css";
import ProjectRepository from "../../repositories/ProjectRepository";
import React from "react";
import Breadcrumb from "../../components/common/Breadcrumb";
import InfraPlanning from "../../components/Activities/InfraPlanning";
import { cacheData, getCachedData } from "../../slices/apiDataManager";
import { useProfile } from "../../hooks/useProfile";
import { useDispatch, useSelector } from "react-redux";
import { useProjectDetails, useProjects } from "../../hooks/useProjects";
import { setProjectId } from "../../slices/localVariablesSlice";
import showToast from "../../services/toastService";
const TaskPlannng = () => {
const { profile } = useProfile();
const {
projects,
loading: project_listLoader,
error: projects_error,
} = useProjects();
const dispatch = useDispatch();
const selectedProject = useSelector(
(store) => store.localVariables.projectId
);
const [project, setProject] = useState(null);
const [projectDetails, setProjectDetails] = useState(null);
const [activities, setActivities] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState("");
const fetchActivities = async () => {
try {
const activities_cache = getCachedData("activitiesMaster");
if (!activities_cache) {
ActivityeRepository.getActivities()
.then((response) => {
setActivities(response.data);
cacheData("activitiesMaster", response.data);
})
.catch((error) => {
setError("Failed to fetch data.");
});
} else {
setActivities(activities_cache);
}
} catch (err) {
setError("Failed to fetch activities.");
} finally {
// setLoading(false);
}
};
const fetchData = async () => {
try {
const project_cache = getCachedData("projectInfo");
if (!project_cache || !project_cache.projectId == selectedProject) {
ProjectRepository.getProjectByprojectId(selectedProject)
.then((response) => {
setProjectDetails(response);
setProject(response);
cacheData("projectInfo", {
data: response.data,
projectId: selectedProject,
});
})
.catch((error) => {
const message =
error.response?.data?.message ||
error.message ||
"An unexpected error occurred";
showToast( message, "error" );
});
} else {
setProjectDetails(project_cache);
}
} catch (err) {
setError( "Failed to fetch data." );
const message =
error.response?.data?.message ||
error.message ||
"An unexpected error occurred";
showToast( message, "error" );
} finally {
setLoading(false);
}
};
const [activePill, setActivePill] = useState("profile");
const handlePillClick = (pillKey) => {
setActivePill(pillKey);
};
const handleDataChange = (data) => {
fetchData();
};
useEffect(() => {
if (projects.length != 0 && selectedProject) {
fetchData();
fetchActivities();
}
}, [selectedProject]);
return (
<>
@ -115,17 +14,7 @@ const TaskPlannng = () => {
{ label: "Daily Task Planning", link: "/activities/task" },
]}
></Breadcrumb>
{project_listLoader && <p>Loading..</p>}
{!project_listLoader && projects.length === 0 && (
<p>No Project Found.</p>
)}
{!project_listLoader && projects.length > 0 && (
<InfraPlanning
data={projectDetails}
activityMaster={activities}
onDataChange={handleDataChange}
/>
)}
<InfraPlanning/>
</div>
</>
);

View File

@ -8,7 +8,8 @@ import showToast from "./toastService";
import eventBus from "./eventBus";
import { useSelector } from "react-redux";
import { clearApiCacheKey } from "../slices/apiCacheSlice";
import { BASE_URL } from "../utils/constants";
import {BASE_URL} from "../utils/constants";
import { queryClient } from "../layouts/AuthLayout";
const base_Url = BASE_URL;
let connection = null;
@ -57,7 +58,8 @@ export function startSignalR(loggedUser) {
data.keyword == "Create_Project" ||
data.keyword == "Update_Project"
) {
clearCacheKey("projectslist");
// clearCacheKey("projectslist");
queryClient.invalidateQueries(['projectslist']);
eventBus.emit("project", data);
}
@ -83,13 +85,22 @@ export function startSignalR(loggedUser) {
// if created or updated Employee
if (data.keyword == "Employee") {
clearCacheKey("employeeListByProject");
clearCacheKey("allEmployeeList");
clearCacheKey("allInactiveEmployeeList");
clearCacheKey("employeeProfile");
// clearCacheKey("employeeListByProject");
// clearCacheKey("allEmployeeList");
// clearCacheKey("allInactiveEmployeeList");
// clearCacheKey("employeeProfile");
clearCacheKey("Attendance");
clearCacheKey("regularizedList")
clearCacheKey("AttendanceLogs")
// ---we can do also----
// queryClient.removeQueries(['allEmployee', true]);
// but best practies is refetch
queryClient.invalidateQueries(['allEmployee', true]);
queryClient.invalidateQueries(['allEmployee', false]);
queryClient.invalidateQueries(['employeeProfile', data.response?.employeeId]);
queryClient.invalidateQueries(['employeeListByProject']); // optional if scope
queryClient
eventBus.emit("employee", data);
}
}