Compare commits

...

11 Commits

Author SHA1 Message Date
9b2c27b903 Merge branch 'Ashutosh_Enhancement#205_Added_WorkCategory_Dropdown' of https://git.marcoaiot.com/admin/marco.pms.web into Ashutosh_Enhancement#205_Added_WorkCategory_Dropdown 2025-05-12 14:44:59 +05:30
e8ac267d46 Added a Work Category dropdown in task create/update forms and a new column to display the category in Project Infrastructure and Daily Task Planning views. 2025-05-12 14:40:13 +05:30
634dc12e5b Merge pull request 'Changed the first letter of all form field variables to lowercase to follow proper variable naming conventions.' (#98) from Ashutosh_Bug#216_Create_Employee_Popup_Typo into Issue_May_2W
Reviewed-on: #98
2025-05-12 07:58:33 +00:00
cf204f376d Changed the first letter of all form field variables to lowercase to follow proper variable naming conventions. 2025-05-12 07:58:33 +00:00
49f725b62d Merge pull request 'pramod_Task#207 Sync activity updates and deletions in Daily Task Planning view without page refresh' (#96) from pramod_Task#207 into Issue_May_2W
Reviewed-on: #96
2025-05-12 07:58:04 +00:00
8db6a16e15 revert 1827757f19bd15c05029e1ca9c72de3a65a68bf1
revert updated regularization logic based on 48-hour checkout threshold


- This update was mistakenly implemented in the wrong branch. Moving it here to align with the correct workflow.-  pramod_Bug#-27
2025-05-12 07:58:04 +00:00
Pramod Mahajan
2188f109cb disable Edit button and show "Please wait" message during activity update API call 2025-05-12 07:58:04 +00:00
Pramod Mahajan
292c920941 added loader during submitting form data. 2025-05-12 07:58:04 +00:00
Pramod Mahajan
af6a6faa46 ensure activity updates reflect in Daily Task Planning without page refresh 2025-05-12 07:58:04 +00:00
73152dbf0a Merge pull request 'Bug#215 updated regularization logic based on 48-hour checkout threshold for attendanceLogs.' (#97) from pramod_Bug-#215 into Issue_May_2W
Reviewed-on: #97
2025-05-12 07:57:40 +00:00
Pramod Mahajan
216e9b0db0 updated regularization logic based on 48-hour checkout threshold for attendanceLogs. 2025-05-12 07:57:40 +00:00
5 changed files with 103 additions and 75 deletions

View File

@ -13,7 +13,7 @@ import {useHasUserPermission} from "../../hooks/useHasUserPermission";
import {MANAGE_PROJECT_INFRA} from "../../utils/constants";
import {useDispatch, useSelector} from "react-redux";
import {useProfile} from "../../hooks/useProfile";
import {setProjectId} from "../../slices/localVariablesSlice";
import {refreshData, setProjectId} from "../../slices/localVariablesSlice";
import InfraTable from "../Project/Infrastructure/InfraTable";
@ -25,11 +25,23 @@ const InfraPlanning = () =>
const selectedProject = useSelector((store)=>store.localVariables.projectId)
const ManageInfra = useHasUserPermission( MANAGE_PROJECT_INFRA )
const {projects_Details, loading: project_deatilsLoader, error: project_error} = useProjectDetails(selectedProject)
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])
}, [ projects ] )
useEffect( () =>
{
if (reloadedData)
{
refetch()
dispatch( refreshData( false ) )
}
},[reloadedData])
return (
<div className="col-md-12 col-lg-12 col-xl-12 order-0 mb-4">

View File

@ -33,7 +33,7 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
const { data: job_role, loading } = useMaster();
const [isloading, setLoading] = useState(false);
const navigation = useNavigate();
const [currentEmployee, setCurrentEmployee] = useState();
const [currentEmployee, setCurrentEmployee] = useState(null);
const [currentAddressLength, setCurrentAddressLength] = useState(0);
const [permanentAddressLength, setPermanentAddressLength] = useState(0);
@ -157,22 +157,30 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
mode: "onChange",
});
const AadharNumberValue = watch("AadharNumber") || "";
const AadharNumberValue = watch("aadharNumber") || "";
const onSubmit = (data) => {
setLoading(true);
console.log(data);
if (data.email == "") {
data.email = null;
}
EmployeeRepository.manageEmployee(data)
.then((response) => {
showToast("Employee details updated successfully.", "success");
showToast(
`Employee details ${
data.id == null ? "created" : "updated"
} successfully.`,
"success"
);
clearCacheKey("employeeListByProject");
clearCacheKey("allEmployeeList");
clearCacheKey("allInactiveEmployeeList");
clearCacheKey("employeeProfile");
setLoading(false);
reset();
navigation("/employees");
// navigation("/employees");
onClosed();
})
.catch((error) => {
const message =
@ -232,7 +240,7 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
className="cursor-pointer fs-6"
onClick={() => onClosed()}
>
<i className='bx bx-x'></i>
<i className="bx bx-x"></i>
</span>
</div>
<div className="card-body">
@ -250,15 +258,15 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
name="FirstName"
{...register("firstName")}
className="form-control form-control-sm"
id="FirstName"
id="firstName"
placeholder="First Name"
/>
{errors.FirstName && (
{errors.firstName && (
<div
className="danger-text text-start"
style={{ fontSize: "12px" }}
>
{errors.FirstName.message}
{errors.firstName.message}
</div>
)}
</div>{" "}
@ -269,15 +277,15 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
type="text"
{...register("middleName")}
className="form-control form-control-sm"
id="MiddleName"
id="middleName"
placeholder="Middle Name"
/>
{errors.MiddleName && (
{errors.middleName && (
<div
className="danger-text text-start "
style={{ fontSize: "12px" }}
>
{errors.MiddleName.message}
{errors.middleName.message}
</div>
)}
</div>
@ -287,15 +295,15 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
type="text"
{...register("lastName")}
className="form-control form-control-sm"
id="LastName"
id="lastName"
placeholder="Last Name"
/>
{errors.LastName && (
{errors.lastName && (
<div
className="danger-text text-start"
style={{ fontSize: "12px" }}
>
{errors.LastName.message}
{errors.lastName.message}
</div>
)}
</div>
@ -305,7 +313,7 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
<div className="form-text text-start">Email</div>
<input
type="email"
id="Email"
id="email"
{...register("email")}
className="form-control form-control-sm"
placeholder="example@domain.com"
@ -313,12 +321,12 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
aria-describedby="Email"
disabled={!!currentEmployee?.email}
/>
{errors.Email && (
{errors.email && (
<div
className="danger-text text-start"
style={{ fontSize: "12px" }}
>
{errors.Email.message}
{errors.email.message}
</div>
)}
</div>
@ -327,19 +335,19 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
<input
type="text"
keyboardType="numeric"
id="PhoneNumber"
id="phoneNumber"
{...register("phoneNumber")}
className="form-control form-control-sm"
placeholder="Phone Number"
inputMode="numeric"
maxLength={10}
/>
{errors.PhoneNumber && (
{errors.phoneNumber && (
<div
className="danger-text text-start"
style={{ fontSize: "12px" }}
>
{errors.PhoneNumber.message}
{errors.phoneNumber.message}
</div>
)}
</div>
@ -353,7 +361,7 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
<select
className="form-select form-select-sm "
{...register("gender")}
id="Gender"
id="gender"
aria-label=""
>
<option disabled value="">
@ -364,12 +372,12 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
<option value="Other">Other</option>
</select>
</div>
{errors.Gender && (
{errors.gender && (
<div
className="danger-text text-start"
style={{ fontSize: "12px" }}
>
{errors.Gender.message}
{errors.gender.message}
</div>
)}
</div>
@ -381,15 +389,15 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
className="form-control form-control-sm"
type="date"
{...register("birthDate")}
id="BirthDate"
id="birthDate"
/>
</div>
{errors.BirthDate && (
{errors.birthDate && (
<div
className="danger-text text-start"
style={{ fontSize: "12px" }}
>
{errors.BirthDate.message}
{errors.birthDate.message}
</div>
)}
</div>
@ -401,15 +409,15 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
className="form-control form-control-sm"
type="date"
{...register("joiningDate")}
id="JoiningDate"
id="joiningDate"
/>
</div>
{errors.JoiningDate && (
{errors.joiningDate && (
<div
className="danger-text text-start"
style={{ fontSize: "12px" }}
>
{errors.JoiningDate.message}
{errors.joiningDate.message}
</div>
)}
</div>
@ -419,7 +427,7 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
<div className="form-text text-start">Current Address</div>
<textarea
id="CurrentAddress"
id="currentAddress"
className="form-control form-control-sm"
placeholder="Current Address"
aria-label="Current Address"
@ -429,7 +437,7 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
onChange={(e) => {
setCurrentAddressLength(e.target.value.length);
// let react-hook-form still handle it
register("CurrentAddress").onChange(e);
register("currentAddress").onChange(e);
}}
></textarea>
<div className="text-end muted">
@ -438,12 +446,12 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
{500 - currentAddressLength} characters left
</small>
</div>
{errors.CurrentAddress && (
{errors.currentAddress && (
<div
className="danger-text text-start"
style={{ fontSize: "12px" }}
>
{errors.CurrentAddress.message}
{errors.currentAddress.message}
</div>
)}
</div>
@ -453,7 +461,7 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
</div>
<textarea
id="PermanentAddress"
id="permanentAddress"
className="form-control form-control-sm"
placeholder="Permanent Address"
aria-label="Permanent Address"
@ -462,7 +470,7 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
maxLength={500}
onChange={(e) => {
setPermanentAddressLength(e.target.value.length);
register("PermanentAddress").onChange(e);
register("permanentAddress").onChange(e);
}}
></textarea>
<div className="text-end muted">
@ -470,12 +478,12 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
{500 - permanentAddressLength} characters left
</small>
</div>
{errors.PermanentAddress && (
{errors.permanentAddress && (
<div
className="danger-text text-start"
style={{ fontSize: "12px" }}
>
{errors.PermanentAddress.message}
{errors.permanentAddress.message}
</div>
)}
</div>
@ -493,7 +501,7 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
<select
className="form-select form-select-sm"
{...register("jobRoleId")}
id="JobRoleId"
id="jobRoleId"
aria-label=""
>
<option disabled value="">
@ -506,12 +514,12 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
))}
</select>
</div>
{errors.JobRoleId && (
{errors.jobRoleId && (
<div
className="danger-text text-start"
style={{ fontSize: "12px" }}
>
{errors.JobRoleId.message}
{errors.jobRoleId.message}
</div>
)}
</div>
@ -523,16 +531,16 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
type="text"
{...register("emergencyContactPerson")}
className="form-control form-control-sm"
id="EmergencyContactPerson"
id="emergencyContactPerson"
maxLength={50}
placeholder="Contact Person"
/>
{errors.EmergencyContactPerson && (
{errors.emergencyContactPerson && (
<div
className="danger-text text-start"
style={{ fontSize: "12px" }}
>
{errors.EmergencyContactPerson.message}
{errors.emergencyContactPerson.message}
</div>
)}
</div>
@ -544,17 +552,17 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
type="text"
{...register("emergencyPhoneNumber")}
className="form-control form-control-sm phone-mask"
id="EmergencyPhoneNumber"
id="emergencyPhoneNumber"
placeholder="Phone Number"
inputMode="numeric"
maxLength={10}
/>
{errors.EmergencyPhoneNumber && (
{errors.emergencyPhoneNumber && (
<div
className="danger-text text-start"
style={{ fontSize: "12px" }}
>
{errors.EmergencyPhoneNumber.message}
{errors.emergencyPhoneNumber.message}
</div>
)}
</div>
@ -567,14 +575,14 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
type="text"
{...register("aadharNumber")}
className="form-control form-control-sm"
id="AadharNumber"
id="aadharNumber"
placeholder="AADHAR Number"
maxLength={12}
inputMode="numeric"
/>
{errors.AadharNumber && (
{errors.aadharNumber && (
<div className="danger-text text-start">
{errors.AadharNumber.message}
{errors.aadharNumber.message}
</div>
)}
</div>
@ -585,16 +593,16 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
type="text"
{...register("panNumber")}
className="form-control form-control-sm"
id="PanNumber"
id="panNumber"
placeholder="PAN Number"
maxLength={10}
/>
{errors.PanNumber && (
{errors.panNumber && (
<div
className="danger-text text-start"
style={{ fontSize: "12px" }}
>
{errors.PanNumber.message}
{errors.panNumber.message}
</div>
)}
</div>

View File

@ -88,7 +88,9 @@ const EditActivityModal = ({
setValue("workCategoryId", selectedId);
};
const onSubmitForm = async (data) => {
const onSubmitForm = async ( data ) =>
{
setIsSubmitting(true)
const updatedProject = { ...projects_Details };
const finalData = {
...data,
@ -153,14 +155,18 @@ const EditActivityModal = ({
data: newProject,
});
resetForm();
dispatch(refreshData(true));
showToast("Activity Updated Successfully", "success");
dispatch( refreshData( true ) );
setIsSubmitting(false)
showToast("Activity Updated Successfully","success")
onClose();
}
})
.catch((error) => {
showToast(error?.response?.data?.message || error.message, "error");
.catch( ( error ) =>
{
setIsSubmitting(false)
const message = error.response.data.message || error.message || "Error Occured During Api Call"
showToast( message, "error" );
});
};
@ -379,11 +385,7 @@ const EditActivityModal = ({
{/* )} */}
<div className="col-12 text-center">
<button
type="submit"
className="btn btn-sm btn-primary me-3"
disabled={activities.length === 0}
>
<button type="submit" className="btn btn-sm btn-primary me-3" disabled={activities.length === 0 || isSubmitting}>
{isSubmitting ? "Please Wait.." : "Edit Task"}
</button>
<button

View File

@ -209,9 +209,15 @@ export const useEmployeesAllOrByProjectId = (projectId, showInactive) => {
export const useEmployeeProfile = (employeeId) => {
const [loading, setLoading] = useState(true);
const [error, setError] = useState();
const [employee, setEmployees] = useState();
const [employee, setEmployees] = useState(null);
const fetchData = async () => {
if (!employeeId) {
// Reset the state if no employeeId (e.g., opening for 'add' mode)
setEmployees(null);
setLoading(false);
return;
}
const Employee_cache = getCachedData("employeeProfile");
if (!Employee_cache || Employee_cache.employeeId !== employeeId) {
EmployeeRepository.getEmployeeProfile(employeeId)
@ -231,9 +237,7 @@ export const useEmployeeProfile = (employeeId) => {
};
useEffect(() => {
if (employeeId) {
fetchData(employeeId);
}
fetchData();
}, [employeeId]);
return { employee, loading, error };

View File

@ -43,7 +43,7 @@ const EmployeeList = () => {
const [searchText, setSearchText] = useState("");
const [filteredData, setFilteredData] = useState([]);
const [showModal, setShowModal] = useState(false);
const [selectedEmployeeId, setSelecedEmployeeId] = useState();
const [selectedEmployeeId, setSelecedEmployeeId] = useState(null);
const [IsDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
const [selectedEmpFordelete, setSelectedEmpFordelete] = useState(null);
const [employeeLodaing, setemployeeLodaing] = useState(false);
@ -111,6 +111,8 @@ const EmployeeList = () => {
document.querySelector(".modal-backdrop").remove();
}
setShowModal(false);
clearCacheKey("employeeProfile");
recallEmployeeData(showInactive);
};
const handleShow = () => setShowModal(true);
const handleClose = () => setShowModal(false);
@ -193,7 +195,7 @@ const EmployeeList = () => {
{isCreateModalOpen && (
<ManageEmp employeeId={modelConfig} onClosed={closeModal} />
)}
<div
{showModal && (<div
className={`modal fade ${showModal ? "show" : ""} `}
tabIndex="-1"
role="dialog"
@ -211,7 +213,7 @@ const EmployeeList = () => {
/>
</div>
</div>
</div>
</div>)}
{IsDeleteModalOpen && (
<div