Merge pull request 'Issues_Sep_1W_V2' (#402) from Issues_Sep_1W_V2 into Refactor_Directory
Reviewed-on: #402 Merged
This commit is contained in:
commit
d2288ea967
@ -470,9 +470,8 @@ const ManageContact = ({ contactId, closeModal }) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Actions */}
|
<div className="d-flex justify-content-end gap-2 py-2 mt-3">
|
||||||
<div className="d-flex justify-content-end gap-3 py-2">
|
<button
|
||||||
<button
|
|
||||||
className="btn btn-sm btn-label-secondary"
|
className="btn btn-sm btn-label-secondary"
|
||||||
type="button"
|
type="button"
|
||||||
onClick={handleClosed}
|
onClick={handleClosed}
|
||||||
|
@ -34,9 +34,13 @@ const EmpDashboard = ({ profile }) => {
|
|||||||
<div className="d-flex flex-wrap align-items-center justify-content-between gap-2">
|
<div className="d-flex flex-wrap align-items-center justify-content-between gap-2">
|
||||||
<div className="d-flex">
|
<div className="d-flex">
|
||||||
<div className="avatar flex-shrink-0 me-3">
|
<div className="avatar flex-shrink-0 me-3">
|
||||||
<span className="avatar-initial rounded bg-label-primary">
|
<span
|
||||||
|
className={`avatar-initial rounded ${project.removedDate ? "bg-label-warning" : "bg-label-success"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
<i className="icon-base bx bx-buildings icon-lg"></i>
|
<i className="icon-base bx bx-buildings icon-lg"></i>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h6 className="mb-0">{project.projectShortName}</h6>
|
<h6 className="mb-0">{project.projectShortName}</h6>
|
||||||
@ -49,6 +53,14 @@ const EmpDashboard = ({ profile }) => {
|
|||||||
<em>NA</em>
|
<em>NA</em>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{project.removedDate && (
|
||||||
|
<div className="mt-0 d-flex flex-column flex-sm-row justify-content-between">
|
||||||
|
<div className="label-secondary">
|
||||||
|
Unassigned:{" "}
|
||||||
|
{new Date(project.removedDate).toLocaleDateString()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@ -59,14 +71,7 @@ const EmpDashboard = ({ profile }) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Dates */}
|
{/* Dates */}
|
||||||
{project.removedDate && (
|
|
||||||
<div className="mt-2 d-flex flex-column flex-sm-row justify-content-between">
|
|
||||||
<div className="label-secondary">
|
|
||||||
Unassigned:{" "}
|
|
||||||
{new Date(project.removedDate).toLocaleDateString()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
@ -187,7 +187,7 @@ const ExpenseFilterPanel = ({ onApply, handleGroupBy }) => {
|
|||||||
<div className="d-flex justify-content-end py-3 gap-2">
|
<div className="d-flex justify-content-end py-3 gap-2">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-secondary btn-xs"
|
className="btn btn-label-secondary btn-xs"
|
||||||
onClick={onClear}
|
onClick={onClear}
|
||||||
>
|
>
|
||||||
Clear
|
Clear
|
||||||
|
@ -47,6 +47,20 @@ const AssignTask = ({ assignData, onClose, setAssigned }) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const dropdownRef = useRef(null);
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
|
// Close dropdown on outside click
|
||||||
|
useEffect(() => {
|
||||||
|
const handleClickOutside = (event) => {
|
||||||
|
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
||||||
|
setOpen(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
document.addEventListener("mousedown", handleClickOutside);
|
||||||
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const infoRef = useRef(null);
|
const infoRef = useRef(null);
|
||||||
const infoRef1 = useRef(null);
|
const infoRef1 = useRef(null);
|
||||||
|
|
||||||
@ -255,19 +269,20 @@ const AssignTask = ({ assignData, onClose, setAssigned }) => {
|
|||||||
<div className="row mb-1">
|
<div className="row mb-1">
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<div className="form-text text-start">
|
<div className="form-text text-start">
|
||||||
<div className="d-flex align-items-center form-text fs-7">
|
<div
|
||||||
|
className="d-flex align-items-center form-text fs-7"
|
||||||
|
ref={dropdownRef}
|
||||||
|
>
|
||||||
<span className="text-dark">Select Team</span>
|
<span className="text-dark">Select Team</span>
|
||||||
|
|
||||||
{/* Dropdown */}
|
{/* Dropdown */}
|
||||||
<div className="dropdown position-relative d-inline-block">
|
<div className="dropdown position-relative d-inline-block">
|
||||||
<a
|
<a
|
||||||
className={`dropdown-toggle hide-arrow cursor-pointer ${selectedRoles.includes("all") || selectedRoles.length === 0
|
className={`dropdown-toggle hide-arrow cursor-pointer ${selectedRoles.includes("all") || selectedRoles.length === 0
|
||||||
? "text-secondary"
|
? "text-secondary"
|
||||||
: "text-primary"
|
: "text-primary"
|
||||||
}`}
|
}`}
|
||||||
data-bs-toggle="dropdown"
|
onClick={() => setOpen(!open)}
|
||||||
role="button"
|
|
||||||
aria-expanded="false"
|
|
||||||
>
|
>
|
||||||
<i className="bx bx-slider-alt ms-2"></i>
|
<i className="bx bx-slider-alt ms-2"></i>
|
||||||
</a>
|
</a>
|
||||||
@ -290,57 +305,55 @@ const AssignTask = ({ assignData, onClose, setAssigned }) => {
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Dropdown Menu with Scroll */}
|
{/* Dropdown Menu */}
|
||||||
<ul
|
{open && (
|
||||||
className="dropdown-menu p-2 text-capitalize"
|
<ul
|
||||||
style={{ maxHeight: "300px", overflowY: "auto" }}
|
className="dropdown-menu show p-2 text-capitalize"
|
||||||
>
|
style={{ maxHeight: "300px", overflowY: "auto" }}
|
||||||
{/* All Roles */}
|
>
|
||||||
<li key="all">
|
{/* All Roles */}
|
||||||
<div className="form-check dropdown-item py-0">
|
<li key="all">
|
||||||
<input
|
|
||||||
className="form-check-input"
|
|
||||||
type="checkbox"
|
|
||||||
id="checkboxAllRoles"
|
|
||||||
value="all"
|
|
||||||
checked={selectedRoles.includes("all")}
|
|
||||||
onChange={(e) =>
|
|
||||||
handleRoleChange(e, e.target.value)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
className="form-check-label ms-2"
|
|
||||||
htmlFor="checkboxAllRoles"
|
|
||||||
>
|
|
||||||
All Roles
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
{/* Dynamic Roles */}
|
|
||||||
{jobRolesForDropdown?.map((role) => (
|
|
||||||
<li key={role.id}>
|
|
||||||
<div className="form-check dropdown-item py-0">
|
<div className="form-check dropdown-item py-0">
|
||||||
<input
|
<input
|
||||||
className="form-check-input"
|
className="form-check-input"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
id={`checkboxRole-${role.id}`}
|
id="checkboxAllRoles"
|
||||||
value={role.id}
|
value="all"
|
||||||
checked={selectedRoles.includes(String(role.id))}
|
checked={selectedRoles.includes("all")}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleRoleChange(e, e.target.value)}
|
||||||
handleRoleChange(e, e.target.value)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<label
|
<label
|
||||||
className="form-check-label ms-2"
|
className="form-check-label ms-2"
|
||||||
htmlFor={`checkboxRole-${role.id}`}
|
htmlFor="checkboxAllRoles"
|
||||||
>
|
>
|
||||||
{role.name}
|
All Roles
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
))}
|
|
||||||
</ul>
|
{/* Dynamic Roles */}
|
||||||
|
{jobRolesForDropdown?.map((role) => (
|
||||||
|
<li key={role.id}>
|
||||||
|
<div className="form-check dropdown-item py-0">
|
||||||
|
<input
|
||||||
|
className="form-check-input"
|
||||||
|
type="checkbox"
|
||||||
|
id={`checkboxRole-${role.id}`}
|
||||||
|
value={role.id}
|
||||||
|
checked={selectedRoles.includes(String(role.id))}
|
||||||
|
onChange={(e) => handleRoleChange(e, e.target.value)}
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
className="form-check-label ms-2"
|
||||||
|
htmlFor={`checkboxRole-${role.id}`}
|
||||||
|
>
|
||||||
|
{role.name}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Search Box */}
|
{/* Search Box */}
|
||||||
|
@ -106,7 +106,7 @@ const TenantFilterPanel = ({ onApply }) => {
|
|||||||
<div className="d-flex justify-content-end py-3 gap-2">
|
<div className="d-flex justify-content-end py-3 gap-2">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-secondary btn-xs"
|
className="btn btn-label-secondary btn-xs"
|
||||||
onClick={onClear}
|
onClick={onClear}
|
||||||
|
|
||||||
>
|
>
|
||||||
|
@ -273,7 +273,7 @@ const FilterIcon = ({
|
|||||||
<li className="d-flex justify-content-end gap-2 px-2 mt-2 mb-2">
|
<li className="d-flex justify-content-end gap-2 px-2 mt-2 mb-2">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-secondary btn-sm py-0 px-2"
|
className="btn btn-label-secondary btn-sm py-0 px-2"
|
||||||
onClick={clearAllFilters}
|
onClick={clearAllFilters}
|
||||||
>
|
>
|
||||||
Clear
|
Clear
|
||||||
|
@ -63,6 +63,7 @@
|
|||||||
border: none;
|
border: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
background-color: #f8f9fa;
|
background-color: #f8f9fa;
|
||||||
|
color: black;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
@ -65,9 +65,9 @@ const handleChange = (e) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Label htmlFor={name} className="form-label" required>
|
<label htmlFor={name} className="form-label">
|
||||||
{label}
|
{label}
|
||||||
</Label>
|
</label>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className="form-control form-control-sm p-1"
|
className="form-control form-control-sm p-1"
|
||||||
|
@ -11,6 +11,17 @@ import { queryClient } from "../layouts/AuthLayout";
|
|||||||
|
|
||||||
// Query ---------------------------------------------------------------------------
|
// Query ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export const useEmployee = (employeeId) => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ["employeeProfile", employeeId],
|
||||||
|
queryFn: async () => {
|
||||||
|
const res = await EmployeeRepository.getEmployeeProfile(employeeId)
|
||||||
|
return res.data;
|
||||||
|
},
|
||||||
|
enabled:!!employeeId
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const useAllEmployees = (showInactive) => {
|
export const useAllEmployees = (showInactive) => {
|
||||||
const {
|
const {
|
||||||
data = [],
|
data = [],
|
||||||
@ -197,6 +208,9 @@ export const useEmployeesNameByProject = (projectId) => {
|
|||||||
|
|
||||||
// Mutation------------------------------------------------------------------
|
// Mutation------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const useUpdateEmployee = () => {
|
export const useUpdateEmployee = () => {
|
||||||
const selectedProject = useSelector(
|
const selectedProject = useSelector(
|
||||||
(store) => store.localVariables.projectId
|
(store) => store.localVariables.projectId
|
||||||
@ -211,6 +225,7 @@ export const useUpdateEmployee = () => {
|
|||||||
const isAllEmployee = variables.IsAllEmployee;
|
const isAllEmployee = variables.IsAllEmployee;
|
||||||
|
|
||||||
// Cache invalidation
|
// Cache invalidation
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["employeeProfile",id] });
|
||||||
queryClient.invalidateQueries({ queryKey: ["allEmployees"] });
|
queryClient.invalidateQueries({ queryKey: ["allEmployees"] });
|
||||||
// queryClient.invalidateQueries(['employeeProfile', id]);
|
// queryClient.invalidateQueries(['employeeProfile', id]);
|
||||||
queryClient.invalidateQueries({ queryKey: ["projectEmployees"] });
|
queryClient.invalidateQueries({ queryKey: ["projectEmployees"] });
|
||||||
@ -232,40 +247,6 @@ export const useUpdateEmployee = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// export const useSuspendEmployee = ({ setIsDeleteModalOpen, setemployeeLodaing }) => {
|
|
||||||
// const queryClient = useQueryClient();
|
|
||||||
// const selectedProject = useSelector((store)=>store.localVariables.projectId)
|
|
||||||
// return useMutation({
|
|
||||||
// mutationFn: (id) => {
|
|
||||||
// setemployeeLodaing(true);
|
|
||||||
// return EmployeeRepository.deleteEmployee(id);
|
|
||||||
// },
|
|
||||||
|
|
||||||
// onSuccess: () => {
|
|
||||||
|
|
||||||
// // queryClient.invalidateQueries( ['allEmployee',false]);
|
|
||||||
// queryClient.invalidateQueries( {queryKey: [ 'projectEmployees' ]} );
|
|
||||||
// queryClient.invalidateQueries( {queryKey:[ 'employeeListByProject' ,selectedProject]} );
|
|
||||||
// showToast("Employee deleted successfully.", "success");
|
|
||||||
// setIsDeleteModalOpen(false);
|
|
||||||
// },
|
|
||||||
|
|
||||||
// onError: (error) => {
|
|
||||||
// const message =
|
|
||||||
// error.response?.data?.message ||
|
|
||||||
// error.message ||
|
|
||||||
// "An unexpected error occurred";
|
|
||||||
// showToast(message, "error");
|
|
||||||
// setIsDeleteModalOpen(false);
|
|
||||||
// },
|
|
||||||
|
|
||||||
// onSettled: () => {
|
|
||||||
// setemployeeLodaing(false);
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
|
|
||||||
// Manage Role
|
|
||||||
|
|
||||||
export const useSuspendEmployee = ({
|
export const useSuspendEmployee = ({
|
||||||
setIsDeleteModalOpen,
|
setIsDeleteModalOpen,
|
||||||
@ -353,4 +334,4 @@ export const useUpdateEmployeeRoles = ({
|
|||||||
isError: mutation.isError,
|
isError: mutation.isError,
|
||||||
error: mutation.error,
|
error: mutation.error,
|
||||||
};
|
};
|
||||||
};
|
};
|
@ -10,7 +10,7 @@ import { z } from "zod";
|
|||||||
|
|
||||||
|
|
||||||
const forgotPassSceham = z.object({
|
const forgotPassSceham = z.object({
|
||||||
email: z.string().email(),
|
email: z.string().trim().email(),
|
||||||
})
|
})
|
||||||
|
|
||||||
const ForgotPasswordPage = () => {
|
const ForgotPasswordPage = () => {
|
||||||
|
@ -16,13 +16,13 @@ const LoginPage = () => {
|
|||||||
|
|
||||||
const loginSchema = IsLoginWithOTP
|
const loginSchema = IsLoginWithOTP
|
||||||
? z.object({
|
? z.object({
|
||||||
username: z.string().email({ message: "Valid email required" }),
|
username: z.string().trim().email({ message: "Valid email required" }),
|
||||||
})
|
})
|
||||||
: z.object({
|
: z.object({
|
||||||
username: z.string().email({ message: "Valid email required" }),
|
username: z.string().trim().email({ message: "Valid email required" }),
|
||||||
password: z.string().min(1, { message: "Password required" }),
|
password: z.string().trim().min(1, { message: "Password required" }),
|
||||||
rememberMe: z.boolean(),
|
rememberMe: z.boolean(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
@ -106,7 +106,7 @@ const LoginPage = () => {
|
|||||||
{/* Password */}
|
{/* Password */}
|
||||||
{!IsLoginWithOTP && (
|
{!IsLoginWithOTP && (
|
||||||
<>
|
<>
|
||||||
<div className="mb-3 text-start">
|
{/* <div className="mb-3 text-start">
|
||||||
<label htmlFor="password" className="form-label">
|
<label htmlFor="password" className="form-label">
|
||||||
Password
|
Password
|
||||||
</label>
|
</label>
|
||||||
@ -114,9 +114,8 @@ const LoginPage = () => {
|
|||||||
<input
|
<input
|
||||||
type={hidepass ? "password" : "text"}
|
type={hidepass ? "password" : "text"}
|
||||||
id="password"
|
id="password"
|
||||||
className={`form-control ${
|
className={`form-control ${errors.password ? "is-invalid" : ""
|
||||||
errors.password ? "is-invalid" : ""
|
}`}
|
||||||
}`}
|
|
||||||
placeholder="••••••••"
|
placeholder="••••••••"
|
||||||
{...register("password")}
|
{...register("password")}
|
||||||
/>
|
/>
|
||||||
@ -135,6 +134,38 @@ const LoginPage = () => {
|
|||||||
{errors.password.message}
|
{errors.password.message}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
</div> */}
|
||||||
|
|
||||||
|
<div className="mb-3 form-password-toggle text-start">
|
||||||
|
<label htmlFor="password" className="form-label">
|
||||||
|
Password
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div className="input-group input-group-merge">
|
||||||
|
<input
|
||||||
|
type={hidepass ? "password" : "text"}
|
||||||
|
autoComplete="new-password"
|
||||||
|
id="password"
|
||||||
|
className="form-control form-control-xl shadow-none"
|
||||||
|
name="password"
|
||||||
|
{...register("password")}
|
||||||
|
placeholder="••••••••••••"
|
||||||
|
aria-describedby="password"
|
||||||
|
/>
|
||||||
|
<span className="input-group-text cursor-pointer border-start-0">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-link p-0"
|
||||||
|
onClick={() => setHidepass(!hidepass)}
|
||||||
|
>
|
||||||
|
{hidepass ? (
|
||||||
|
<i className="bx bx-hide fs-5" />
|
||||||
|
) : (
|
||||||
|
<i className="bx bx-show fs-5" />
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Remember Me + Forgot Password */}
|
{/* Remember Me + Forgot Password */}
|
||||||
@ -169,8 +200,8 @@ const LoginPage = () => {
|
|||||||
{loading
|
{loading
|
||||||
? "Please Wait..."
|
? "Please Wait..."
|
||||||
: IsLoginWithOTP
|
: IsLoginWithOTP
|
||||||
? "Send OTP"
|
? "Send OTP"
|
||||||
: "Sign In"}
|
: "Sign In"}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{/* Login With OTP Button */}
|
{/* Login With OTP Button */}
|
||||||
|
@ -93,153 +93,155 @@ const ResetPassword = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="col-12 col-lg-5 col-xl-4 d-flex align-items-center justify-content-center p-4 p-sm-5 bg-gray-60 h-100">
|
<div className="col-12 col-lg-5 col-xl-4 d-flex align-items-center justify-content-center p-4 p-sm-5 bg-gray-60 h-100">
|
||||||
<div className="block p-4 p-sm-5 bg-gray-60">
|
<div className="block p-4 p-sm-5 bg-gray-60">
|
||||||
<h4 className="mb-2">Reset Password? 🔒</h4>
|
<h4 className="mb-2">Reset Password? 🔒</h4>
|
||||||
<p className="mb-4">Enter your email and new password to update.</p>
|
<p className="mb-4">Enter your email and new password to update.</p>
|
||||||
<form
|
<form
|
||||||
id="formAuthentication"
|
id="formAuthentication"
|
||||||
className="mb-3"
|
className="mb-3"
|
||||||
onSubmit={handleSubmit(onSubmitResetPassword)}
|
onSubmit={handleSubmit(onSubmitResetPassword)}
|
||||||
>
|
|
||||||
<div className="mb-3 text-start">
|
|
||||||
<label htmlFor="email" className="form-label">
|
|
||||||
Email
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className="form-control"
|
|
||||||
id="email"
|
|
||||||
{...register("email")}
|
|
||||||
placeholder="Enter your email"
|
|
||||||
autoFocus
|
|
||||||
/>
|
|
||||||
{errors.email && (
|
|
||||||
<div
|
|
||||||
className="danger-text text-start"
|
|
||||||
style={{ fontSize: "12px" }}
|
|
||||||
>
|
|
||||||
{errors.email.message}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-2 form-password-toggle text-start">
|
|
||||||
<div className="mt-2">
|
|
||||||
<label htmlFor="email" className="form-label">
|
|
||||||
New Password
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div className=" input-group input-group-merge">
|
|
||||||
<input
|
|
||||||
type={hidepass ? "password" : "text"}
|
|
||||||
autoComplete="true"
|
|
||||||
id="password"
|
|
||||||
className="form-control"
|
|
||||||
name="password"
|
|
||||||
{...register("password")}
|
|
||||||
placeholder="············"
|
|
||||||
aria-describedby="password"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="btn btn-outline-secondy border-top border-end border-bottom "
|
|
||||||
onClick={() => setHidepass(!hidepass)}
|
|
||||||
style={{
|
|
||||||
borderTopLeftRadius: 0,
|
|
||||||
borderBottomLeftRadius: 0,
|
|
||||||
borderLeft: 0,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{hidepass ? (
|
|
||||||
<i className="bx bx-hide" />
|
|
||||||
) : (
|
|
||||||
<i className="bx bx-show" />
|
|
||||||
)}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{errors.password && (
|
|
||||||
<div
|
|
||||||
className="danger-text text-start"
|
|
||||||
style={{ fontSize: "12px" }}
|
|
||||||
>
|
|
||||||
{errors.password.message}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className="mt-2">
|
|
||||||
{" "}
|
|
||||||
<label htmlFor="email" className="form-label">
|
|
||||||
Repeat New Password
|
|
||||||
</label>{" "}
|
|
||||||
</div>
|
|
||||||
<div className=" input-group input-group-merge">
|
|
||||||
<input
|
|
||||||
type={hidepass1 ? "password" : "text"}
|
|
||||||
autoComplete="true"
|
|
||||||
id="password"
|
|
||||||
className="form-control"
|
|
||||||
name="confirmPassword"
|
|
||||||
{...register("confirmPassword")}
|
|
||||||
placeholder="············"
|
|
||||||
aria-describedby="password"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="btn border-top border-end border-bottom "
|
|
||||||
onClick={() => setHidepass1(!hidepass1)}
|
|
||||||
style={{
|
|
||||||
borderTopLeftRadius: 0,
|
|
||||||
borderBottomLeftRadius: 0,
|
|
||||||
borderLeft: 0,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{hidepass1 ? (
|
|
||||||
<i className="bx bx-hide" />
|
|
||||||
) : (
|
|
||||||
<i className="bx bx-show" />
|
|
||||||
)}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{errors.confirmPassword && (
|
|
||||||
<div
|
|
||||||
className="danger-text text-start"
|
|
||||||
style={{ fontSize: "12px" }}
|
|
||||||
>
|
|
||||||
{errors.confirmPassword.message}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-3 text-start ">
|
|
||||||
<p className="p-0 m-0" style={{ fontSize: "9px" }}>
|
|
||||||
Password must be at least 8 characters
|
|
||||||
</p>
|
|
||||||
<p className="p-0 m-0" style={{ fontSize: "9px" }}>
|
|
||||||
Password must contain at least one uppercase letter
|
|
||||||
</p>
|
|
||||||
<p className="p-0 m-0" style={{ fontSize: "9px" }}>
|
|
||||||
Password must contain at least one number
|
|
||||||
</p>
|
|
||||||
<p className="p-0 m-0" style={{ fontSize: "9px" }}>
|
|
||||||
Password must contain at least one special character
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<button aria-label="Click me" className="btn btn-primary d-grid w-100">
|
|
||||||
{loading ? "Please Wait..." : "Update Password"}
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
<div className="text-center">
|
|
||||||
<Link
|
|
||||||
aria-label="Go to Login Page"
|
|
||||||
to="/auth/login"
|
|
||||||
className="d-flex align-items-center justify-content-center"
|
|
||||||
>
|
>
|
||||||
<i className="bx bx-chevron-left scaleX-n1-rtl bx-sm"></i>
|
<div className="mb-3 text-start">
|
||||||
Back to login
|
<label htmlFor="email" className="form-label">
|
||||||
</Link>
|
Email
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="form-control border border-secondary"
|
||||||
|
id="email"
|
||||||
|
{...register("email")}
|
||||||
|
placeholder="Enter your email"
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
{errors.email && (
|
||||||
|
<div
|
||||||
|
className="danger-text text-start"
|
||||||
|
style={{ fontSize: "12px" }}
|
||||||
|
>
|
||||||
|
{errors.email.message}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mb-2 form-password-toggle text-start">
|
||||||
|
<div className="mt-2">
|
||||||
|
<label htmlFor="email" className="form-label">
|
||||||
|
New Password
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="input-group input-group-merge d-flex align-items-center border border-secondary rounded px-2">
|
||||||
|
<input
|
||||||
|
type={hidepass ? "password" : "text"}
|
||||||
|
autoComplete="true"
|
||||||
|
id="password"
|
||||||
|
className="form-control form-control-xl border-0 shadow-none"
|
||||||
|
name="password"
|
||||||
|
{...register("password")}
|
||||||
|
placeholder="············"
|
||||||
|
aria-describedby="password"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-link-secondary p-0 ms-2"
|
||||||
|
onClick={() => setHidepass(!hidepass)}
|
||||||
|
style={{
|
||||||
|
borderTopLeftRadius: 0,
|
||||||
|
borderBottomLeftRadius: 0,
|
||||||
|
borderLeft: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{hidepass ? (
|
||||||
|
<i className="bx bx-hide" />
|
||||||
|
) : (
|
||||||
|
<i className="bx bx-show" />
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{errors.password && (
|
||||||
|
<div
|
||||||
|
className="danger-text text-start"
|
||||||
|
style={{ fontSize: "12px" }}
|
||||||
|
>
|
||||||
|
{errors.password.message}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="mt-2">
|
||||||
|
{" "}
|
||||||
|
<label htmlFor="email" className="form-label">
|
||||||
|
Repeat New Password
|
||||||
|
</label>{" "}
|
||||||
|
</div>
|
||||||
|
<div className="input-group input-group-merge d-flex align-items-center border border-secondary rounded px-2">
|
||||||
|
<input
|
||||||
|
type={hidepass1 ? "password" : "text"}
|
||||||
|
autoComplete="true"
|
||||||
|
id="password"
|
||||||
|
className="form-control form-control-xl border-0 shadow-none"
|
||||||
|
name="confirmPassword"
|
||||||
|
{...register("confirmPassword")}
|
||||||
|
placeholder="············"
|
||||||
|
aria-describedby="password"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-link-secondary p-0 ms-2"
|
||||||
|
onClick={() => setHidepass1(!hidepass1)}
|
||||||
|
style={{
|
||||||
|
borderTopLeftRadius: 0,
|
||||||
|
borderBottomLeftRadius: 0,
|
||||||
|
borderLeft: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{hidepass1 ? (
|
||||||
|
<i className="bx bx-hide" />
|
||||||
|
) : (
|
||||||
|
<i className="bx bx-show" />
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{errors.confirmPassword && (
|
||||||
|
<div
|
||||||
|
className="danger-text text-start"
|
||||||
|
style={{ fontSize: "12px" }}
|
||||||
|
>
|
||||||
|
{errors.confirmPassword.message}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mb-3 text-start ">
|
||||||
|
<p className="p-0 m-0" style={{ fontSize: "9px" }}>
|
||||||
|
Password must be at least 8 characters
|
||||||
|
</p>
|
||||||
|
<p className="p-0 m-0" style={{ fontSize: "9px" }}>
|
||||||
|
Password must contain at least one uppercase letter
|
||||||
|
</p>
|
||||||
|
<p className="p-0 m-0" style={{ fontSize: "9px" }}>
|
||||||
|
Password must contain at least one number
|
||||||
|
</p>
|
||||||
|
<p className="p-0 m-0" style={{ fontSize: "9px" }}>
|
||||||
|
Password must contain at least one special character
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<button aria-label="Click me" className="btn btn-primary d-grid w-100">
|
||||||
|
{loading ? "Please Wait..." : "Update Password"}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<div className="text-center">
|
||||||
|
<Link
|
||||||
|
aria-label="Go to Login Page"
|
||||||
|
to="/auth/login"
|
||||||
|
className="d-flex align-items-center justify-content-center"
|
||||||
|
>
|
||||||
|
<i className="bx bx-chevron-left scaleX-n1-rtl bx-sm"></i>
|
||||||
|
Back to login
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ import {
|
|||||||
VIEW_ALL_EMPLOYEES,
|
VIEW_ALL_EMPLOYEES,
|
||||||
VIEW_TEAM_MEMBERS,
|
VIEW_TEAM_MEMBERS,
|
||||||
} from "../../utils/constants";
|
} from "../../utils/constants";
|
||||||
import { clearCacheKey, useSelectedProject } from "../../slices/apiDataManager";
|
import { clearCacheKey } from "../../slices/apiDataManager";
|
||||||
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
||||||
import SuspendEmp from "../../components/Employee/SuspendEmp"; // Keep if you use SuspendEmp
|
import SuspendEmp from "../../components/Employee/SuspendEmp"; // Keep if you use SuspendEmp
|
||||||
import {
|
import {
|
||||||
@ -38,10 +38,9 @@ import usePagination from "../../hooks/usePagination";
|
|||||||
import { setProjectId } from "../../slices/localVariablesSlice";
|
import { setProjectId } from "../../slices/localVariablesSlice";
|
||||||
|
|
||||||
const EmployeeList = () => {
|
const EmployeeList = () => {
|
||||||
// const selectedProjectId = useSelector(
|
const selectedProjectId = useSelector(
|
||||||
// (store) => store.localVariables.projectId
|
(store) => store.localVariables.projectId
|
||||||
// );
|
);
|
||||||
const selectedProjectId = useSelectedProject();
|
|
||||||
const { projectNames, loading: projectLoading, fetchData } = useProjectName();
|
const { projectNames, loading: projectLoading, fetchData } = useProjectName();
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@ -79,11 +78,11 @@ const EmployeeList = () => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!selectedProjectId && projectNames?.length > 0) {
|
if (selectedProjectId === null) {
|
||||||
dispatch(setProjectId(projectNames[0].id));
|
dispatch(setProjectId(projectNames[0]?.id));
|
||||||
}
|
}
|
||||||
}, [selectedProjectId, projectNames, dispatch]);
|
}, [selectedProjectId]);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const applySearchFilter = (data, text) => {
|
const applySearchFilter = (data, text) => {
|
||||||
@ -177,12 +176,10 @@ useEffect(() => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!loading && Array.isArray(employees)) {
|
if (!loading && Array.isArray(employees)) {
|
||||||
const sorted = [...employees].sort((a, b) => {
|
const sorted = [...employees].sort((a, b) => {
|
||||||
const nameA = `${a.firstName || ""}${a.middleName || ""}${
|
const nameA = `${a.firstName || ""}${a.middleName || ""}${a.lastName || ""
|
||||||
a.lastName || ""
|
}`.toLowerCase();
|
||||||
}`.toLowerCase();
|
const nameB = `${b.firstName || ""}${b.middleName || ""}${b.lastName || ""
|
||||||
const nameB = `${b.firstName || ""}${b.middleName || ""}${
|
}`.toLowerCase();
|
||||||
b.lastName || ""
|
|
||||||
}`.toLowerCase();
|
|
||||||
return nameA?.localeCompare(nameB);
|
return nameA?.localeCompare(nameB);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -221,10 +218,10 @@ useEffect(() => {
|
|||||||
recallEmployeeData(
|
recallEmployeeData(
|
||||||
showInactive,
|
showInactive,
|
||||||
showAllEmployees ? null : selectedProjectId
|
showAllEmployees ? null : selectedProjectId
|
||||||
);
|
); // Use selectedProjectId here
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[employees, showInactive, showAllEmployees, selectedProjectId]
|
[employees, showInactive, showAllEmployees, selectedProjectId] // Add all relevant dependencies
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -247,7 +244,7 @@ useEffect(() => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{showModal && (
|
{showModal && (
|
||||||
<GlobalModel
|
<GlobalModel
|
||||||
isOpen={showModal}
|
isOpen={showModal}
|
||||||
size="lg"
|
size="lg"
|
||||||
closeModal={() => setShowModal(false)}
|
closeModal={() => setShowModal(false)}
|
||||||
@ -259,18 +256,24 @@ useEffect(() => {
|
|||||||
/>
|
/>
|
||||||
</GlobalModel>
|
</GlobalModel>
|
||||||
)}
|
)}
|
||||||
{IsDeleteModalOpen && (
|
|
||||||
|
{IsDeleteModalOpen && (
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
isOpen={IsDeleteModalOpen}
|
isOpen={IsDeleteModalOpen}
|
||||||
type="delete"
|
type="delete"
|
||||||
header="Suspend Employee"
|
header={
|
||||||
message="Are you sure you want suspend?"
|
selectedEmpFordelete?.isActive
|
||||||
|
? "Suspend Employee"
|
||||||
|
: "Reactivate Employee"
|
||||||
|
}
|
||||||
|
message={`Are you sure you want to ${selectedEmpFordelete?.isActive ? "suspend" : "reactivate"
|
||||||
|
} this employee?`}
|
||||||
onSubmit={(id) =>
|
onSubmit={(id) =>
|
||||||
suspendEmployee({
|
suspendEmployee({
|
||||||
employeeId:id ,
|
employeeId: id,
|
||||||
active: !selectedEmpFordelete.isActive,
|
active: !selectedEmpFordelete.isActive,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
onClose={() => setIsDeleteModalOpen(false)}
|
onClose={() => setIsDeleteModalOpen(false)}
|
||||||
loading={employeeLodaing}
|
loading={employeeLodaing}
|
||||||
paramData={selectedEmpFordelete.id}
|
paramData={selectedEmpFordelete.id}
|
||||||
@ -496,9 +499,8 @@ useEffect(() => {
|
|||||||
Status
|
Status
|
||||||
</th>
|
</th>
|
||||||
<th
|
<th
|
||||||
className={`sorting_disabled ${
|
className={`sorting_disabled ${!Manage_Employee && "d-none"
|
||||||
!Manage_Employee && "d-none"
|
}`}
|
||||||
}`}
|
|
||||||
rowSpan="1"
|
rowSpan="1"
|
||||||
colSpan="1"
|
colSpan="1"
|
||||||
style={{ width: "50px" }}
|
style={{ width: "50px" }}
|
||||||
@ -518,9 +520,9 @@ useEffect(() => {
|
|||||||
)}
|
)}
|
||||||
{/* Conditional messages for no data or no search results */}
|
{/* Conditional messages for no data or no search results */}
|
||||||
{!loading &&
|
{!loading &&
|
||||||
displayData?.length === 0 &&
|
displayData?.length === 0 &&
|
||||||
searchText &&
|
searchText &&
|
||||||
!showAllEmployees ? (
|
!showAllEmployees ? (
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={8}>
|
<td colSpan={8}>
|
||||||
<small className="muted">
|
<small className="muted">
|
||||||
@ -530,14 +532,14 @@ useEffect(() => {
|
|||||||
</tr>
|
</tr>
|
||||||
) : null}
|
) : null}
|
||||||
{!loading &&
|
{!loading &&
|
||||||
displayData?.length === 0 &&
|
displayData?.length === 0 &&
|
||||||
(!searchText || showAllEmployees) ? (
|
(!searchText || showAllEmployees) ? (
|
||||||
<tr>
|
<tr>
|
||||||
<td
|
<td
|
||||||
colSpan={8}
|
colSpan={8}
|
||||||
style={{ paddingTop: "20px", textAlign: "center" }}
|
style={{ paddingTop: "20px", textAlign: "center" }}
|
||||||
>
|
>
|
||||||
No team members assigned yet
|
No Data Found
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
) : null}
|
) : null}
|
||||||
@ -556,9 +558,7 @@ useEffect(() => {
|
|||||||
<div className="d-flex flex-column">
|
<div className="d-flex flex-column">
|
||||||
<a
|
<a
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
navigate(
|
navigate(`/employee/${item.id}`)
|
||||||
`/employee/${item.id}?for=attendance`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
className="text-heading text-truncate cursor-pointer"
|
className="text-heading text-truncate cursor-pointer"
|
||||||
>
|
>
|
||||||
@ -594,10 +594,9 @@ useEffect(() => {
|
|||||||
{item.jobRole || "Not Assign Yet"}
|
{item.jobRole || "Not Assign Yet"}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td className=" d-none d-md-table-cell">
|
<td className=" d-none d-md-table-cell">
|
||||||
{item.joiningDate
|
{moment(item.joiningDate)?.format("DD-MMM-YYYY")}
|
||||||
? moment(item.joiningDate).format("DD-MMM-YYYY")
|
|
||||||
: "NA"}
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{showInactive ? (
|
{showInactive ? (
|
||||||
@ -626,47 +625,56 @@ useEffect(() => {
|
|||||||
<i className="bx bx-dots-vertical-rounded bx-md"></i>
|
<i className="bx bx-dots-vertical-rounded bx-md"></i>
|
||||||
</button>
|
</button>
|
||||||
<div className="dropdown-menu dropdown-menu-end">
|
<div className="dropdown-menu dropdown-menu-end">
|
||||||
|
{/* View always visible */}
|
||||||
<button
|
<button
|
||||||
onClick={() =>
|
onClick={() => navigate(`/employee/${item.id}`)}
|
||||||
navigate(`/employee/${item.id}`)
|
|
||||||
}
|
|
||||||
className="dropdown-item py-1"
|
className="dropdown-item py-1"
|
||||||
>
|
>
|
||||||
<i className="bx bx-detail bx-sm"></i> View
|
<i className="bx bx-detail bx-sm"></i> View
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
className="dropdown-item py-1"
|
{/* If ACTIVE employee */}
|
||||||
onClick={() => {
|
{item.isActive && (
|
||||||
handleEmployeeModel(item.id);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<i className="bx bx-edit bx-sm"></i> Edit
|
|
||||||
</button>
|
|
||||||
{!item.isSystem && (
|
|
||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
className="dropdown-item py-1"
|
className="dropdown-item py-1"
|
||||||
onClick={() =>
|
onClick={() => handleEmployeeModel(item.id)}
|
||||||
handleOpenDelete(item)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<i className="bx bx-task-x bx-sm"></i>{" "}
|
<i className="bx bx-edit bx-sm"></i> Edit
|
||||||
Suspend
|
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
{/* Suspend only when active */}
|
||||||
|
{item.isActive && (
|
||||||
|
<button
|
||||||
|
className="dropdown-item py-1"
|
||||||
|
onClick={() => handleOpenDelete(item)}
|
||||||
|
>
|
||||||
|
<i className="bx bx-task-x bx-sm"></i> Suspend
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className="dropdown-item py-1"
|
className="dropdown-item py-1"
|
||||||
type="button"
|
type="button"
|
||||||
data-bs-toggle="modal"
|
data-bs-toggle="modal"
|
||||||
data-bs-target="#managerole-modal"
|
data-bs-target="#managerole-modal"
|
||||||
onClick={() =>
|
onClick={() => setEmpForManageRole(item.id)}
|
||||||
setEmpForManageRole(item.id)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<i className="bx bx-cog bx-sm"></i>{" "}
|
<i className="bx bx-cog bx-sm"></i> Manage Role
|
||||||
Manage Role
|
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* If INACTIVE employee AND inactive toggle is ON */}
|
||||||
|
{!item.isActive && showInactive && (
|
||||||
|
<button
|
||||||
|
className="dropdown-item py-1"
|
||||||
|
onClick={() => handleOpenDelete(item)}
|
||||||
|
>
|
||||||
|
<i className="bx bx-refresh bx-sm me-1"></i> Re-activate
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@ -683,9 +691,8 @@ useEffect(() => {
|
|||||||
<nav aria-label="Page">
|
<nav aria-label="Page">
|
||||||
<ul className="pagination pagination-sm justify-content-end py-1">
|
<ul className="pagination pagination-sm justify-content-end py-1">
|
||||||
<li
|
<li
|
||||||
className={`page-item ${
|
className={`page-item ${currentPage === 1 ? "disabled" : ""
|
||||||
currentPage === 1 ? "disabled" : ""
|
}`}
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
className="page-link btn-xs"
|
className="page-link btn-xs"
|
||||||
@ -698,9 +705,8 @@ useEffect(() => {
|
|||||||
{[...Array(totalPages)]?.map((_, index) => (
|
{[...Array(totalPages)]?.map((_, index) => (
|
||||||
<li
|
<li
|
||||||
key={index}
|
key={index}
|
||||||
className={`page-item ${
|
className={`page-item ${currentPage === index + 1 ? "active" : ""
|
||||||
currentPage === index + 1 ? "active" : ""
|
}`}
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
className="page-link"
|
className="page-link"
|
||||||
@ -712,9 +718,8 @@ useEffect(() => {
|
|||||||
))}
|
))}
|
||||||
|
|
||||||
<li
|
<li
|
||||||
className={`page-item ${
|
className={`page-item ${currentPage === totalPages ? "disabled" : ""
|
||||||
currentPage === totalPages ? "disabled" : ""
|
}`}
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
className="page-link"
|
className="page-link"
|
||||||
|
@ -3,6 +3,7 @@ import { useSearchParams, useParams, useNavigate } from "react-router-dom";
|
|||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
useEmployee,
|
||||||
useEmployeeProfile,
|
useEmployeeProfile,
|
||||||
useEmployees,
|
useEmployees,
|
||||||
useEmployeesByProject,
|
useEmployeesByProject,
|
||||||
@ -28,38 +29,20 @@ const EmployeeProfile = () => {
|
|||||||
|
|
||||||
const projectID = useSelector((store) => store.localVariables.projectId);
|
const projectID = useSelector((store) => store.localVariables.projectId);
|
||||||
const { employeeId } = useParams();
|
const { employeeId } = useParams();
|
||||||
// const {employee,loading} = useEmployeeProfile(employeeId)
|
|
||||||
const [loading, setLoading] = useState(true);
|
|
||||||
|
|
||||||
const [SearchParams] = useSearchParams();
|
const [SearchParams] = useSearchParams();
|
||||||
const tab = SearchParams.get("for");
|
const tab = SearchParams.get("for");
|
||||||
const [activePill, setActivePill] = useState(tab || "profile");
|
const [activePill, setActivePill] = useState(tab || "profile");
|
||||||
const [currentEmployee, setCurrentEmployee] = useState();
|
|
||||||
const [showModal, setShowModal] = useState(false);
|
const [showModal, setShowModal] = useState(false);
|
||||||
|
const {data:currentEmployee,isLoading,isError,error} = useEmployee(employeeId)
|
||||||
const handlePillClick = (pillKey) => {
|
const handlePillClick = (pillKey) => {
|
||||||
setActivePill(pillKey);
|
setActivePill(pillKey);
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchEmployeeProfile = async (employeeID) => {
|
|
||||||
try {
|
|
||||||
const resp = await EmployeeRepository.getEmployeeProfile(employeeID);
|
|
||||||
setCurrentEmployee(resp.data);
|
|
||||||
setLoading(false);
|
|
||||||
} catch (err) {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (employeeId) {
|
|
||||||
fetchEmployeeProfile(employeeId);
|
|
||||||
}
|
|
||||||
}, [employeeId]);
|
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const renderContent = () => {
|
const renderContent = () => {
|
||||||
if (loading) return <div>Loading</div>;
|
if (isLoading) return <div>Loading</div>;
|
||||||
switch (activePill) {
|
switch (activePill) {
|
||||||
case "profile": {
|
case "profile": {
|
||||||
return (
|
return (
|
||||||
@ -101,9 +84,10 @@ const EmployeeProfile = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (loading) {
|
if (isLoading) {
|
||||||
return <div>Loading...</div>;
|
return <div>Loading...</div>;
|
||||||
}
|
}
|
||||||
|
if(isError) return <div >{error.message}</div>
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="container-fluid">
|
<div className="container-fluid">
|
||||||
@ -138,4 +122,4 @@ const EmployeeProfile = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default EmployeeProfile;
|
export default EmployeeProfile;
|
Loading…
x
Reference in New Issue
Block a user