Compare commits
8 Commits
959e4dd7dd
...
e6a687c8e2
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e6a687c8e2 | ||
![]() |
21ca99455b | ||
![]() |
73ffbe9bf4 | ||
![]() |
f7f1f8d083 | ||
![]() |
f4af7ccf1c | ||
![]() |
79a1a08620 | ||
![]() |
fba9a8fc06 | ||
![]() |
5a7ca02952 |
@ -5,7 +5,8 @@ import { convertShortTime } from '../../utils/dateUtils';
|
|||||||
|
|
||||||
const AttendLogs = ({ Id }) => {
|
const AttendLogs = ({ Id }) => {
|
||||||
|
|
||||||
const {logs,loading} = useEmployeeAttendacesLog(Id)
|
const {logs, loading} = useEmployeeAttendacesLog( Id )
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="table-responsive">
|
<div className="table-responsive">
|
||||||
{loading && <p>Loading..</p>}
|
{loading && <p>Loading..</p>}
|
||||||
@ -26,20 +27,19 @@ const AttendLogs = ({ Id }) => {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{logs?.length > 0 ? (
|
{logs
|
||||||
logs?.map((log, index) => (
|
.slice()
|
||||||
<tr key={index}>
|
.sort((a, b) => new Date(b.activityTime) - new Date(a.activityTime))
|
||||||
<td>{convertShortTime(log.activityTime)}</td>
|
.map((log, index) => (
|
||||||
<td>{log.activityTime.slice(0,10)}</td>
|
<tr key={index}>
|
||||||
<td className="text-wrap" colSpan={3}>{log?.comment}</td>
|
<td>{convertShortTime(log.activityTime)}</td>
|
||||||
</tr>
|
<td>{log.activityTime.slice(0, 10)}</td>
|
||||||
))
|
<td className="text-wrap" colSpan={3}>
|
||||||
) : (
|
{log?.comment}
|
||||||
<tr>
|
</td>
|
||||||
<td colSpan="3">No Data Available</td>
|
</tr>
|
||||||
</tr>
|
))}
|
||||||
)}
|
</tbody>
|
||||||
</tbody>
|
|
||||||
</table>
|
</table>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
@ -30,7 +30,14 @@ const Attendance = ( {attendance, getRole, handleModalData} ) =>
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody className="table-border-bottom-0">
|
<tbody className="table-border-bottom-0">
|
||||||
{currentItems &&
|
{currentItems &&
|
||||||
currentItems.map((item) => (
|
currentItems
|
||||||
|
.sort((a, b) => {
|
||||||
|
// If checkInTime exists, compare it, otherwise, treat null as earlier than a date
|
||||||
|
const checkInA = a.checkInTime ? new Date(a.checkInTime) : new Date(0);
|
||||||
|
const checkInB = b.checkInTime ? new Date(b.checkInTime) : new Date(0);
|
||||||
|
return checkInB - checkInA; // Sort in descending order of checkInTime
|
||||||
|
})
|
||||||
|
.map( ( item ) => (
|
||||||
<tr key={item.id}>
|
<tr key={item.id}>
|
||||||
<td colSpan={2}>
|
<td colSpan={2}>
|
||||||
<div className="d-flex justify-content-start align-items-center">
|
<div className="d-flex justify-content-start align-items-center">
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
import { useProfile } from "../../hooks/useProfile";
|
||||||
|
|
||||||
const Dashboard = () => {
|
const Dashboard = () => {
|
||||||
|
const {profile,loading} = useProfile()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -11,7 +13,7 @@ const Dashboard = () => {
|
|||||||
<div className="d-flex align-items-end row">
|
<div className="d-flex align-items-end row">
|
||||||
<div className="col-sm-7">
|
<div className="col-sm-7">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<h5 className="card-title text-primary">Congratulations Ramchandra! 🎉</h5>
|
<h5 className="card-title text-primary">Congratulations {profile?.employeeInfo?.firstName }! 🎉</h5>
|
||||||
<p className="mb-4">
|
<p className="mb-4">
|
||||||
You have done <span className="fw-bold">72%</span> more sales today. Check your new badge in
|
You have done <span className="fw-bold">72%</span> more sales today. Check your new badge in
|
||||||
your profile.
|
your profile.
|
||||||
|
@ -7,16 +7,17 @@ import { z } from "zod";
|
|||||||
import useMaster from "../../hooks/masterHook/useMaster";
|
import useMaster from "../../hooks/masterHook/useMaster";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
import { changeMaster } from "../../slices/localVariablesSlice";
|
import { changeMaster } from "../../slices/localVariablesSlice";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { Link, useNavigate, useParams } from "react-router-dom";
|
||||||
import { formatDate } from "../../utils/dateUtils";
|
import { formatDate } from "../../utils/dateUtils";
|
||||||
import { useEmployeeProfile } from "../../hooks/useEmployees";
|
import { useEmployeeProfile } from "../../hooks/useEmployees";
|
||||||
import { clearCacheKey, getCachedData } from "../../slices/apiDataManager";
|
import { clearCacheKey, getCachedData } from "../../slices/apiDataManager";
|
||||||
import {clearApiCacheKey} from "../../slices/apiCacheSlice";
|
import {clearApiCacheKey} from "../../slices/apiCacheSlice";
|
||||||
|
|
||||||
const mobileNumberRegex = /^(?:\d{10}|\d{3}[-\s]?\d{3}[-\s]?\d{4})$/;
|
const mobileNumberRegex = /^[7-9]\d{9}$/;
|
||||||
|
|
||||||
const ManageEmployee = () => {
|
const ManageEmployee = () => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const { employeeId } = useParams();
|
const { employeeId } = useParams();
|
||||||
const {
|
const {
|
||||||
employee,
|
employee,
|
||||||
@ -29,7 +30,7 @@ const ManageEmployee = () => {
|
|||||||
const [isloading, setLoading] = useState(false);
|
const [isloading, setLoading] = useState(false);
|
||||||
const navigation = useNavigate();
|
const navigation = useNavigate();
|
||||||
const [currentEmployee, setCurrentEmployee] = useState();
|
const [currentEmployee, setCurrentEmployee] = useState();
|
||||||
console.log(currentEmployee);
|
|
||||||
|
|
||||||
const userSchema = z
|
const userSchema = z
|
||||||
.object({
|
.object({
|
||||||
@ -40,9 +41,17 @@ const ManageEmployee = () => {
|
|||||||
Email: z.string().optional(),
|
Email: z.string().optional(),
|
||||||
CurrentAddress: z
|
CurrentAddress: z
|
||||||
.string()
|
.string()
|
||||||
.min(1, { message: "Current Address is required" }),
|
.min(1, { message: "Current Address is required" }).max(150, { message: "Address cannot exceed 150 characters" }),
|
||||||
BirthDate: z.string().min(1, { message: "Birth Date is required" }),
|
BirthDate: z.string().min(1, { message: "Birth Date is required" }).refine((date, ctx) => {
|
||||||
JoiningDate: z.string().min(1, { message: "Joining Date is required" }),
|
return new Date(date) <= new Date();
|
||||||
|
}, {
|
||||||
|
message: "Birth date cannot be in the future",
|
||||||
|
}),
|
||||||
|
JoiningDate: z.string().min(1, { message: "Joining Date is required" }).refine((date, ctx) => {
|
||||||
|
return new Date(date) <= new Date();
|
||||||
|
}, {
|
||||||
|
message: "Joining date cannot be in the future",
|
||||||
|
}),
|
||||||
EmergencyPhoneNumber: z
|
EmergencyPhoneNumber: z
|
||||||
.string()
|
.string()
|
||||||
.min(1, { message: "Phone Number is required" })
|
.min(1, { message: "Phone Number is required" })
|
||||||
@ -50,68 +59,31 @@ const ManageEmployee = () => {
|
|||||||
EmergencyContactPerson: z
|
EmergencyContactPerson: z
|
||||||
.string()
|
.string()
|
||||||
.min(1, { message: "Emergency Contact Person is required" }),
|
.min(1, { message: "Emergency Contact Person is required" }),
|
||||||
AadharNumber: z.string().optional(),
|
AadharNumber: z.string()
|
||||||
|
.regex(/^\d{12}$/, "Aadhar card must be exactly 12 digits long")
|
||||||
|
.nonempty("Aadhar card is required"),
|
||||||
Gender: z
|
Gender: z
|
||||||
.string()
|
.string()
|
||||||
.min(1, { message: "Gender is required" })
|
.min(1, { message: "Gender is required" })
|
||||||
.refine((val) => val !== "Select Gender", {
|
.refine((val) => val !== "Select Gender", {
|
||||||
message: "Please select a gender",
|
message: "Please select a gender",
|
||||||
}),
|
}),
|
||||||
PanNumber: z.string().optional(),
|
PanNumber: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.refine((val) => !val || /^[A-Z]{5}[0-9]{4}[A-Z]{1}$/.test(val), {
|
||||||
|
message: "Invalid PAN number",
|
||||||
|
}),
|
||||||
PeramnentAddress: z
|
PeramnentAddress: z
|
||||||
.string()
|
.string()
|
||||||
.min(1, { message: "Permanent Address is required" }),
|
.min(1, { message: "Permanent Address is required" }).max(150, { message: "Address cannot exceed 150 characters" }),
|
||||||
PhoneNumber: z
|
PhoneNumber: z
|
||||||
.string()
|
.string()
|
||||||
.min(1, { message: "Phone Number is required" })
|
.min(1, { message: "Phone Number is required" })
|
||||||
.regex(mobileNumberRegex, { message: "Invalid phone number " }),
|
.regex(mobileNumberRegex, { message: "Invalid phone number " }),
|
||||||
JobRoleId: z.string().min(1, { message: "Role is required" }),
|
JobRoleId: z.string().min(1, { message: "Role is required" }),
|
||||||
// Documents: z
|
|
||||||
// .array(z.unknown())
|
|
||||||
// // .optional()
|
|
||||||
// .default([])
|
|
||||||
// .refine((value) => value.length > 0, {
|
|
||||||
// message: "Documents is required",
|
|
||||||
// })
|
|
||||||
// .refine((value) => {
|
|
||||||
// return value.every((file) => file.size <= 5000000); //this required if want
|
|
||||||
// }, "Each file must be less than 5MB")
|
|
||||||
// .refine((value) => {
|
|
||||||
// if (!value || value.length === 0) return true;
|
|
||||||
// return value.every((file) =>
|
|
||||||
// ["application/pdf", "application/msword", "image/jpeg", "image/png"].includes(file.type)
|
|
||||||
// );
|
|
||||||
// }, "Only PDF, Word, and image files are allowed"),
|
|
||||||
// Photo: z
|
|
||||||
// .unknown()
|
|
||||||
// .default(null)
|
|
||||||
|
|
||||||
// .refine((value) => value !== undefined && value !== null, {
|
|
||||||
// message: "Photo is required",
|
|
||||||
// })
|
|
||||||
// .refine((value) => value?.size <= 5000000, { //this required if want
|
|
||||||
// message: "The file must be less than 5MB", //size
|
|
||||||
// })
|
|
||||||
// .refine((value) => {
|
|
||||||
// if (!value || value.length === 0) return true;
|
|
||||||
// return value && ["image/jpeg", "image/png", "image/jpg"].includes(value?.type);
|
|
||||||
// }, { message: "Only JPEG and PNG images are allowed" }),
|
|
||||||
})
|
})
|
||||||
.superRefine((data, ctx) => {
|
|
||||||
if (!data.AadharNumber && !data.PanNumber) {
|
|
||||||
ctx.addIssue({
|
|
||||||
code: z.ZodIssueCode.custom,
|
|
||||||
message: "Either Aadhar Number or Pan Number is required.",
|
|
||||||
path: ["AadharNumber"], // Add error to AadharNumber
|
|
||||||
});
|
|
||||||
|
|
||||||
ctx.addIssue({
|
|
||||||
code: z.ZodIssueCode.custom,
|
|
||||||
message: "Either Aadhar Number or Pan Number is required.",
|
|
||||||
path: ["PanNumber"], // Add error to PanNumber
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
@ -139,8 +111,6 @@ const ManageEmployee = () => {
|
|||||||
PeramnentAddress: currentEmployee?.peramnentAddress || "",
|
PeramnentAddress: currentEmployee?.peramnentAddress || "",
|
||||||
PhoneNumber: currentEmployee?.phoneNumber || "",
|
PhoneNumber: currentEmployee?.phoneNumber || "",
|
||||||
JobRoleId: currentEmployee?.jobRoleId || "",
|
JobRoleId: currentEmployee?.jobRoleId || "",
|
||||||
// Documents: currentEmployee?.documents || [],
|
|
||||||
// Photo: currentEmployee?.photo || null
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -172,13 +142,11 @@ const ManageEmployee = () => {
|
|||||||
EmployeeRepository.manageEmployee(formDataToSend)
|
EmployeeRepository.manageEmployee(formDataToSend)
|
||||||
.then( ( response ) =>
|
.then( ( response ) =>
|
||||||
{
|
{
|
||||||
|
|
||||||
showToast("Employee details updated successfully.", "success" );
|
showToast("Employee details updated successfully.", "success" );
|
||||||
clearCacheKey("employeeListByProject")
|
clearCacheKey("employeeListByProject")
|
||||||
clearCacheKey("allEmployeeList")
|
clearCacheKey( "allEmployeeList" )
|
||||||
navigation("/employees");
|
|
||||||
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
navigation("/employees");
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
showToast(error.message, "error");
|
showToast(error.message, "error");
|
||||||
@ -215,16 +183,11 @@ const ManageEmployee = () => {
|
|||||||
PeramnentAddress: currentEmployee.peramnentAddress || "",
|
PeramnentAddress: currentEmployee.peramnentAddress || "",
|
||||||
PhoneNumber: currentEmployee.phoneNumber || "",
|
PhoneNumber: currentEmployee.phoneNumber || "",
|
||||||
JobRoleId: currentEmployee.jobRoleId?.toString() || "",
|
JobRoleId: currentEmployee.jobRoleId?.toString() || "",
|
||||||
// Documents: currentEmployee.documents || [],
|
|
||||||
// Photo: currentEmployee.photo || null,
|
|
||||||
}
|
}
|
||||||
: {} // Empty object resets the form
|
: {} // Empty object resets the form
|
||||||
);
|
);
|
||||||
// if(currentEmployee && currentEmployee.email) setDisabledEmail(true)
|
|
||||||
}, [currentEmployee, reset]);
|
}, [currentEmployee, reset]);
|
||||||
|
|
||||||
console.log(currentEmployee);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
@ -232,9 +195,13 @@ const ManageEmployee = () => {
|
|||||||
<div className="card mb-4">
|
<div className="card mb-4">
|
||||||
<div className="card-header d-flex align-items-center justify-content-between">
|
<div className="card-header d-flex align-items-center justify-content-between">
|
||||||
<h6 className="mb-0">
|
<h6 className="mb-0">
|
||||||
{" "}
|
|
||||||
{employee ? "Update Employee" : "Create Employee"}
|
{employee ? "Update Employee" : "Create Employee"}
|
||||||
</h6>
|
</h6>
|
||||||
|
|
||||||
|
<span className="cursor-pointer fs-6" data-htm="true" data-bs-toggle="tooltip"
|
||||||
|
data-bs-offset="0,6"
|
||||||
|
data-bs-placement="top"
|
||||||
|
data-bs-html="true" title="Move Back" onClick={()=>navigation("/employees")}><i class='bx bxs-chevron-left'></i> Back</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
{!currentEmployee && empLoading && (
|
{!currentEmployee && empLoading && (
|
||||||
@ -304,14 +271,12 @@ const ManageEmployee = () => {
|
|||||||
<div className="row mb-3">
|
<div className="row mb-3">
|
||||||
<div className="col-sm-6">
|
<div className="col-sm-6">
|
||||||
<div className="form-text text-start">Email</div>
|
<div className="form-text text-start">Email</div>
|
||||||
|
|
||||||
{/* <div className="input-group input-group-merge"> */}
|
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
id="Email"
|
id="Email"
|
||||||
{...register("Email")}
|
{...register("Email")}
|
||||||
className="form-control form-control-sm"
|
className="form-control form-control-sm"
|
||||||
placeholder="Email"
|
placeholder="example@domain.com"
|
||||||
aria-label=""
|
aria-label=""
|
||||||
aria-describedby="Email"
|
aria-describedby="Email"
|
||||||
disabled={!!currentEmployee?.email}
|
disabled={!!currentEmployee?.email}
|
||||||
@ -325,7 +290,7 @@ const ManageEmployee = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* </div> */}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="col-sm-6">
|
<div className="col-sm-6">
|
||||||
<div className="form-text text-start">Phone Number</div>
|
<div className="form-text text-start">Phone Number</div>
|
||||||
@ -335,7 +300,7 @@ const ManageEmployee = () => {
|
|||||||
id="PhoneNumber"
|
id="PhoneNumber"
|
||||||
{...register("PhoneNumber")}
|
{...register("PhoneNumber")}
|
||||||
className="form-control form-control-sm"
|
className="form-control form-control-sm"
|
||||||
placeholder="000 000 0000"
|
placeholder="Phone Number"
|
||||||
/>
|
/>
|
||||||
{errors.PhoneNumber && (
|
{errors.PhoneNumber && (
|
||||||
<div
|
<div
|
||||||
@ -479,7 +444,7 @@ const ManageEmployee = () => {
|
|||||||
Select Role
|
Select Role
|
||||||
</option>
|
</option>
|
||||||
{job_role?.map((item) => (
|
{job_role?.map((item) => (
|
||||||
<option value={item?.id}>{item?.name} </option>
|
<option value={item?.id} key={item.id}>{item?.name} </option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@ -544,9 +509,9 @@ const ManageEmployee = () => {
|
|||||||
id="AadharNumber"
|
id="AadharNumber"
|
||||||
placeholder="AADHAR Number"
|
placeholder="AADHAR Number"
|
||||||
/>
|
/>
|
||||||
{errors.root?.AadharNumber && (
|
{errors.AadharNumber && (
|
||||||
<div className="danger-text text-start">
|
<div className="danger-text text-start">
|
||||||
{errors.AadharNumber.root?.message}
|
{errors.AadharNumber.message}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -560,67 +525,9 @@ const ManageEmployee = () => {
|
|||||||
id="PanNumber"
|
id="PanNumber"
|
||||||
placeholder="PAN Number"
|
placeholder="PAN Number"
|
||||||
/>
|
/>
|
||||||
{/* {errors.PanNumber && <div className="danger-text text-start" style={{fontSize:"12px"}}>{errors.PanNumber.message}</div>} */}
|
{errors.PanNumber && <div className="danger-text text-start" style={{fontSize:"12px"}}>{errors.PanNumber.message}</div>}
|
||||||
</div>
|
</div>
|
||||||
{(errors.PanNumber || errors.AadharNumber) && (
|
|
||||||
<div className="danger-text text-start">
|
|
||||||
{errors.PanNumber?.message ||
|
|
||||||
errors.AadharNumber?.message}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
{/* <div className="row mb-3">
|
|
||||||
<div className="col-sm-12">
|
|
||||||
<div className="form-text text-start">Upload Photo</div>
|
|
||||||
<Controller
|
|
||||||
name="Photo"
|
|
||||||
control={control}
|
|
||||||
render={({ field }) => (
|
|
||||||
<input
|
|
||||||
type="file"
|
|
||||||
accept="image/*"
|
|
||||||
className="form-control form-control-sm"
|
|
||||||
onChange={(e) => {
|
|
||||||
field.onChange(e.target.files[0]);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
{errors.Photo && <div className="danger-text text-start" style={{fontSize:"12px"}}>{errors.Photo.message}</div>}
|
|
||||||
</div>
|
|
||||||
</div> */}
|
|
||||||
{/* <div className="row mb-3">
|
|
||||||
<div className="col-sm-12">
|
|
||||||
<div className="form-text text-start">Upload Documents</div>
|
|
||||||
|
|
||||||
<Controller
|
|
||||||
name="Documents"
|
|
||||||
control={control}
|
|
||||||
render={({ field }) => (
|
|
||||||
<input
|
|
||||||
type="file"
|
|
||||||
accept=".doc,.docx,.pdf,image/*"
|
|
||||||
multiple
|
|
||||||
className="form-control form-control-sm"
|
|
||||||
onChange={(e) => {
|
|
||||||
|
|
||||||
field.onChange(Array.from(e.target.files));
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className="form-text text-start mt-1">
|
|
||||||
{getValues("Documents") && Array.from(getValues("Documents")).map((item, index) => (
|
|
||||||
<span key={index} className="ms-1 mt-1 badge rounded-pill bg-secondary">
|
|
||||||
{item.name}
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
{errors.Documents && <div className="danger-text text-start" style={{fontSize:"12px"}}>{errors.Documents.message}</div>}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div> */}
|
|
||||||
|
|
||||||
{employeeId && (
|
{employeeId && (
|
||||||
<div className="row mb-3 d-none">
|
<div className="row mb-3 d-none">
|
||||||
|
@ -29,7 +29,6 @@ const ManageRole = ({employeeId,onClosed}) => {
|
|||||||
|
|
||||||
const buildDefaultRoles = () => {
|
const buildDefaultRoles = () => {
|
||||||
const defaults = {};
|
const defaults = {};
|
||||||
|
|
||||||
data.forEach((role) => {
|
data.forEach((role) => {
|
||||||
const isRoleEnabled = employeeRoles?.data?.some((empRole) => empRole.roleId === role.id);
|
const isRoleEnabled = employeeRoles?.data?.some((empRole) => empRole.roleId === role.id);
|
||||||
defaults[role.id] = isRoleEnabled;
|
defaults[role.id] = isRoleEnabled;
|
||||||
@ -76,10 +75,8 @@ const ManageRole = ({employeeId,onClosed}) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RolesRepository.createEmployeeRoles( result ).then( ( resp ) =>
|
RolesRepository.createEmployeeRoles( result ).then( ( resp ) =>
|
||||||
{
|
{
|
||||||
|
|
||||||
showToast( "Role assigned successfully", "success" )
|
showToast( "Role assigned successfully", "success" )
|
||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
onClosed()
|
onClosed()
|
||||||
@ -90,11 +87,8 @@ const ManageRole = ({employeeId,onClosed}) => {
|
|||||||
showToast(err.message,"error")
|
showToast(err.message,"error")
|
||||||
})
|
})
|
||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
<div className={`modal fade `} id="managerole-modal" tabIndex="-1" aria-hidden="true" >
|
<div className={`modal fade `} id="managerole-modal" tabIndex="-1" aria-hidden="true" >
|
||||||
@ -118,9 +112,9 @@ const ManageRole = ({employeeId,onClosed}) => {
|
|||||||
|
|
||||||
{(loading || roleLoading) && <p>Loading...</p>}
|
{(loading || roleLoading) && <p>Loading...</p>}
|
||||||
{data && data.map((item) => (
|
{data && data.map((item) => (
|
||||||
<>
|
|
||||||
|
|
||||||
<div className="col-md-6 col-lg-4 mb-4">
|
<div className="col-md-6 col-lg-4 mb-4" key={item.id}>
|
||||||
<div className="form-check ms-2 text-start">
|
<div className="form-check ms-2 text-start">
|
||||||
<input
|
<input
|
||||||
className="form-check-input"
|
className="form-check-input"
|
||||||
@ -135,7 +129,7 @@ const ManageRole = ({employeeId,onClosed}) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</>
|
|
||||||
))}
|
))}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,7 +5,7 @@ const Footer = () => {
|
|||||||
<div className="container-xxl d-flex flex-wrap justify-content-between py-2 flex-md-row flex-column">
|
<div className="container-xxl d-flex flex-wrap justify-content-between py-2 flex-md-row flex-column">
|
||||||
<div className="mb-2 mb-md-0" style={{width: "100%", textAlign: "right"}}>
|
<div className="mb-2 mb-md-0" style={{width: "100%", textAlign: "right"}}>
|
||||||
© {new Date().getFullYear()}
|
© {new Date().getFullYear()}
|
||||||
, by <a href="https://marcosolutions.co.in/" target="_blank" className="font-weight-light footer-link">MARCO AIoT Softwares Pvt. Ltd.</a>
|
, by <a href="https://marcosolutions.co.in/" target="_blank" className="font-weight-light footer-link">MARCO AIoT Technologies Pvt. Ltd.</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -27,7 +27,7 @@ const ManageProjectInfo = ( {project,handleSubmitForm, onClose} ) =>
|
|||||||
...(project?.id ? { id: z.number().optional() } : {}),
|
...(project?.id ? { id: z.number().optional() } : {}),
|
||||||
name: z.string().min( 1, {message: "Project Name is required"} ),
|
name: z.string().min( 1, {message: "Project Name is required"} ),
|
||||||
contactPerson: z.string().min( 1, {message: "Contact Person Name is required"} ),
|
contactPerson: z.string().min( 1, {message: "Contact Person Name is required"} ),
|
||||||
projectAddress: z.string().min( 1, {message: "Address is required"} ),
|
projectAddress: z.string().min( 1, {message: "Address is required"} ).max(150, 'Address must not exceed 150 characters'),
|
||||||
startDate: z.string().min( 1, {message: "Start Date is required"} ).default(currentDate),
|
startDate: z.string().min( 1, {message: "Start Date is required"} ).default(currentDate),
|
||||||
endDate: z.string().min( 1, {message: "End Date is required"} ).default(currentDate),
|
endDate: z.string().min( 1, {message: "End Date is required"} ).default(currentDate),
|
||||||
projectStatusId: z
|
projectStatusId: z
|
||||||
|
@ -134,12 +134,12 @@ const allocationEmployeesData = employeesList
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-footer">
|
<div className="modal-footer">
|
||||||
<button className="btn btn-success" onClick={handleSubmit}>
|
<button className="btn btn-sm btn-success" onClick={handleSubmit}>
|
||||||
Assign to Project
|
Assign to Project
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-secondary"
|
className="btn btn-sm btn-secondary"
|
||||||
data-dismiss="modal"
|
data-dismiss="modal"
|
||||||
aria-label="Close"
|
aria-label="Close"
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
|
@ -7,6 +7,8 @@ import ManageProjectInfo from "./ManageProjectInfo";
|
|||||||
import ProjectRepository from "../../repositories/ProjectRepository";
|
import ProjectRepository from "../../repositories/ProjectRepository";
|
||||||
import {cacheData, getCachedData} from "../../slices/apiDataManager";
|
import {cacheData, getCachedData} from "../../slices/apiDataManager";
|
||||||
import showToast from "../../services/toastService";
|
import showToast from "../../services/toastService";
|
||||||
|
import {useHasUserPermission} from "../../hooks/useHasUserPermission";
|
||||||
|
import {MANAGE_PROJECT} from "../../utils/constants";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -16,7 +18,8 @@ const ProjectCard = ( {projectData} ) =>
|
|||||||
const[projectInfo,setProjectInfo] = useState(projectData)
|
const[projectInfo,setProjectInfo] = useState(projectData)
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const {projects_Details, loading} = useProjectDetails( projectData.id )
|
const {projects_Details, loading} = useProjectDetails( projectData.id )
|
||||||
const [showModal, setShowModal] = useState(false);
|
const [ showModal, setShowModal ] = useState( false );
|
||||||
|
const ManageProject = useHasUserPermission(MANAGE_PROJECT)
|
||||||
|
|
||||||
const handleShow = () => setShowModal(true);
|
const handleShow = () => setShowModal(true);
|
||||||
const handleClose = () => setShowModal( false );
|
const handleClose = () => setShowModal( false );
|
||||||
@ -144,7 +147,7 @@ const ProjectCard = ( {projectData} ) =>
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="ms-auto">
|
<div className={`ms-auto ${!ManageProject && 'd-none'}`}>
|
||||||
<div className="dropdown z-2">
|
<div className="dropdown z-2">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -7,6 +7,8 @@ import WorkAreaModel from "./WorkAreaModel";
|
|||||||
import TaskModel from "./TaskModel";
|
import TaskModel from "./TaskModel";
|
||||||
import ProjectRepository from "../../repositories/ProjectRepository";
|
import ProjectRepository from "../../repositories/ProjectRepository";
|
||||||
import ProjectModal from "./ProjectModal";
|
import ProjectModal from "./ProjectModal";
|
||||||
|
import {useHasUserPermission} from "../../hooks/useHasUserPermission";
|
||||||
|
import {MANAGE_PROJECT_INFRA} from "../../utils/constants";
|
||||||
// import AssignRoleModel from "./AssignRoleModel";
|
// import AssignRoleModel from "./AssignRoleModel";
|
||||||
|
|
||||||
const ProjectInfra = ({ data, activityMaster, onDataChange,eachSiteEngineer }) => {
|
const ProjectInfra = ({ data, activityMaster, onDataChange,eachSiteEngineer }) => {
|
||||||
@ -14,7 +16,8 @@ const ProjectInfra = ({ data, activityMaster, onDataChange,eachSiteEngineer }) =
|
|||||||
const [expandedBuildings, setExpandedBuildings] = useState([]);
|
const [expandedBuildings, setExpandedBuildings] = useState([]);
|
||||||
const [project, setProject] = useState(data);
|
const [project, setProject] = useState(data);
|
||||||
const[modalConfig,setModalConfig] = useState({type:null,data:null});
|
const[modalConfig,setModalConfig] = useState({type:null,data:null});
|
||||||
const[isModalOpen,setIsModalOpen] = useState(false)
|
const [ isModalOpen, setIsModalOpen ] = useState( false )
|
||||||
|
const ManageInfra = useHasUserPermission(MANAGE_PROJECT_INFRA)
|
||||||
|
|
||||||
const [buildings, setBuildings] = useState(data.buildings);
|
const [buildings, setBuildings] = useState(data.buildings);
|
||||||
const [isBuildingModalOpen, setIsBuildingModalOpen] = useState(false);
|
const [isBuildingModalOpen, setIsBuildingModalOpen] = useState(false);
|
||||||
@ -514,11 +517,11 @@ const ProjectInfra = ({ data, activityMaster, onDataChange,eachSiteEngineer }) =
|
|||||||
|
|
||||||
<div className="card-body" style={{ padding: "0.5rem" }}>
|
<div className="card-body" style={{ padding: "0.5rem" }}>
|
||||||
<div className="align-items-center">
|
<div className="align-items-center">
|
||||||
<div className="row">
|
<div className="row ">
|
||||||
<div className="col-12 text-end mb-1">
|
<div className={`col-12 text-end mb-1 ${!ManageInfra && 'd-none'} `} >
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="link-button link-button-sm m-1"
|
className="link-button link-button-sm m-1 "
|
||||||
data-bs-toggle="modal"
|
data-bs-toggle="modal"
|
||||||
data-bs-target="#building-model"
|
data-bs-target="#building-model"
|
||||||
onClick={() => openBuildingModel()}
|
onClick={() => openBuildingModel()}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {hasUserPermission} from "../../utils/authUtils";
|
import {hasUserPermission} from "../../utils/authUtils";
|
||||||
import {useHasUserPermission} from "../../hooks/useHasUserPermission";
|
import {useHasUserPermission} from "../../hooks/useHasUserPermission";
|
||||||
import {INFRASTRUCTURE} from "../../utils/constants";
|
import { VIEW_PROJECT_INFRA} from "../../utils/constants";
|
||||||
|
|
||||||
const ProjectNav = ( {onPillClick, activePill} ) =>
|
const ProjectNav = ( {onPillClick, activePill} ) =>
|
||||||
{
|
{
|
||||||
const HasInfraStructure = useHasUserPermission( INFRASTRUCTURE )
|
const HasViewInfraStructure = useHasUserPermission( VIEW_PROJECT_INFRA )
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="col-md-12">
|
<div className="col-md-12">
|
||||||
@ -35,7 +35,7 @@ const ProjectNav = ( {onPillClick, activePill} ) =>
|
|||||||
<i className="bx bx-group bx-sm me-1_5"></i> Teams
|
<i className="bx bx-group bx-sm me-1_5"></i> Teams
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li className={`nav-item ${HasInfraStructure ? "":"d-none"} `}>
|
<li className={`nav-item ${HasViewInfraStructure ? "":"d-none"} `}>
|
||||||
<a
|
<a
|
||||||
className={`nav-link ${activePill === "infra" ? "active" : ""}`}
|
className={`nav-link ${activePill === "infra" ? "active" : ""}`}
|
||||||
href="#"
|
href="#"
|
||||||
|
@ -9,7 +9,7 @@ import {useDispatch} from "react-redux";
|
|||||||
import {changeMaster} from "../../slices/localVariablesSlice";
|
import {changeMaster} from "../../slices/localVariablesSlice";
|
||||||
import useMaster from "../../hooks/masterHook/useMaster"
|
import useMaster from "../../hooks/masterHook/useMaster"
|
||||||
import {useHasUserPermission} from "../../hooks/useHasUserPermission"
|
import {useHasUserPermission} from "../../hooks/useHasUserPermission"
|
||||||
import {ASSIGN_USER_TO_PROJECT} from "../../utils/constants";
|
import {ASSIGN_TO_PROJECT} from "../../utils/constants";
|
||||||
|
|
||||||
|
|
||||||
const Teams = ( {project} ) =>
|
const Teams = ( {project} ) =>
|
||||||
@ -24,7 +24,7 @@ const Teams = ( {project} ) =>
|
|||||||
const [employees, setEmployees] = useState([]);
|
const [employees, setEmployees] = useState([]);
|
||||||
const [ filteredEmployees, setFilteredEmployees ] = useState( [] );
|
const [ filteredEmployees, setFilteredEmployees ] = useState( [] );
|
||||||
|
|
||||||
const HasAssignUserPermission = useHasUserPermission( ASSIGN_USER_TO_PROJECT )
|
const HasAssignUserPermission = useHasUserPermission( ASSIGN_TO_PROJECT )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ const Teams = ( {project} ) =>
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
submitAllocations(items)
|
submitAllocations(items)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,9 +6,9 @@ const Breadcrumb = ({ data }) => {
|
|||||||
return (
|
return (
|
||||||
<nav aria-label="breadcrumb">
|
<nav aria-label="breadcrumb">
|
||||||
<ol className="breadcrumb breadcrumb-style1">
|
<ol className="breadcrumb breadcrumb-style1">
|
||||||
{data.map((item) =>
|
{data.map((item,index) =>
|
||||||
item.link ? (
|
item.link ? (
|
||||||
<li className="breadcrumb-item cursor-pointer">
|
<li className="breadcrumb-item cursor-pointer" key={index}>
|
||||||
<a
|
<a
|
||||||
aria-label="pagination link link-underline-primary "
|
aria-label="pagination link link-underline-primary "
|
||||||
onClick={()=>navigate(item.link)}
|
onClick={()=>navigate(item.link)}
|
||||||
|
@ -10,7 +10,8 @@ import showToast from '../../services/toastService';
|
|||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
role: z.string().min(1, { message: "Role is required" }),
|
role: z.string().min(1, { message: "Role is required" }),
|
||||||
description: z.string().min(1, { message: "Description is required" }),
|
description: z.string().min(1, { message: "Description is required" })
|
||||||
|
.max(255, { message: "Description cannot exceed 255 characters" }),
|
||||||
});
|
});
|
||||||
|
|
||||||
const CreateJobRole = ({onClose}) => {
|
const CreateJobRole = ({onClose}) => {
|
||||||
|
@ -15,7 +15,8 @@ import showToast from "../../services/toastService";
|
|||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
role: z.string().min(1, { message: "Role is required" }),
|
role: z.string().min(1, { message: "Role is required" }),
|
||||||
description: z.string().min(1, { message: "Description is required" }),
|
description: z.string().min(1, { message: "Description is required" })
|
||||||
|
.max(255, { message: "Description cannot exceed 255 characters" }),
|
||||||
|
|
||||||
selectedPermissions: z
|
selectedPermissions: z
|
||||||
.array(z.string())
|
.array(z.string())
|
||||||
|
@ -10,7 +10,8 @@ import showToast from '../../services/toastService';
|
|||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
role: z.string().min(1, { message: "Role is required" }),
|
role: z.string().min(1, { message: "Role is required" }),
|
||||||
description: z.string().min(1, { message: "Description is required" }),
|
description: z.string().min(1, { message: "Description is required" })
|
||||||
|
.max(255, { message: "Description cannot exceed 255 characters" }),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,7 +17,8 @@ import showToast from "../../services/toastService";
|
|||||||
|
|
||||||
const updateSchema = z.object({
|
const updateSchema = z.object({
|
||||||
role: z.string().min(1, { message: "Role is required" }),
|
role: z.string().min(1, { message: "Role is required" }),
|
||||||
description: z.string().min(1, { message: "Description is required" }),
|
description: z.string().min(1, { message: "Description is required" })
|
||||||
|
.max(255, { message: "Description cannot exceed 255 characters" }),
|
||||||
permissions: z.record(z.boolean()).refine((permission) => Object.values(permission).includes(true), {
|
permissions: z.record(z.boolean()).refine((permission) => Object.values(permission).includes(true), {
|
||||||
message: "At least one permission must be selected",
|
message: "At least one permission must be selected",
|
||||||
}),
|
}),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
export const mastersList = [{id:1, name: "Role"},{id:2, name: "Job Role"}, {id:3, name: "Status"},{id:4,name:"Module"}]
|
export const mastersList = [{id:1, name: "Role"},{id:2, name: "Job Role"}]
|
||||||
|
|
||||||
export const dailyTask = [
|
export const dailyTask = [
|
||||||
{
|
{
|
||||||
|
@ -111,8 +111,13 @@ export const useEmployeeRoles = (employeeId)=>{
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect( () =>
|
||||||
fetchData(employeeId);
|
{
|
||||||
|
if ( employeeId )
|
||||||
|
{
|
||||||
|
fetchData(employeeId);
|
||||||
|
|
||||||
|
}
|
||||||
},[employeeId])
|
},[employeeId])
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,17 +12,20 @@ import { useDispatch, useSelector } from "react-redux";
|
|||||||
import { setProjectId } from "../../slices/localVariablesSlice";
|
import { setProjectId } from "../../slices/localVariablesSlice";
|
||||||
import {markCurrentAttendance} from "../../slices/apiSlice/attendanceAllSlice";
|
import {markCurrentAttendance} from "../../slices/apiSlice/attendanceAllSlice";
|
||||||
import { hasUserPermission } from "../../utils/authUtils";
|
import { hasUserPermission } from "../../utils/authUtils";
|
||||||
|
import {useHasUserPermission} from "../../hooks/useHasUserPermission";
|
||||||
|
import {REGULARIZE_ATTENDANCE} from "../../utils/constants";
|
||||||
|
|
||||||
const AttendancePage = () =>
|
const AttendancePage = () =>
|
||||||
{
|
{
|
||||||
const loginUser = getCachedProfileData()
|
const loginUser = getCachedProfileData()
|
||||||
const selectedProject = useSelector((store)=>store.localVariables.projectId)
|
var selectedProject = useSelector( ( store ) => store.localVariables.projectId )
|
||||||
const {projects,loading:projectLoading} = useProjects()
|
const {projects,loading:projectLoading} = useProjects()
|
||||||
const {attendance,loading:attLoading} = useAttendace(selectedProject)
|
const {attendance,loading:attLoading} = useAttendace(selectedProject)
|
||||||
const[attendances,setAttendances] = useState()
|
const[attendances,setAttendances] = useState()
|
||||||
const [empRoles, setEmpRoles] = useState(null);
|
const [empRoles, setEmpRoles] = useState(null);
|
||||||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
||||||
const [modelConfig, setModelConfig] = useState();
|
const [ modelConfig, setModelConfig ] = useState();
|
||||||
|
const DoRegularized = useHasUserPermission(REGULARIZE_ATTENDANCE)
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
|
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
@ -57,13 +60,11 @@ const AttendancePage = () =>
|
|||||||
modalElement.style.display = 'none';
|
modalElement.style.display = 'none';
|
||||||
document.body.classList.remove('modal-open');
|
document.body.classList.remove('modal-open');
|
||||||
document.querySelector('.modal-backdrop').remove();
|
document.querySelector('.modal-backdrop').remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const handleSubmit = ( formData ) =>{
|
const handleSubmit = ( formData ) =>{
|
||||||
|
|
||||||
dispatch( markCurrentAttendance( formData ) ).then( ( action ) =>
|
dispatch( markCurrentAttendance( formData ) ).then( ( action ) =>
|
||||||
{
|
{
|
||||||
const updatedAttendance = attendances.map(item =>
|
const updatedAttendance = attendances.map(item =>
|
||||||
@ -164,8 +165,8 @@ const AttendancePage = () =>
|
|||||||
Logs
|
Logs
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
{hasUserPermission("52c9cf54-1eb2-44d2-81bb-524cf29c0a94") && (
|
|
||||||
<li class="nav-item">
|
<li className={`nav-item ${!DoRegularized && 'd-none'}`}>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="nav-link "
|
className="nav-link "
|
||||||
@ -178,14 +179,14 @@ const AttendancePage = () =>
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
)}
|
|
||||||
</ul>
|
</ul>
|
||||||
<div class="tab-content attedanceTabs py-2">
|
<div class="tab-content attedanceTabs py-2">
|
||||||
{projectLoading && (<span>Loading..</span>)}
|
{projectLoading && (<span>Loading..</span>)}
|
||||||
{(!projectLoading && !attendances) && <span>Not Found</span>}
|
{(!projectLoading && !attendances) && <span>Not Found</span>}
|
||||||
{ (projects && projects.length > 0 ) && (
|
{ (projects && projects.length > 0 ) && (
|
||||||
<>
|
<>
|
||||||
<div className="tab-pane fade show active py-0" id="navs-top-home" role="tabpanel">
|
<div className="tab-pane fade show active py-0" id="navs-top-home" role="tabpanel" key={projects.id}>
|
||||||
|
|
||||||
<Attendance attendance={attendances} handleModalData={handleModalData} getRole={getRole} />
|
<Attendance attendance={attendances} handleModalData={handleModalData} getRole={getRole} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -8,14 +8,15 @@ import {useEmployeesAllOrByProjectId} from "../../hooks/useEmployees";
|
|||||||
import { useProjects } from "../../hooks/useProjects";
|
import { useProjects } from "../../hooks/useProjects";
|
||||||
import { useProfile } from "../../hooks/useProfile";
|
import { useProfile } from "../../hooks/useProfile";
|
||||||
import {hasUserPermission} from "../../utils/authUtils";
|
import {hasUserPermission} from "../../utils/authUtils";
|
||||||
|
import {MANAGE_EMPLOYEES} from "../../utils/constants";
|
||||||
|
import {useHasUserPermission} from "../../hooks/useHasUserPermission";
|
||||||
|
|
||||||
const EmployeeList = () =>
|
const EmployeeList = () =>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
const {profile:loginUser}= useProfile()
|
const {profile:loginUser}= useProfile()
|
||||||
const [selectedProject, setSelectedProject] = useState("");
|
const [selectedProject, setSelectedProject] = useState("");
|
||||||
const {projects, loading: projectLoading} = useProjects()
|
const {projects, loading: projectLoading} = useProjects()
|
||||||
|
const ManageEmployee = useHasUserPermission(MANAGE_EMPLOYEES)
|
||||||
|
|
||||||
const {employees, loading,setLoading, error} = useEmployeesAllOrByProjectId( selectedProject );
|
const {employees, loading,setLoading, error} = useEmployeesAllOrByProjectId( selectedProject );
|
||||||
const [ projectsList, setProjectsList ] = useState(projects || [] );
|
const [ projectsList, setProjectsList ] = useState(projects || [] );
|
||||||
@ -45,31 +46,19 @@ const EmployeeList = () =>
|
|||||||
setFilteredData(results);
|
setFilteredData(results);
|
||||||
};
|
};
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// if ( loginUser && projects )
|
|
||||||
// {
|
|
||||||
// const filteredProjects = projects.filter((project) =>
|
|
||||||
// loginUser?.projects?.map(Number).includes(project.id)
|
|
||||||
// );
|
|
||||||
// setProjectsList(filteredProjects);
|
|
||||||
// }
|
|
||||||
// }, [ loginUser, projects ] );
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCurrentPage( 1 )
|
setCurrentPage( 1 )
|
||||||
|
|
||||||
if (!loading && Array.isArray(employees)) {
|
if (!loading && Array.isArray(employees)) {
|
||||||
setEmployeeList(employees);
|
setEmployeeList(employees);
|
||||||
setFilteredData(employees);
|
setFilteredData( employees );
|
||||||
}
|
}
|
||||||
|
|
||||||
}, [loading, employees, selectedProject]);
|
}, [loading, employees, selectedProject]);
|
||||||
|
|
||||||
|
|
||||||
const displayData = searchText ? filteredData : employeeList
|
const displayData = searchText ? filteredData : employeeList
|
||||||
|
|
||||||
const indexOfLastItem = currentPage * itemsPerPage;
|
const indexOfLastItem = currentPage * itemsPerPage;
|
||||||
const indexOfFirstItem = indexOfLastItem - itemsPerPage;
|
const indexOfFirstItem = indexOfLastItem - itemsPerPage;
|
||||||
const currentItems = Array.isArray(displayData)
|
const currentItems = Array.isArray(displayData)
|
||||||
@ -110,7 +99,6 @@ const EmployeeList = () =>
|
|||||||
}, [ modelConfig, isCreateModalOpen ] );
|
}, [ modelConfig, isCreateModalOpen ] );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{isCreateModalOpen && (
|
{isCreateModalOpen && (
|
||||||
@ -138,7 +126,6 @@ const EmployeeList = () =>
|
|||||||
className="dataTables_length text-start"
|
className="dataTables_length text-start"
|
||||||
id="DataTables_Table_0_length"
|
id="DataTables_Table_0_length"
|
||||||
>
|
>
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
<select
|
<select
|
||||||
id="project-select"
|
id="project-select"
|
||||||
@ -237,8 +224,8 @@ const EmployeeList = () =>
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<button
|
<button
|
||||||
className={`btn btn-sm add-new btn-primary `}
|
|
||||||
// ${hasUserPermission("81ab8a87-8ccd-4015-a917-0627cee6a100")?"":"d-none"}
|
className={`btn btn-sm add-new btn-primary ${!ManageEmployee && 'd-none'}`}
|
||||||
tabIndex="0"
|
tabIndex="0"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
@ -249,7 +236,7 @@ const EmployeeList = () =>
|
|||||||
>
|
>
|
||||||
<i className="bx bx-plus-circle me-2"></i>
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
<span className="d-none d-md-inline-block">
|
<span className="d-none d-md-inline-block">
|
||||||
Add New User
|
Add New Employee
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
@ -284,7 +271,6 @@ const EmployeeList = () =>
|
|||||||
aria-controls="DataTables_Table_0"
|
aria-controls="DataTables_Table_0"
|
||||||
rowSpan="1"
|
rowSpan="1"
|
||||||
colSpan="1"
|
colSpan="1"
|
||||||
// style={{ width: "332px" }}
|
|
||||||
aria-label="User: activate to sort column ascending"
|
aria-label="User: activate to sort column ascending"
|
||||||
aria-sort="descending"
|
aria-sort="descending"
|
||||||
>
|
>
|
||||||
@ -296,7 +282,6 @@ const EmployeeList = () =>
|
|||||||
aria-controls="DataTables_Table_0"
|
aria-controls="DataTables_Table_0"
|
||||||
rowSpan="1"
|
rowSpan="1"
|
||||||
colSpan="1"
|
colSpan="1"
|
||||||
// style={{ width: "332px" }}
|
|
||||||
aria-label="User: activate to sort column ascending"
|
aria-label="User: activate to sort column ascending"
|
||||||
aria-sort="descending"
|
aria-sort="descending"
|
||||||
>
|
>
|
||||||
@ -309,7 +294,6 @@ const EmployeeList = () =>
|
|||||||
aria-controls="DataTables_Table_0"
|
aria-controls="DataTables_Table_0"
|
||||||
rowSpan="1"
|
rowSpan="1"
|
||||||
colSpan="1"
|
colSpan="1"
|
||||||
// style={{ width: "107px" }}
|
|
||||||
aria-label="Plan: activate to sort column ascending"
|
aria-label="Plan: activate to sort column ascending"
|
||||||
>
|
>
|
||||||
Joining Date
|
Joining Date
|
||||||
@ -324,9 +308,8 @@ const EmployeeList = () =>
|
|||||||
>
|
>
|
||||||
Status
|
Status
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
<th
|
<th
|
||||||
className="sorting_disabled"
|
className={`sorting_disabled ${!ManageEmployee && 'd-none'}`}
|
||||||
rowSpan="1"
|
rowSpan="1"
|
||||||
colSpan="1"
|
colSpan="1"
|
||||||
style={{ width: "50px" }}
|
style={{ width: "50px" }}
|
||||||
@ -344,9 +327,8 @@ const EmployeeList = () =>
|
|||||||
</tr>}
|
</tr>}
|
||||||
{( !loading && employeeList?.length === 0 ) && <td colSpan={8}>Not Data Found </td>}
|
{( !loading && employeeList?.length === 0 ) && <td colSpan={8}>Not Data Found </td>}
|
||||||
{( !loading && employeeList && currentItems.length === 0 && employeeList.length !==0 ) && <td colSpan={8}><small className="muted">'{searchText}' employee not found</small> </td>}
|
{( !loading && employeeList && currentItems.length === 0 && employeeList.length !==0 ) && <td colSpan={8}><small className="muted">'{searchText}' employee not found</small> </td>}
|
||||||
|
|
||||||
|
{(currentItems && !loading) && currentItems.sort((a, b) => b.id - a.id).map((item) => (
|
||||||
{(currentItems && !loading) && currentItems.map((item) => (
|
|
||||||
<tr className="odd" key={item.id}>
|
<tr className="odd" key={item.id}>
|
||||||
<td className="sorting_1" colSpan={2}>
|
<td className="sorting_1" colSpan={2}>
|
||||||
<div className="d-flex justify-content-start align-items-center user-name">
|
<div className="d-flex justify-content-start align-items-center user-name">
|
||||||
@ -390,10 +372,10 @@ const EmployeeList = () =>
|
|||||||
Active
|
Active
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td className="d-flex justify-content-end justify-content-sm-center">
|
<td className={`d-flex justify-content-end justify-content-sm-center ${!ManageEmployee && 'd-none'} `}>
|
||||||
<div className="d-flex align-items-center ">
|
<div className="d-flex align-items-center ">
|
||||||
<a
|
<a
|
||||||
className="btn btn-icon dropdown-toggle hide-arrow"
|
className={`btn btn-icon dropdown-toggle hide-arrow`}
|
||||||
data-bs-toggle="dropdown"
|
data-bs-toggle="dropdown"
|
||||||
>
|
>
|
||||||
<i className="bx bx-dots-vertical-rounded bx-md"></i>
|
<i className="bx bx-dots-vertical-rounded bx-md"></i>
|
||||||
@ -408,17 +390,14 @@ const EmployeeList = () =>
|
|||||||
>
|
>
|
||||||
View
|
View
|
||||||
</a>
|
</a>
|
||||||
{/* <a
|
|
||||||
|
|
||||||
> */}
|
|
||||||
<Link
|
<Link
|
||||||
className={`dropdown-item `}
|
className={`dropdown-item `}
|
||||||
// ${hasUserPermission("81ab8a87-8ccd-4015-a917-0627cee6a100")?"":"d-none"}
|
|
||||||
to={`/employee/manage/${item.id}`}
|
to={`/employee/manage/${item.id}`}
|
||||||
>
|
>
|
||||||
Edit
|
Edit
|
||||||
</Link>
|
</Link>
|
||||||
{/* </a> */}
|
|
||||||
<a className="dropdown-item">
|
<a className="dropdown-item">
|
||||||
Suspend
|
Suspend
|
||||||
</a>
|
</a>
|
||||||
|
@ -7,13 +7,16 @@ import { changeMaster } from "../../slices/localVariablesSlice";
|
|||||||
import useMaster from "../../hooks/masterHook/useMaster"
|
import useMaster from "../../hooks/masterHook/useMaster"
|
||||||
import MasterTable from "./MasterTable";
|
import MasterTable from "./MasterTable";
|
||||||
import { getCachedData } from "../../slices/apiDataManager";
|
import { getCachedData } from "../../slices/apiDataManager";
|
||||||
|
import {useHasUserPermission} from "../../hooks/useHasUserPermission";
|
||||||
|
import { MANAGE_MASTER } from "../../utils/constants";
|
||||||
|
|
||||||
|
|
||||||
const MasterPage = () => {
|
const MasterPage = () => {
|
||||||
|
|
||||||
const [modalConfig, setmodalConfig] = useState({modalType: "", item: null, masterType:null });
|
const [modalConfig, setmodalConfig] = useState({modalType: "", item: null, masterType:null });
|
||||||
const [searchTerm, setSearchTerm] = useState('');
|
const [searchTerm, setSearchTerm] = useState('');
|
||||||
const [filteredResults, setFilteredResults] = useState([]);
|
const [ filteredResults, setFilteredResults ] = useState( [] );
|
||||||
|
const hasMasterPermission = useHasUserPermission( MANAGE_MASTER )
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const selectedMaster = useSelector((store)=>store.localVariables.selectedMaster)
|
const selectedMaster = useSelector((store)=>store.localVariables.selectedMaster)
|
||||||
|
|
||||||
@ -98,7 +101,6 @@ const MasterPage = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{isCreateModalOpen && (
|
{isCreateModalOpen && (
|
||||||
|
|
||||||
<MasterModal modaldata={modalConfig} closeModal={closeModal} />
|
<MasterModal modaldata={modalConfig} closeModal={closeModal} />
|
||||||
|
|
||||||
)}
|
)}
|
||||||
@ -133,7 +135,7 @@ const MasterPage = () => {
|
|||||||
className="form-select form-select-sm"
|
className="form-select form-select-sm"
|
||||||
value={selectedMaster}
|
value={selectedMaster}
|
||||||
>
|
>
|
||||||
<option value="" disabled >Select Master</option>
|
|
||||||
{mastersList.map( ( item ) => (
|
{mastersList.map( ( item ) => (
|
||||||
|
|
||||||
<option key={item.id} value={item.name}>{item.name}</option>
|
<option key={item.id} value={item.name}>{item.name}</option>
|
||||||
@ -160,7 +162,7 @@ const MasterPage = () => {
|
|||||||
></input>
|
></input>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className="dt-buttons btn-group flex-wrap">
|
<div className={`dt-buttons btn-group flex-wrap ${!hasMasterPermission && 'd-none'}`}>
|
||||||
{" "}
|
{" "}
|
||||||
<div className="input-group">
|
<div className="input-group">
|
||||||
|
|
||||||
@ -190,7 +192,7 @@ const MasterPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<MasterTable data={displayData} columns={columns} loading={loading} handleModalData={handleModalData} />
|
<MasterTable data={displayData} columns={columns} loading={loading} handleModalData={handleModalData} />
|
||||||
<div style={{ width: "1%" }}></div>
|
<div style={{ width: "1%" }}></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import React, { useEffect,useState } from "react";
|
import React, { useEffect,useState } from "react";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
||||||
import {MASTER_MANAGE} from "../../utils/constants";
|
import {MANAGE_MASTER} from "../../utils/constants";
|
||||||
|
|
||||||
const MasterTable = ( {data, columns, loading, handleModalData} ) =>
|
const MasterTable = ( {data, columns, loading, handleModalData} ) =>
|
||||||
{
|
{
|
||||||
const hasMasterPermission = useHasUserPermission(MASTER_MANAGE) // for master manage permission id
|
const hasMasterPermission = useHasUserPermission(MANAGE_MASTER)
|
||||||
const selectedMaster = useSelector((store)=>store.localVariables.selectedMaster)
|
const selectedMaster = useSelector((store)=>store.localVariables.selectedMaster)
|
||||||
const hiddenColumns = ["id", "featurePermission","tenant","tenantId"];
|
const hiddenColumns = ["id", "featurePermission","tenant","tenantId"];
|
||||||
|
|
||||||
@ -44,12 +44,10 @@ const MasterTable = ( {data, columns, loading, handleModalData} ) =>
|
|||||||
>
|
>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
{/* Example of using updatedColumns */}
|
|
||||||
<th></th>
|
<th></th>
|
||||||
<th>Name</th>
|
<th>{ selectedMaster} Name</th>
|
||||||
<th>Description</th>
|
<th>{selectedMaster } Description</th>
|
||||||
<th className={` ${hasMasterPermission? "":"d-none"}`}>Actions</th>
|
<th className={` ${!hasMasterPermission && 'd-none'}`}>Actions</th>
|
||||||
{/* ${hasUserPermission('660131a4-788c-4739-a082-cbbf7879cbf2') ? "":"d-none"} */}
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -74,12 +72,9 @@ const MasterTable = ( {data, columns, loading, handleModalData} ) =>
|
|||||||
) : (
|
) : (
|
||||||
item[col.key] !== undefined && item[col.key] !== null ? item[col.key] : " --- "
|
item[col.key] !== undefined && item[col.key] !== null ? item[col.key] : " --- "
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
))}
|
))}
|
||||||
<td >
|
<td className={`${!hasMasterPermission && 'd-none'}`} >
|
||||||
{/* className={` ${hasUserPermission('660131a4-788c-4739-a082-cbbf7879cbf2') ? "":"d-none"}`}> */}
|
|
||||||
<button
|
<button
|
||||||
aria-label="Modify"
|
aria-label="Modify"
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -155,7 +155,7 @@ const ProjectList = () =>
|
|||||||
<div className="row">
|
<div className="row">
|
||||||
{loading && <p className="text-center">Loading...</p>}
|
{loading && <p className="text-center">Loading...</p>}
|
||||||
{currentItems &&
|
{currentItems &&
|
||||||
currentItems?.map((item) => (
|
currentItems.sort((a, b) => b.id - a.id).map((item) => (
|
||||||
<ProjectCard projectData={item} key={item.id}></ProjectCard>
|
<ProjectCard projectData={item} key={item.id}></ProjectCard>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,7 +5,7 @@ const localVariablesSlice = createSlice({
|
|||||||
initialState: {
|
initialState: {
|
||||||
selectedMaster:"Role",
|
selectedMaster:"Role",
|
||||||
regularizationCount:0,
|
regularizationCount:0,
|
||||||
projectId:1,
|
projectId:5,
|
||||||
|
|
||||||
},
|
},
|
||||||
reducers: {
|
reducers: {
|
||||||
|
@ -1,10 +1,22 @@
|
|||||||
export const THRESH_HOLD = 12; // hours
|
export const THRESH_HOLD = 12; // hours
|
||||||
export const DURATION_TIME = 10; // minutes
|
export const DURATION_TIME = 10; // minutes
|
||||||
|
|
||||||
export const MASTER_MANAGE = "660131a4-788c-4739-a082-cbbf7879cbf2";
|
export const MANAGE_MASTER = "588a8824-f924-4955-82d8-fc51956cf323";
|
||||||
|
|
||||||
export const ASSIGN_USER_TO_PROJECT = "81ab8a87-8ccd-4015-a917-0627cee6a100";
|
export const MANAGE_PROJECT = "172fc9b6-755b-4f62-ab26-55c34a330614"
|
||||||
|
|
||||||
|
export const MANAGE_EMPLOYEES = "a97d366a-c2bb-448d-be93-402bd2324566"
|
||||||
|
|
||||||
|
export const MANAGE_PROJECT_INFRA = "f2aee20a-b754-4537-8166-f9507b44585b"
|
||||||
|
|
||||||
|
export const VIEW_PROJECT_INFRA = "c7b68e33-72f0-474f-bd96-77636427ecc8"
|
||||||
|
|
||||||
|
export const REGULARIZE_ATTENDANCE ="57802c4a-00aa-4a1f-a048-fd2f70dd44b6"
|
||||||
|
|
||||||
|
|
||||||
|
export const ASSIGN_TO_PROJECT = "fbd213e0-0250-46f1-9f5f-4b2a1e6e76a3";
|
||||||
|
|
||||||
export const INFRASTRUCTURE = "9666de86-d7c7-4d3d-acaa-fcd6d6b81f3c";
|
export const INFRASTRUCTURE = "9666de86-d7c7-4d3d-acaa-fcd6d6b81f3c";
|
||||||
|
|
||||||
export const MANAGE_PROJECT = "53176ebf-c75d-42e5-839f-4508ffac3def"
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user