Compare commits
	
		
			42 Commits
		
	
	
		
			5de4953760
			...
			6f247fb0e9
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 6f247fb0e9 | |||
| 8431e856aa | |||
| 782ace9d1c | |||
| fdff7f7b41 | |||
| 8832ff1c51 | |||
| 24dc481169 | |||
| 351e5a2b0d | |||
| 2848177908 | |||
| b767641643 | |||
| b24edba8f7 | |||
| 8217308db9 | |||
| ab5a598562 | |||
| 9530f9ca87 | |||
| 9b6fa84d0d | |||
| 5567928c7f | |||
| 88efbf5542 | |||
| ed2fa2d5b0 | |||
| a0e4b1c5ed | |||
| 90a77d357f | |||
| 8ad375ede4 | |||
| 6f3a8bd7c9 | |||
| 2fbf0f98ef | |||
| 36d70b3850 | |||
| a3381bb2e6 | |||
| 
						 | 
					6f88980986 | ||
| 
						 | 
					6d2c2c5e0b | ||
| 
						 | 
					f48d05ecee | ||
| 
						 | 
					dee44c63aa | ||
| 
						 | 
					b76ca68059 | ||
| 
						 | 
					7c9607cb78 | ||
| 
						 | 
					cbf376d5b6 | ||
| 
						 | 
					00902fff9f | ||
| 
						 | 
					c254b98405 | ||
| 41f3628d45 | |||
| 31a9f55b63 | |||
| 70ac3e0344 | |||
| 409d98f923 | |||
| 
						 | 
					1f0255bc55 | ||
| edf092e85e | |||
| 
						 | 
					9043cfd49e | ||
| da440060e8 | |||
| 
						 | 
					3ed5999f29 | 
@ -7,7 +7,13 @@ import usePagination from "../../hooks/usePagination";
 | 
				
			|||||||
import { useNavigate } from "react-router-dom";
 | 
					import { useNavigate } from "react-router-dom";
 | 
				
			||||||
import { ITEMS_PER_PAGE } from "../../utils/constants";
 | 
					import { ITEMS_PER_PAGE } from "../../utils/constants";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const Attendance = ({ attendance, getRole, handleModalData }) => {
 | 
					const Attendance = ({
 | 
				
			||||||
 | 
					  attendance,
 | 
				
			||||||
 | 
					  getRole,
 | 
				
			||||||
 | 
					  handleModalData,
 | 
				
			||||||
 | 
					  setshowOnlyCheckout,
 | 
				
			||||||
 | 
					  showOnlyCheckout,
 | 
				
			||||||
 | 
					}) => {
 | 
				
			||||||
  const [loading, setLoading] = useState(false);
 | 
					  const [loading, setLoading] = useState(false);
 | 
				
			||||||
  const navigate = useNavigate();
 | 
					  const navigate = useNavigate();
 | 
				
			||||||
  const [todayDate, setTodayDate] = useState(new Date());
 | 
					  const [todayDate, setTodayDate] = useState(new Date());
 | 
				
			||||||
@ -19,7 +25,7 @@ const Attendance = ({ attendance, getRole, handleModalData }) => {
 | 
				
			|||||||
  const sortByName = (a, b) => {
 | 
					  const sortByName = (a, b) => {
 | 
				
			||||||
    const nameA = (a.firstName + a.lastName).toLowerCase();
 | 
					    const nameA = (a.firstName + a.lastName).toLowerCase();
 | 
				
			||||||
    const nameB = (b.firstName + b.lastName).toLowerCase();
 | 
					    const nameB = (b.firstName + b.lastName).toLowerCase();
 | 
				
			||||||
    return nameA.localeCompare(nameB);
 | 
					    return nameA?.localeCompare(nameB);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Filter employees based on activity
 | 
					  // Filter employees based on activity
 | 
				
			||||||
@ -39,30 +45,36 @@ const Attendance = ({ attendance, getRole, handleModalData }) => {
 | 
				
			|||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <>
 | 
					    <>
 | 
				
			||||||
      <div className="table-responsive text-nowrap">
 | 
					      <div className="table-responsive text-nowrap">
 | 
				
			||||||
 | 
					        <div className="d-flex text-start align-items-center py-2">
 | 
				
			||||||
 | 
					          <strong>Date : {todayDate.toLocaleDateString("en-GB")}</strong>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <div className="form-check form-switch text-start m-0 ms-5">
 | 
				
			||||||
 | 
					            <input
 | 
				
			||||||
 | 
					              type="checkbox"
 | 
				
			||||||
 | 
					              className="form-check-input"
 | 
				
			||||||
 | 
					              role="switch"
 | 
				
			||||||
 | 
					              id="inactiveEmployeesCheckbox"
 | 
				
			||||||
 | 
					              checked={showOnlyCheckout}
 | 
				
			||||||
 | 
					              onChange={(e) => setshowOnlyCheckout(e.target.checked)}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					            <label className="form-check-label ms-0">Show Pending</label>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
        {attendance && attendance.length > 0 && (
 | 
					        {attendance && attendance.length > 0 && (
 | 
				
			||||||
          <>
 | 
					          <>
 | 
				
			||||||
            <table className="table ">
 | 
					            <table className="table ">
 | 
				
			||||||
              <thead>
 | 
					              <thead>
 | 
				
			||||||
                <tr className="border-none" style={{ textAlign: 'left' }}>
 | 
					                <tr className="border-top-1">
 | 
				
			||||||
                  <td style={{ borderBottom: 'none' }}>
 | 
					                  <th colSpan={2}>Name</th>
 | 
				
			||||||
                    <strong>Date : {todayDate.toLocaleDateString('en-GB')}</strong>
 | 
					                  <th>Role</th>
 | 
				
			||||||
                  </td>
 | 
					                  <th>
 | 
				
			||||||
                  <td style={{ paddingLeft: '20px', borderBottom: 'none' }}></td>
 | 
					 | 
				
			||||||
                </tr>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                <tr>
 | 
					 | 
				
			||||||
                  <th className="border-top-0" colSpan={2}>
 | 
					 | 
				
			||||||
                    Name
 | 
					 | 
				
			||||||
                  </th>
 | 
					 | 
				
			||||||
                  <th className="border-top-0">Role</th>
 | 
					 | 
				
			||||||
                  <th className="border-top-0">
 | 
					 | 
				
			||||||
                    <i className="bx bxs-down-arrow-alt text-success"></i>
 | 
					                    <i className="bx bxs-down-arrow-alt text-success"></i>
 | 
				
			||||||
                    Check-In
 | 
					                    Check-In
 | 
				
			||||||
                  </th>
 | 
					                  </th>
 | 
				
			||||||
                  <th className="border-top-0">
 | 
					                  <th>
 | 
				
			||||||
                    <i className="bx bxs-up-arrow-alt text-danger"></i>Check-Out
 | 
					                    <i className="bx bxs-up-arrow-alt text-danger"></i>Check-Out
 | 
				
			||||||
                  </th>
 | 
					                  </th>
 | 
				
			||||||
                  <th className="border-top-0">Actions</th>
 | 
					                  <th>Actions</th>
 | 
				
			||||||
                </tr>
 | 
					                </tr>
 | 
				
			||||||
              </thead>
 | 
					              </thead>
 | 
				
			||||||
              <tbody className="table-border-bottom-0 ">
 | 
					              <tbody className="table-border-bottom-0 ">
 | 
				
			||||||
@ -70,10 +82,10 @@ const Attendance = ({ attendance, getRole, handleModalData }) => {
 | 
				
			|||||||
                  currentItems
 | 
					                  currentItems
 | 
				
			||||||
                    .sort((a, b) => {
 | 
					                    .sort((a, b) => {
 | 
				
			||||||
                      // If checkInTime exists, compare it, otherwise, treat null as earlier than a date
 | 
					                      // If checkInTime exists, compare it, otherwise, treat null as earlier than a date
 | 
				
			||||||
                      const checkInA = a.checkInTime
 | 
					                      const checkInA = a?.checkInTime
 | 
				
			||||||
                        ? new Date(a.checkInTime)
 | 
					                        ? new Date(a.checkInTime)
 | 
				
			||||||
                        : new Date(0);
 | 
					                        : new Date(0);
 | 
				
			||||||
                      const checkInB = b.checkInTime
 | 
					                      const checkInB = b?.checkInTime
 | 
				
			||||||
                        ? new Date(b.checkInTime)
 | 
					                        ? new Date(b.checkInTime)
 | 
				
			||||||
                        : new Date(0);
 | 
					                        : new Date(0);
 | 
				
			||||||
                      return checkInB - checkInA; // Sort in descending order of checkInTime
 | 
					                      return checkInB - checkInA; // Sort in descending order of checkInTime
 | 
				
			||||||
@ -135,7 +147,8 @@ const Attendance = ({ attendance, getRole, handleModalData }) => {
 | 
				
			|||||||
              <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  ${currentPage === 1 ? "disabled" : ""
 | 
					                    className={`page-item  ${
 | 
				
			||||||
 | 
					                      currentPage === 1 ? "disabled" : ""
 | 
				
			||||||
                    }`}
 | 
					                    }`}
 | 
				
			||||||
                  >
 | 
					                  >
 | 
				
			||||||
                    <button
 | 
					                    <button
 | 
				
			||||||
@ -148,7 +161,8 @@ const Attendance = ({ attendance, getRole, handleModalData }) => {
 | 
				
			|||||||
                  {[...Array(totalPages)].map((_, index) => (
 | 
					                  {[...Array(totalPages)].map((_, index) => (
 | 
				
			||||||
                    <li
 | 
					                    <li
 | 
				
			||||||
                      key={index}
 | 
					                      key={index}
 | 
				
			||||||
                      className={`page-item ${currentPage === index + 1 ? "active" : ""
 | 
					                      className={`page-item ${
 | 
				
			||||||
 | 
					                        currentPage === index + 1 ? "active" : ""
 | 
				
			||||||
                      }`}
 | 
					                      }`}
 | 
				
			||||||
                    >
 | 
					                    >
 | 
				
			||||||
                      <button
 | 
					                      <button
 | 
				
			||||||
@ -160,7 +174,8 @@ const Attendance = ({ attendance, getRole, handleModalData }) => {
 | 
				
			|||||||
                    </li>
 | 
					                    </li>
 | 
				
			||||||
                  ))}
 | 
					                  ))}
 | 
				
			||||||
                  <li
 | 
					                  <li
 | 
				
			||||||
                    className={`page-item ${currentPage === totalPages ? "disabled" : ""
 | 
					                    className={`page-item ${
 | 
				
			||||||
 | 
					                      currentPage === totalPages ? "disabled" : ""
 | 
				
			||||||
                    }`}
 | 
					                    }`}
 | 
				
			||||||
                  >
 | 
					                  >
 | 
				
			||||||
                    <button
 | 
					                    <button
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,6 @@ import eventBus from "../../services/eventBus";
 | 
				
			|||||||
const usePagination = (data, itemsPerPage) => {
 | 
					const usePagination = (data, itemsPerPage) => {
 | 
				
			||||||
  const [currentPage, setCurrentPage] = useState(1);
 | 
					  const [currentPage, setCurrentPage] = useState(1);
 | 
				
			||||||
  const maxPage = Math.ceil(data.length / itemsPerPage);
 | 
					  const maxPage = Math.ceil(data.length / itemsPerPage);
 | 
				
			||||||
 | 
					 | 
				
			||||||
  const currentItems = useMemo(() => {
 | 
					  const currentItems = useMemo(() => {
 | 
				
			||||||
    const startIndex = (currentPage - 1) * itemsPerPage;
 | 
					    const startIndex = (currentPage - 1) * itemsPerPage;
 | 
				
			||||||
    const endIndex = startIndex + itemsPerPage;
 | 
					    const endIndex = startIndex + itemsPerPage;
 | 
				
			||||||
@ -22,10 +21,21 @@ const usePagination = (data, itemsPerPage) => {
 | 
				
			|||||||
  const paginate = useCallback((pageNumber) => setCurrentPage(pageNumber), []);
 | 
					  const paginate = useCallback((pageNumber) => setCurrentPage(pageNumber), []);
 | 
				
			||||||
  const resetPage = useCallback(() => setCurrentPage(1), []);
 | 
					  const resetPage = useCallback(() => setCurrentPage(1), []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return { currentPage, totalPages: maxPage, currentItems, paginate, resetPage };
 | 
					  return {
 | 
				
			||||||
 | 
					    currentPage,
 | 
				
			||||||
 | 
					    totalPages: maxPage,
 | 
				
			||||||
 | 
					    currentItems,
 | 
				
			||||||
 | 
					    paginate,
 | 
				
			||||||
 | 
					    resetPage,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const AttendanceLog = ({ handleModalData, projectId, showOnlyCheckout }) => {
 | 
					const AttendanceLog = ({
 | 
				
			||||||
 | 
					  handleModalData,
 | 
				
			||||||
 | 
					  projectId,
 | 
				
			||||||
 | 
					  setshowOnlyCheckout,
 | 
				
			||||||
 | 
					  showOnlyCheckout,
 | 
				
			||||||
 | 
					}) => {
 | 
				
			||||||
  const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" });
 | 
					  const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" });
 | 
				
			||||||
  const dispatch = useDispatch();
 | 
					  const dispatch = useDispatch();
 | 
				
			||||||
  const { data, loading, error } = useSelector((store) => store.attendanceLogs);
 | 
					  const { data, loading, error } = useSelector((store) => store.attendanceLogs);
 | 
				
			||||||
@ -55,7 +65,7 @@ const AttendanceLog = ({ handleModalData, projectId, showOnlyCheckout }) => {
 | 
				
			|||||||
  const sortByName = (a, b) => {
 | 
					  const sortByName = (a, b) => {
 | 
				
			||||||
    const nameA = a.firstName.toLowerCase() + a.lastName.toLowerCase();
 | 
					    const nameA = a.firstName.toLowerCase() + a.lastName.toLowerCase();
 | 
				
			||||||
    const nameB = b.firstName.toLowerCase() + b.lastName.toLowerCase();
 | 
					    const nameB = b.firstName.toLowerCase() + b.lastName.toLowerCase();
 | 
				
			||||||
    return nameA.localeCompare(nameB);
 | 
					    return nameA?.localeCompare(nameB);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  useEffect(() => {
 | 
					  useEffect(() => {
 | 
				
			||||||
@ -84,14 +94,24 @@ const AttendanceLog = ({ handleModalData, projectId, showOnlyCheckout }) => {
 | 
				
			|||||||
    const group3 = filteredData
 | 
					    const group3 = filteredData
 | 
				
			||||||
      .filter((d) => d.activity === 1 && isBeforeToday(d.checkInTime))
 | 
					      .filter((d) => d.activity === 1 && isBeforeToday(d.checkInTime))
 | 
				
			||||||
      .sort(sortByName);
 | 
					      .sort(sortByName);
 | 
				
			||||||
    const group4 = filteredData
 | 
					    const group4 = filteredData.filter(
 | 
				
			||||||
      .filter((d) => d.activity === 4 && isBeforeToday(d.checkOutTime));
 | 
					      (d) => d.activity === 4 && isBeforeToday(d.checkOutTime)
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
    const group5 = filteredData
 | 
					    const group5 = filteredData
 | 
				
			||||||
      .filter((d) => d.activity === 2 && isBeforeToday(d.checkOutTime))
 | 
					      .filter((d) => d.activity === 2 && isBeforeToday(d.checkOutTime))
 | 
				
			||||||
      .sort(sortByName);
 | 
					      .sort(sortByName);
 | 
				
			||||||
    const group6 = filteredData.filter((d) => d.activity === 5).sort(sortByName);
 | 
					    const group6 = filteredData
 | 
				
			||||||
 | 
					      .filter((d) => d.activity === 5)
 | 
				
			||||||
 | 
					      .sort(sortByName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const sortedList = [...group1, ...group2, ...group3, ...group4, ...group5, ...group6];
 | 
					    const sortedList = [
 | 
				
			||||||
 | 
					      ...group1,
 | 
				
			||||||
 | 
					      ...group2,
 | 
				
			||||||
 | 
					      ...group3,
 | 
				
			||||||
 | 
					      ...group4,
 | 
				
			||||||
 | 
					      ...group5,
 | 
				
			||||||
 | 
					      ...group6,
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Group by date
 | 
					    // Group by date
 | 
				
			||||||
    const groupedByDate = sortedList.reduce((acc, item) => {
 | 
					    const groupedByDate = sortedList.reduce((acc, item) => {
 | 
				
			||||||
@ -104,7 +124,9 @@ const AttendanceLog = ({ handleModalData, projectId, showOnlyCheckout }) => {
 | 
				
			|||||||
    }, {});
 | 
					    }, {});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Sort dates in descending order
 | 
					    // Sort dates in descending order
 | 
				
			||||||
    const sortedDates = Object.keys(groupedByDate).sort((a, b) => new Date(b) - new Date(a));
 | 
					    const sortedDates = Object.keys(groupedByDate).sort(
 | 
				
			||||||
 | 
					      (a, b) => new Date(b) - new Date(a)
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create the final sorted array
 | 
					    // Create the final sorted array
 | 
				
			||||||
    const finalData = sortedDates.flatMap((date) => groupedByDate[date]);
 | 
					    const finalData = sortedDates.flatMap((date) => groupedByDate[date]);
 | 
				
			||||||
@ -115,10 +137,13 @@ const AttendanceLog = ({ handleModalData, projectId, showOnlyCheckout }) => {
 | 
				
			|||||||
    filtering(data)
 | 
					    filtering(data)
 | 
				
			||||||
  }, [data, showOnlyCheckout]);
 | 
					  }, [data, showOnlyCheckout]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const { currentPage, totalPages, currentItems: paginatedAttendances, paginate, resetPage } = usePagination(
 | 
					  const {
 | 
				
			||||||
    processedData,
 | 
					    currentPage,
 | 
				
			||||||
    20
 | 
					    totalPages,
 | 
				
			||||||
  );
 | 
					    currentItems: paginatedAttendances,
 | 
				
			||||||
 | 
					    paginate,
 | 
				
			||||||
 | 
					    resetPage,
 | 
				
			||||||
 | 
					  } = usePagination(processedData, 20);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Reset to the first page whenever processedData changes (due to switch on/off)
 | 
					  // Reset to the first page whenever processedData changes (due to switch on/off)
 | 
				
			||||||
  useEffect(() => {
 | 
					  useEffect(() => {
 | 
				
			||||||
@ -154,24 +179,41 @@ const AttendanceLog = ({ handleModalData, projectId, showOnlyCheckout }) => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <>
 | 
					    <>
 | 
				
			||||||
      
 | 
					 | 
				
			||||||
      <div
 | 
					      <div
 | 
				
			||||||
        className="dataTables_length text-start py-2 d-flex justify-content-between"
 | 
					        className="dataTables_length text-start py-2 d-flex justify-content-between"
 | 
				
			||||||
        id="DataTables_Table_0_length"
 | 
					        id="DataTables_Table_0_length"
 | 
				
			||||||
      >
 | 
					      >
 | 
				
			||||||
          <div className="col-md-3 my-0 ">
 | 
					        <div className="d-flex align-items-center my-0 ">
 | 
				
			||||||
            <DateRangePicker onRangeChange={setDateRange} defaultStartDate={yesterday} />
 | 
					          <DateRangePicker
 | 
				
			||||||
 | 
					            onRangeChange={setDateRange}
 | 
				
			||||||
 | 
					            defaultStartDate={yesterday}
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					          <div className="form-check form-switch text-start m-0 ms-5">
 | 
				
			||||||
 | 
					            <input
 | 
				
			||||||
 | 
					              type="checkbox"
 | 
				
			||||||
 | 
					              className="form-check-input"
 | 
				
			||||||
 | 
					              role="switch"
 | 
				
			||||||
 | 
					              id="inactiveEmployeesCheckbox"
 | 
				
			||||||
 | 
					              checked={showOnlyCheckout}
 | 
				
			||||||
 | 
					              onChange={(e) => setshowOnlyCheckout(e.target.checked)}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					            <label className="form-check-label ms-0">Show Pending</label>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div className="col-md-2 m-0 text-end">
 | 
					        <div className="col-md-2 m-0 text-end">
 | 
				
			||||||
          <i
 | 
					          <i
 | 
				
			||||||
              className={`bx bx-refresh cursor-pointer fs-4 ${loading || isRefreshing ? "spin" : ""
 | 
					            className={`bx bx-refresh cursor-pointer fs-4 ${
 | 
				
			||||||
 | 
					              loading || isRefreshing ? "spin" : ""
 | 
				
			||||||
            }`}
 | 
					            }`}
 | 
				
			||||||
            title="Refresh"
 | 
					            title="Refresh"
 | 
				
			||||||
            onClick={() => setIsRefreshing(true)}
 | 
					            onClick={() => setIsRefreshing(true)}
 | 
				
			||||||
          />
 | 
					          />
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
        <div className="table-responsive text-nowrap" style={{ minHeight: "250px" }}>
 | 
					      <div
 | 
				
			||||||
 | 
					        className="table-responsive text-nowrap"
 | 
				
			||||||
 | 
					        style={{ minHeight: "250px" }}
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
        {data && data.length > 0 && (
 | 
					        {data && data.length > 0 && (
 | 
				
			||||||
          <table className="table mb-0">
 | 
					          <table className="table mb-0">
 | 
				
			||||||
            <thead>
 | 
					            <thead>
 | 
				
			||||||
@ -181,7 +223,8 @@ const AttendanceLog = ({ handleModalData, projectId, showOnlyCheckout }) => {
 | 
				
			|||||||
                </th>
 | 
					                </th>
 | 
				
			||||||
                <th className="border-top-1">Date</th>
 | 
					                <th className="border-top-1">Date</th>
 | 
				
			||||||
                <th>
 | 
					                <th>
 | 
				
			||||||
                    <i className="bx bxs-down-arrow-alt text-success"></i> Check-In
 | 
					                  <i className="bx bxs-down-arrow-alt text-success"></i>{" "}
 | 
				
			||||||
 | 
					                  Check-In
 | 
				
			||||||
                </th>
 | 
					                </th>
 | 
				
			||||||
                <th>
 | 
					                <th>
 | 
				
			||||||
                  <i className="bx bxs-up-arrow-alt text-danger"></i> Check-Out
 | 
					                  <i className="bx bxs-up-arrow-alt text-danger"></i> Check-Out
 | 
				
			||||||
@ -195,16 +238,30 @@ const AttendanceLog = ({ handleModalData, projectId, showOnlyCheckout }) => {
 | 
				
			|||||||
                  <td colSpan={6}>Loading...</td>
 | 
					                  <td colSpan={6}>Loading...</td>
 | 
				
			||||||
                </tr>
 | 
					                </tr>
 | 
				
			||||||
              )}
 | 
					              )}
 | 
				
			||||||
                {!loading && !isRefreshing && paginatedAttendances.reduce((acc, attendance, index, arr) => {
 | 
					              {!loading &&
 | 
				
			||||||
                  const currentDate = moment(attendance.checkInTime || attendance.checkOutTime).format("YYYY-MM-DD");
 | 
					                !isRefreshing &&
 | 
				
			||||||
 | 
					                paginatedAttendances.reduce((acc, attendance, index, arr) => {
 | 
				
			||||||
 | 
					                  const currentDate = moment(
 | 
				
			||||||
 | 
					                    attendance.checkInTime || attendance.checkOutTime
 | 
				
			||||||
 | 
					                  ).format("YYYY-MM-DD");
 | 
				
			||||||
                  const previousAttendance = arr[index - 1];
 | 
					                  const previousAttendance = arr[index - 1];
 | 
				
			||||||
                  const previousDate = previousAttendance ? moment(previousAttendance.checkInTime || previousAttendance.checkOutTime).format("YYYY-MM-DD") : null;
 | 
					                  const previousDate = previousAttendance
 | 
				
			||||||
 | 
					                    ? moment(
 | 
				
			||||||
 | 
					                        previousAttendance.checkInTime ||
 | 
				
			||||||
 | 
					                          previousAttendance.checkOutTime
 | 
				
			||||||
 | 
					                      ).format("YYYY-MM-DD")
 | 
				
			||||||
 | 
					                    : null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                  if (!previousDate || currentDate !== previousDate) {
 | 
					                  if (!previousDate || currentDate !== previousDate) {
 | 
				
			||||||
                    acc.push(
 | 
					                    acc.push(
 | 
				
			||||||
                      <tr key={`header-${currentDate}`} className="table-row-header">
 | 
					                      <tr
 | 
				
			||||||
 | 
					                        key={`header-${currentDate}`}
 | 
				
			||||||
 | 
					                        className="table-row-header"
 | 
				
			||||||
 | 
					                      >
 | 
				
			||||||
                        <td colSpan={6} className="text-start">
 | 
					                        <td colSpan={6} className="text-start">
 | 
				
			||||||
                          <strong>{moment(currentDate).format("DD-MM-YYYY")}</strong>
 | 
					                          <strong>
 | 
				
			||||||
 | 
					                            {moment(currentDate).format("DD-MM-YYYY")}
 | 
				
			||||||
 | 
					                          </strong>
 | 
				
			||||||
                        </td>
 | 
					                        </td>
 | 
				
			||||||
                      </tr>
 | 
					                      </tr>
 | 
				
			||||||
                    );
 | 
					                    );
 | 
				
			||||||
@ -218,10 +275,7 @@ const AttendanceLog = ({ handleModalData, projectId, showOnlyCheckout }) => {
 | 
				
			|||||||
                            lastName={attendance.lastName}
 | 
					                            lastName={attendance.lastName}
 | 
				
			||||||
                          />
 | 
					                          />
 | 
				
			||||||
                          <div className="d-flex flex-column">
 | 
					                          <div className="d-flex flex-column">
 | 
				
			||||||
                            <a
 | 
					                            <a href="#" className="text-heading text-truncate">
 | 
				
			||||||
                              href="#"
 | 
					 | 
				
			||||||
                              className="text-heading text-truncate"
 | 
					 | 
				
			||||||
                            >
 | 
					 | 
				
			||||||
                              <span className="fw-normal">
 | 
					                              <span className="fw-normal">
 | 
				
			||||||
                                {attendance.firstName} {attendance.lastName}
 | 
					                                {attendance.firstName} {attendance.lastName}
 | 
				
			||||||
                              </span>
 | 
					                              </span>
 | 
				
			||||||
@ -230,11 +284,15 @@ const AttendanceLog = ({ handleModalData, projectId, showOnlyCheckout }) => {
 | 
				
			|||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                      </td>
 | 
					                      </td>
 | 
				
			||||||
                      <td>
 | 
					                      <td>
 | 
				
			||||||
                        {moment(attendance.checkInTime || attendance.checkOutTime).format("DD-MMM-YYYY")}
 | 
					                        {moment(
 | 
				
			||||||
 | 
					                          attendance.checkInTime || attendance.checkOutTime
 | 
				
			||||||
 | 
					                        ).format("DD-MMM-YYYY")}
 | 
				
			||||||
                      </td>
 | 
					                      </td>
 | 
				
			||||||
                      <td>{convertShortTime(attendance.checkInTime)}</td>
 | 
					                      <td>{convertShortTime(attendance.checkInTime)}</td>
 | 
				
			||||||
                      <td>
 | 
					                      <td>
 | 
				
			||||||
                        {attendance.checkOutTime ? convertShortTime(attendance.checkOutTime) : "--"}
 | 
					                        {attendance.checkOutTime
 | 
				
			||||||
 | 
					                          ? convertShortTime(attendance.checkOutTime)
 | 
				
			||||||
 | 
					                          : "--"}
 | 
				
			||||||
                      </td>
 | 
					                      </td>
 | 
				
			||||||
                      <td className="text-center">
 | 
					                      <td className="text-center">
 | 
				
			||||||
                        <RenderAttendanceStatus
 | 
					                        <RenderAttendanceStatus
 | 
				
			||||||
@ -250,10 +308,10 @@ const AttendanceLog = ({ handleModalData, projectId, showOnlyCheckout }) => {
 | 
				
			|||||||
                }, [])}
 | 
					                }, [])}
 | 
				
			||||||
            </tbody>
 | 
					            </tbody>
 | 
				
			||||||
          </table>
 | 
					          </table>
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        )}
 | 
					        )}
 | 
				
			||||||
          {!loading && !isRefreshing && data.length === 0 && <span>No employee logs</span>}
 | 
					        {!loading && !isRefreshing && data.length === 0 && (
 | 
				
			||||||
 | 
					          <span>No employee logs</span>
 | 
				
			||||||
 | 
					        )}
 | 
				
			||||||
        {error && !loading && !isRefreshing && (
 | 
					        {error && !loading && !isRefreshing && (
 | 
				
			||||||
          <tr>
 | 
					          <tr>
 | 
				
			||||||
            <td colSpan={6}>{error}</td>
 | 
					            <td colSpan={6}>{error}</td>
 | 
				
			||||||
@ -264,24 +322,39 @@ const AttendanceLog = ({ handleModalData, projectId, showOnlyCheckout }) => {
 | 
				
			|||||||
        <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 className={`page-item ${currentPage === 1 ? "disabled" : ""}`}>
 | 
					            <li className={`page-item ${currentPage === 1 ? "disabled" : ""}`}>
 | 
				
			||||||
              <button className="page-link btn-xs" onClick={() => paginate(currentPage - 1)}>
 | 
					              <button
 | 
				
			||||||
 | 
					                className="page-link btn-xs"
 | 
				
			||||||
 | 
					                onClick={() => paginate(currentPage - 1)}
 | 
				
			||||||
 | 
					              >
 | 
				
			||||||
                «
 | 
					                «
 | 
				
			||||||
              </button>
 | 
					              </button>
 | 
				
			||||||
            </li>
 | 
					            </li>
 | 
				
			||||||
            {Array.from({ length: totalPages }, (_, i) => i + 1).map((pageNumber) => (
 | 
					            {Array.from({ length: totalPages }, (_, i) => i + 1).map(
 | 
				
			||||||
 | 
					              (pageNumber) => (
 | 
				
			||||||
                <li
 | 
					                <li
 | 
				
			||||||
                  key={pageNumber}
 | 
					                  key={pageNumber}
 | 
				
			||||||
                className={`page-item ${currentPage === pageNumber ? "active" : ""}`}
 | 
					                  className={`page-item ${
 | 
				
			||||||
 | 
					                    currentPage === pageNumber ? "active" : ""
 | 
				
			||||||
 | 
					                  }`}
 | 
				
			||||||
 | 
					                >
 | 
				
			||||||
 | 
					                  <button
 | 
				
			||||||
 | 
					                    className="page-link"
 | 
				
			||||||
 | 
					                    onClick={() => paginate(pageNumber)}
 | 
				
			||||||
                  >
 | 
					                  >
 | 
				
			||||||
                <button className="page-link" onClick={() => paginate(pageNumber)}>
 | 
					 | 
				
			||||||
                    {pageNumber}
 | 
					                    {pageNumber}
 | 
				
			||||||
                  </button>
 | 
					                  </button>
 | 
				
			||||||
                </li>
 | 
					                </li>
 | 
				
			||||||
            ))}
 | 
					              )
 | 
				
			||||||
 | 
					            )}
 | 
				
			||||||
            <li
 | 
					            <li
 | 
				
			||||||
              className={`page-item ${currentPage === totalPages ? "disabled" : ""}`}
 | 
					              className={`page-item ${
 | 
				
			||||||
 | 
					                currentPage === totalPages ? "disabled" : ""
 | 
				
			||||||
 | 
					              }`}
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              <button
 | 
				
			||||||
 | 
					                className="page-link"
 | 
				
			||||||
 | 
					                onClick={() => paginate(currentPage + 1)}
 | 
				
			||||||
              >
 | 
					              >
 | 
				
			||||||
              <button className="page-link" onClick={() => paginate(currentPage + 1)}>
 | 
					 | 
				
			||||||
                »
 | 
					                »
 | 
				
			||||||
              </button>
 | 
					              </button>
 | 
				
			||||||
            </li>
 | 
					            </li>
 | 
				
			||||||
 | 
				
			|||||||
@ -28,10 +28,10 @@ const InfraPlanning = () =>
 | 
				
			|||||||
  const {projects_Details, loading: project_deatilsLoader, error: project_error,refetch} = useProjectDetails( selectedProject )
 | 
					  const {projects_Details, loading: project_deatilsLoader, error: project_error,refetch} = useProjectDetails( selectedProject )
 | 
				
			||||||
  const reloadedData = useSelector( ( store ) => store.localVariables.reload )
 | 
					  const reloadedData = useSelector( ( store ) => store.localVariables.reload )
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
  useEffect( () =>
 | 
					  // useEffect( () =>
 | 
				
			||||||
  {
 | 
					  // {
 | 
				
			||||||
    dispatch(setProjectId(projects[0]?.id))
 | 
					  //   dispatch(setProjectId(projects[0]?.id))
 | 
				
			||||||
  }, [ projects ] )
 | 
					  // }, [ projects ] )
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
   useEffect( () =>
 | 
					   useEffect( () =>
 | 
				
			||||||
   {
 | 
					   {
 | 
				
			||||||
 | 
				
			|||||||
@ -22,7 +22,7 @@ const Regularization = ({ handleRequest }) => {
 | 
				
			|||||||
  const sortByName = (a, b) => {
 | 
					  const sortByName = (a, b) => {
 | 
				
			||||||
    const nameA = a.firstName.toLowerCase() + a.lastName.toLowerCase();
 | 
					    const nameA = a.firstName.toLowerCase() + a.lastName.toLowerCase();
 | 
				
			||||||
    const nameB = b.firstName.toLowerCase() + b.lastName.toLowerCase();
 | 
					    const nameB = b.firstName.toLowerCase() + b.lastName.toLowerCase();
 | 
				
			||||||
    return nameA.localeCompare(nameB);
 | 
					    return nameA?.localeCompare(nameB);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const handler = useCallback(
 | 
					  const handler = useCallback(
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,7 @@ import showToast from "../../services/toastService";
 | 
				
			|||||||
import Avatar from "../common/Avatar";
 | 
					import Avatar from "../common/Avatar";
 | 
				
			||||||
import { getBgClassFromHash } from "../../utils/projectStatus";
 | 
					import { getBgClassFromHash } from "../../utils/projectStatus";
 | 
				
			||||||
import { cacheData, getCachedData } from "../../slices/apiDataManager";
 | 
					import { cacheData, getCachedData } from "../../slices/apiDataManager";
 | 
				
			||||||
 | 
					import ImagePreview from "../common/ImagePreview";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const schema = z.object({
 | 
					const schema = z.object({
 | 
				
			||||||
  comment: z.string().min(1, "Comment cannot be empty"),
 | 
					  comment: z.string().min(1, "Comment cannot be empty"),
 | 
				
			||||||
@ -40,7 +41,9 @@ const ReportTaskComments = ({ commentsData, closeModal }) => {
 | 
				
			|||||||
  useEffect(() => {
 | 
					  useEffect(() => {
 | 
				
			||||||
    const taskList = getCachedData("taskList");
 | 
					    const taskList = getCachedData("taskList");
 | 
				
			||||||
    if (taskList && taskList.data && commentsData?.id) {
 | 
					    if (taskList && taskList.data && commentsData?.id) {
 | 
				
			||||||
      const currentTask = taskList.data.find(task => task.id === commentsData.id);
 | 
					      const currentTask = taskList.data.find(
 | 
				
			||||||
 | 
					        (task) => task.id === commentsData.id
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
      if (currentTask && currentTask.comments) {
 | 
					      if (currentTask && currentTask.comments) {
 | 
				
			||||||
        setComment(currentTask.comments);
 | 
					        setComment(currentTask.comments);
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
@ -99,48 +102,16 @@ const ReportTaskComments = ({ commentsData, closeModal }) => {
 | 
				
			|||||||
      showToast("Successfully Sent", "success");
 | 
					      showToast("Successfully Sent", "success");
 | 
				
			||||||
    } catch (error) {
 | 
					    } catch (error) {
 | 
				
			||||||
      setloading(false);
 | 
					      setloading(false);
 | 
				
			||||||
      showToast(error.response.data?.message || "Something went wrong", "error");
 | 
					      showToast(
 | 
				
			||||||
 | 
					        error.response.data?.message || "Something went wrong",
 | 
				
			||||||
 | 
					        "error"
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div
 | 
					    <div className="p-1">
 | 
				
			||||||
      className="modal-dialog modal-lg modal-simple report-task-comments-modal mx-sm-auto mx-1"
 | 
					 | 
				
			||||||
      role="document"
 | 
					 | 
				
			||||||
    >
 | 
					 | 
				
			||||||
      <div className="modal-content">
 | 
					 | 
				
			||||||
      <div className="modal-body p-sm-4 p-0">
 | 
					      <div className="modal-body p-sm-4 p-0">
 | 
				
			||||||
          <button
 | 
					        <h5 className=" text-center mb-2">Activity Summary</h5>
 | 
				
			||||||
            type="button"
 | 
					 | 
				
			||||||
            className="btn-close"
 | 
					 | 
				
			||||||
            onClick={closeModal}
 | 
					 | 
				
			||||||
            aria-label="Close"
 | 
					 | 
				
			||||||
          ></button>
 | 
					 | 
				
			||||||
          <h5 className=" text-center mb-2">
 | 
					 | 
				
			||||||
            Activity Summary
 | 
					 | 
				
			||||||
          </h5>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          <p className="small-text text-start my-2">
 | 
					 | 
				
			||||||
            {commentsData?.workItem?.workArea?.floor?.building?.description}
 | 
					 | 
				
			||||||
          </p>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          <p className="fw-bold my-2 text-start">
 | 
					 | 
				
			||||||
            Assigned By :
 | 
					 | 
				
			||||||
            <span className=" ms-2">
 | 
					 | 
				
			||||||
              {commentsData?.assignedBy?.firstName +
 | 
					 | 
				
			||||||
                " " +
 | 
					 | 
				
			||||||
                commentsData?.assignedBy?.lastName}
 | 
					 | 
				
			||||||
            </span>{" "}
 | 
					 | 
				
			||||||
          </p>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          <p className="fw-bold my-2 text-start">
 | 
					 | 
				
			||||||
            Reported By :
 | 
					 | 
				
			||||||
            <span className=" ms-2"> -
 | 
					 | 
				
			||||||
              {/* {commentsData?.assignedBy?.firstName +
 | 
					 | 
				
			||||||
                " " +
 | 
					 | 
				
			||||||
                commentsData?.assignedBy?.lastName} */}
 | 
					 | 
				
			||||||
            </span>{" "}
 | 
					 | 
				
			||||||
          </p>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <p className="fw-bold my-2 text-start">
 | 
					        <p className="fw-bold my-2 text-start">
 | 
				
			||||||
          Location :
 | 
					          Location :
 | 
				
			||||||
@ -154,21 +125,41 @@ const ReportTaskComments = ({ commentsData, closeModal }) => {
 | 
				
			|||||||
            {` ${commentsData?.workItem?.activityMaster?.activityName}`}
 | 
					            {` ${commentsData?.workItem?.activityMaster?.activityName}`}
 | 
				
			||||||
          </span>
 | 
					          </span>
 | 
				
			||||||
        </p>
 | 
					        </p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <p className="fw-bold my-2 text-start">
 | 
				
			||||||
 | 
					          Assigned By :
 | 
				
			||||||
 | 
					          <span className=" ms-2">
 | 
				
			||||||
 | 
					            {commentsData?.assignedBy?.firstName +
 | 
				
			||||||
 | 
					              " " +
 | 
				
			||||||
 | 
					              commentsData?.assignedBy?.lastName}
 | 
				
			||||||
 | 
					          </span>{" "}
 | 
				
			||||||
 | 
					        </p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <p className="fw-bold my-2 text-start">
 | 
				
			||||||
 | 
					          Reported By :
 | 
				
			||||||
 | 
					          <span className=" ms-2">
 | 
				
			||||||
 | 
					            {" "}
 | 
				
			||||||
 | 
					            -
 | 
				
			||||||
 | 
					            {/* {commentsData?.assignedBy?.firstName +
 | 
				
			||||||
 | 
					                " " +
 | 
				
			||||||
 | 
					                commentsData?.assignedBy?.lastName} */}
 | 
				
			||||||
 | 
					          </span>{" "}
 | 
				
			||||||
 | 
					        </p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <p className="fw-bold my-2 text-start">
 | 
					        <p className="fw-bold my-2 text-start">
 | 
				
			||||||
          Planned Work: {commentsData?.plannedTask}{" "}
 | 
					          Planned Work: {commentsData?.plannedTask}{" "}
 | 
				
			||||||
              {
 | 
					          {commentsData?.workItem?.activityMaster?.unitOfMeasurement}
 | 
				
			||||||
                commentsData?.workItem?.activityMaster
 | 
					 | 
				
			||||||
                  ?.unitOfMeasurement
 | 
					 | 
				
			||||||
              }            
 | 
					 | 
				
			||||||
        </p>
 | 
					        </p>
 | 
				
			||||||
 | 
					        {commentsData?.reportedDate != null && (
 | 
				
			||||||
          <p className="fw-bold my-2 text-start">
 | 
					          <p className="fw-bold my-2 text-start">
 | 
				
			||||||
            {" "}
 | 
					            {" "}
 | 
				
			||||||
            Completed Work : {commentsData?.completedTask}{" "}
 | 
					            Completed Work : {commentsData?.completedTask}{" "}
 | 
				
			||||||
              {
 | 
					            {commentsData?.workItem?.activityMaster?.unitOfMeasurement}
 | 
				
			||||||
                commentsData?.workItem?.activityMaster
 | 
					 | 
				
			||||||
                  ?.unitOfMeasurement
 | 
					 | 
				
			||||||
              }            
 | 
					 | 
				
			||||||
          </p>
 | 
					          </p>
 | 
				
			||||||
 | 
					        )}
 | 
				
			||||||
 | 
					        {!commentsData?.reportedDate && (
 | 
				
			||||||
 | 
					          <p className="fw-bold my-2 text-start"> Completed Work :  -</p>
 | 
				
			||||||
 | 
					        )}
 | 
				
			||||||
        <div className="d-flex align-items-center flex-wrap">
 | 
					        <div className="d-flex align-items-center flex-wrap">
 | 
				
			||||||
          <p className="fw-bold text-start m-0 me-1">Team :</p>
 | 
					          <p className="fw-bold text-start m-0 me-1">Team :</p>
 | 
				
			||||||
          <div className="d-flex flex-wrap align-items-center gap-2">
 | 
					          <div className="d-flex flex-wrap align-items-center gap-2">
 | 
				
			||||||
@ -184,7 +175,23 @@ const ReportTaskComments = ({ commentsData, closeModal }) => {
 | 
				
			|||||||
            ))}
 | 
					            ))}
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div className="fw-bold my-2 text-start d-flex">
 | 
				
			||||||
 | 
					          <span>Note:</span>
 | 
				
			||||||
 | 
					          <div
 | 
				
			||||||
 | 
					            className="fw-normal ms-2"
 | 
				
			||||||
 | 
					            dangerouslySetInnerHTML={{ __html: commentsData?.description }}
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {commentsData?.reportedPreSignedUrls?.length > 0 && (
 | 
				
			||||||
 | 
					          <div className=" text-start">
 | 
				
			||||||
 | 
					            <p className="fw-bold m-0">Attachment</p>
 | 
				
			||||||
 | 
					            <ImagePreview
 | 
				
			||||||
 | 
					              IsReported={true}
 | 
				
			||||||
 | 
					              images={commentsData?.reportedPreSignedUrls}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        )}
 | 
				
			||||||
        <form onSubmit={handleSubmit(onSubmit)} className="text-start">
 | 
					        <form onSubmit={handleSubmit(onSubmit)} className="text-start">
 | 
				
			||||||
          <label className="fw-bold text-start my-1">Add comment :</label>
 | 
					          <label className="fw-bold text-start my-1">Add comment :</label>
 | 
				
			||||||
          <textarea
 | 
					          <textarea
 | 
				
			||||||
@ -205,7 +212,11 @@ const ReportTaskComments = ({ commentsData, closeModal }) => {
 | 
				
			|||||||
            >
 | 
					            >
 | 
				
			||||||
              Close
 | 
					              Close
 | 
				
			||||||
            </button>
 | 
					            </button>
 | 
				
			||||||
              <button type="submit" className="btn btn-sm btn-primary ms-2" disabled={loading}>
 | 
					            <button
 | 
				
			||||||
 | 
					              type="submit"
 | 
				
			||||||
 | 
					              className="btn btn-sm btn-primary ms-2"
 | 
				
			||||||
 | 
					              disabled={loading}
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
              {loading ? "Sending..." : "Comment"}
 | 
					              {loading ? "Sending..." : "Comment"}
 | 
				
			||||||
            </button>
 | 
					            </button>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
@ -233,25 +244,43 @@ const ReportTaskComments = ({ commentsData, closeModal }) => {
 | 
				
			|||||||
                        <span
 | 
					                        <span
 | 
				
			||||||
                          className={`avatar-initial rounded-circle bg-label-primary`}
 | 
					                          className={`avatar-initial rounded-circle bg-label-primary`}
 | 
				
			||||||
                        >
 | 
					                        >
 | 
				
			||||||
                            {`${data?.employee?.firstName?.slice(0, 1)} ${data?.employee?.lastName?.slice(0, 1)}`}
 | 
					                          {`${data?.employee?.firstName?.slice(
 | 
				
			||||||
 | 
					                            0,
 | 
				
			||||||
 | 
					                            1
 | 
				
			||||||
 | 
					                          )} ${data?.employee?.lastName?.slice(0, 1)}`}
 | 
				
			||||||
                        </span>
 | 
					                        </span>
 | 
				
			||||||
                      </div>
 | 
					                      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        <div className={`d-flex align-items-center justify-content-start`}>
 | 
					                      <div
 | 
				
			||||||
 | 
					                        className={`d-flex align-items-center justify-content-start`}
 | 
				
			||||||
 | 
					                      >
 | 
				
			||||||
                        <p className={`mb-0 text-muted me-2`}>{fullName}</p>
 | 
					                        <p className={`mb-0 text-muted me-2`}>{fullName}</p>
 | 
				
			||||||
                          <p className={`text-secondary m-0`} style={{ fontSize: "10px" }}>
 | 
					                        <p
 | 
				
			||||||
 | 
					                          className={`text-secondary m-0`}
 | 
				
			||||||
 | 
					                          style={{ fontSize: "10px" }}
 | 
				
			||||||
 | 
					                        >
 | 
				
			||||||
                          {moment.utc(data?.commentDate).local().fromNow()}
 | 
					                          {moment.utc(data?.commentDate).local().fromNow()}
 | 
				
			||||||
                        </p>
 | 
					                        </p>
 | 
				
			||||||
                      </div>
 | 
					                      </div>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                      <p className={`ms-6 text-start mb-0 text-body`}>{data?.comment}</p>
 | 
					                    <p className={`ms-6 text-start mb-0 text-body`}>
 | 
				
			||||||
 | 
					                      {data?.comment}
 | 
				
			||||||
 | 
					                    </p>
 | 
				
			||||||
 | 
					                    {data?.preSignedUrls?.length > 0 && (
 | 
				
			||||||
 | 
					                      <div className="ps-6 text-start">
 | 
				
			||||||
 | 
					                        <small className="">Attachment</small>
 | 
				
			||||||
 | 
					                        <ImagePreview
 | 
				
			||||||
 | 
					                          images={data?.preSignedUrls}
 | 
				
			||||||
 | 
					                          IsReported={true}
 | 
				
			||||||
 | 
					                        />
 | 
				
			||||||
 | 
					                      </div>
 | 
				
			||||||
 | 
					                    )}
 | 
				
			||||||
                  </li>
 | 
					                  </li>
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
              })}
 | 
					              })}
 | 
				
			||||||
        </ul>
 | 
					        </ul>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -4,34 +4,46 @@ import { useProjects } from "../../hooks/useProjects";
 | 
				
			|||||||
import { useDashboard_Data } from "../../hooks/useDashboard_Data";
 | 
					import { useDashboard_Data } from "../../hooks/useDashboard_Data";
 | 
				
			||||||
import { useSelector } from "react-redux";
 | 
					import { useSelector } from "react-redux";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const ProjectProgressChart = () =>
 | 
					const ProjectProgressChart = () => {
 | 
				
			||||||
{
 | 
					  const selectedProject = useSelector(
 | 
				
			||||||
  const selectedProject = useSelector((store) => store.localVariables.projectId);
 | 
					    (store) => store.localVariables.projectId
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
  const { projects } = useProjects();
 | 
					  const { projects } = useProjects();
 | 
				
			||||||
  // const [selectedProjectId, setSelectedProjectId] = useState("all");
 | 
					  const [range, setRange] = useState("15D");
 | 
				
			||||||
  const [range, setRange] = useState("1W");
 | 
					  const [showAllEmployees, setShowAllEmployees] = useState(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const getDaysFromRange = (range) => {
 | 
					  const getDaysFromRange = (range) => {
 | 
				
			||||||
    switch (range) {
 | 
					    switch (range) {
 | 
				
			||||||
      case "1D": return 1;
 | 
					      case "1D":
 | 
				
			||||||
      case "1W": return 7;
 | 
					        return 1;
 | 
				
			||||||
      case "15D": return 15;
 | 
					      case "1W":
 | 
				
			||||||
      case "1M": return 30;
 | 
					        return 7;
 | 
				
			||||||
      case "3M": return 90;
 | 
					      case "15D":
 | 
				
			||||||
      case "1Y": return 365;
 | 
					        return 15;
 | 
				
			||||||
      case "5Y": return 1825;
 | 
					      case "1M":
 | 
				
			||||||
      default: return 7;
 | 
					        return 30;
 | 
				
			||||||
 | 
					      case "3M":
 | 
				
			||||||
 | 
					        return 90;
 | 
				
			||||||
 | 
					      case "1Y":
 | 
				
			||||||
 | 
					        return 365;
 | 
				
			||||||
 | 
					      case "5Y":
 | 
				
			||||||
 | 
					        return 1825;
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        return 7;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const days = getDaysFromRange(range);
 | 
					  const days = getDaysFromRange(range);
 | 
				
			||||||
  const today = new Date();
 | 
					  const today = new Date();
 | 
				
			||||||
  const FromDate = today.toLocaleDateString('en-CA');
 | 
					  const FromDate = today.toLocaleDateString("en-CA");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const projectId =
 | 
				
			||||||
 | 
					    showAllEmployees || !selectedProject?.trim() ? null : selectedProject;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const { dashboard_data, loading: isLineChartLoading } = useDashboard_Data({
 | 
					  const { dashboard_data, loading: isLineChartLoading } = useDashboard_Data({
 | 
				
			||||||
    days,
 | 
					    days,
 | 
				
			||||||
    FromDate,
 | 
					    FromDate,
 | 
				
			||||||
     projectId:  selectedProject  === " "  ? "all" : selectedProject//  selectedProjectId === "all" ? null : selectedProjectId,
 | 
					    projectId,
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const sortedDashboardData = [...dashboard_data].sort(
 | 
					  const sortedDashboardData = [...dashboard_data].sort(
 | 
				
			||||||
@ -50,61 +62,69 @@ const ProjectProgressChart = () =>
 | 
				
			|||||||
  ];
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const lineChartCategories = sortedDashboardData.map((d) =>
 | 
					  const lineChartCategories = sortedDashboardData.map((d) =>
 | 
				
			||||||
    new Date(d.date).toLocaleDateString("en-US", { month: "short", day: "numeric" })
 | 
					    new Date(d.date).toLocaleDateString("en-US", {
 | 
				
			||||||
 | 
					      month: "short",
 | 
				
			||||||
 | 
					      day: "numeric",
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
  const lineChartCategoriesDates = sortedDashboardData.map((d) =>
 | 
					  const lineChartCategoriesDates = sortedDashboardData.map((d) =>
 | 
				
			||||||
    new Date(d.date).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })
 | 
					    new Date(d.date).toLocaleDateString("en-US", {
 | 
				
			||||||
 | 
					      month: "short",
 | 
				
			||||||
 | 
					      day: "numeric",
 | 
				
			||||||
 | 
					      year: "numeric",
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const selectedProjectData = projects?.find((p) => p.id === selectedProject);
 | 
				
			||||||
 | 
					  const selectedProjectName = selectedProjectData?.shortName?.trim()
 | 
				
			||||||
 | 
					    ? selectedProjectData.shortName
 | 
				
			||||||
 | 
					    : selectedProjectData?.name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div className="card h-100">
 | 
					    <div className="card h-100">
 | 
				
			||||||
      <div className="card-header">
 | 
					      <div className="card-header">
 | 
				
			||||||
        {/* Row 1: Title + Project Selector */}
 | 
					        <div className="d-flex flex-wrap justify-content-between align-items-start mb-2">
 | 
				
			||||||
        <div className="d-flex flex-wrap justify-content-between align-items-center mb-2">
 | 
					          {/* Left: Title */}
 | 
				
			||||||
          <div className="card-title mb-0 text-start">
 | 
					          <div className="card-title text-start">
 | 
				
			||||||
            <h5 className="mb-1">Project Progress</h5>
 | 
					            <h5 className="mb-1">Project Progress</h5>
 | 
				
			||||||
            <p className="card-subtitle">Progress Overview by Project</p>
 | 
					            <p className="card-subtitle">Progress Overview by Project</p>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          {/* <div className="btn-group">
 | 
					          {/* Right: Checkbox and Project Name */}
 | 
				
			||||||
            <button
 | 
					          <div className="d-flex flex-column align-items-start align-items-md-end text-start text-md-end mt-1 mt-md-0">
 | 
				
			||||||
              className="btn btn-outline-primary btn-sm dropdown-toggle"
 | 
					            <div className="form-check form-switch mb-1 d-flex align-items-center">
 | 
				
			||||||
              type="button"
 | 
					              <input
 | 
				
			||||||
              data-bs-toggle="dropdown"
 | 
					                className="form-check-input"
 | 
				
			||||||
              aria-expanded="false"
 | 
					                type="checkbox"
 | 
				
			||||||
 | 
					                role="switch"
 | 
				
			||||||
 | 
					                id="showAllEmployees"
 | 
				
			||||||
 | 
					                checked={showAllEmployees}
 | 
				
			||||||
 | 
					                onChange={(e) => setShowAllEmployees(e.target.checked)}
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					              <label
 | 
				
			||||||
 | 
					                className="form-check-label ms-2"
 | 
				
			||||||
 | 
					                htmlFor="showAllEmployees"
 | 
				
			||||||
              >
 | 
					              >
 | 
				
			||||||
              {selectedProjectId === "all"
 | 
					 | 
				
			||||||
                ? "All Projects"
 | 
					 | 
				
			||||||
                : projects?.find((p) => p.id === selectedProjectId)?.name || "Select Project"}
 | 
					 | 
				
			||||||
            </button>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            <ul className="dropdown-menu">
 | 
					 | 
				
			||||||
              <li>
 | 
					 | 
				
			||||||
                <button className="dropdown-item" onClick={() => setSelectedProjectId("all")}>
 | 
					 | 
				
			||||||
                All Projects
 | 
					                All Projects
 | 
				
			||||||
                </button>
 | 
					              </label>
 | 
				
			||||||
              </li>
 | 
					            </div>
 | 
				
			||||||
              {projects?.map((project) => (
 | 
					            {!showAllEmployees && selectedProjectName && (
 | 
				
			||||||
                <li key={project.id}>
 | 
					              <p className="text-muted mb-0 small">
 | 
				
			||||||
                  <button
 | 
					                <span className="card-subtitle">{selectedProjectName}</span>
 | 
				
			||||||
                    className="dropdown-item"
 | 
					              </p>
 | 
				
			||||||
                    onClick={() => setSelectedProjectId(project.id)}
 | 
					            )}
 | 
				
			||||||
                  >
 | 
					          </div>
 | 
				
			||||||
                    {project.name}
 | 
					 | 
				
			||||||
                  </button>
 | 
					 | 
				
			||||||
                </li>
 | 
					 | 
				
			||||||
              ))}
 | 
					 | 
				
			||||||
            </ul>
 | 
					 | 
				
			||||||
          </div> */}
 | 
					 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        {/* Row 2: Time Range Buttons */}
 | 
					        {/* Row 2: Time Range Buttons */}
 | 
				
			||||||
        <div className="d-flex flex-wrap  mt-2">
 | 
					        <div className="d-flex flex-wrap mt-2">
 | 
				
			||||||
          {["1D", "1W", "15D", "1M", "3M", "1Y", "5Y"].map((key) => (
 | 
					          {["1D", "1W", "15D", "1M", "3M", "1Y", "5Y"].map((key) => (
 | 
				
			||||||
            <button
 | 
					            <button
 | 
				
			||||||
              key={key}
 | 
					              key={key}
 | 
				
			||||||
              className={`border-0 bg-transparent px-2 py-1 text-sm rounded ${
 | 
					              className={`border-0 bg-transparent px-2 py-1 text-sm rounded ${
 | 
				
			||||||
                range === key ? " border-bottom border-primary text-primary" : "text-muted"
 | 
					                range === key
 | 
				
			||||||
 | 
					                  ? "border-bottom border-primary text-primary"
 | 
				
			||||||
 | 
					                  : "text-muted"
 | 
				
			||||||
              }`}
 | 
					              }`}
 | 
				
			||||||
              style={{ cursor: "pointer", transition: "all 0.2s ease" }}
 | 
					              style={{ cursor: "pointer", transition: "all 0.2s ease" }}
 | 
				
			||||||
              onClick={() => setRange(key)}
 | 
					              onClick={() => setRange(key)}
 | 
				
			||||||
@ -114,6 +134,7 @@ const ProjectProgressChart = () =>
 | 
				
			|||||||
          ))}
 | 
					          ))}
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <div className="card-body">
 | 
					      <div className="card-body">
 | 
				
			||||||
        <LineChart
 | 
					        <LineChart
 | 
				
			||||||
          seriesData={lineChartSeries}
 | 
					          seriesData={lineChartSeries}
 | 
				
			||||||
 | 
				
			|||||||
@ -10,7 +10,11 @@ import { changeMaster } from "../../slices/localVariablesSlice";
 | 
				
			|||||||
import { Link, 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 { cacheData, clearCacheKey, getCachedData } from "../../slices/apiDataManager";
 | 
					import {
 | 
				
			||||||
 | 
					  cacheData,
 | 
				
			||||||
 | 
					  clearCacheKey,
 | 
				
			||||||
 | 
					  getCachedData,
 | 
				
			||||||
 | 
					} from "../../slices/apiDataManager";
 | 
				
			||||||
import { clearApiCacheKey } from "../../slices/apiCacheSlice";
 | 
					import { clearApiCacheKey } from "../../slices/apiCacheSlice";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const mobileNumberRegex = /^[0-9]\d{9}$/;
 | 
					const mobileNumberRegex = /^[0-9]\d{9}$/;
 | 
				
			||||||
@ -178,7 +182,6 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
 | 
				
			|||||||
        clearCacheKey("allInactiveEmployeeList");
 | 
					        clearCacheKey("allInactiveEmployeeList");
 | 
				
			||||||
        clearCacheKey("employeeProfile");
 | 
					        clearCacheKey("employeeProfile");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        setLoading(false);
 | 
					        setLoading(false);
 | 
				
			||||||
        reset();
 | 
					        reset();
 | 
				
			||||||
        // navigation("/employees");
 | 
					        // navigation("/employees");
 | 
				
			||||||
@ -238,10 +241,7 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
 | 
				
			|||||||
                {employee ? "Update Employee" : "Create Employee"}
 | 
					                {employee ? "Update Employee" : "Create Employee"}
 | 
				
			||||||
              </h6>
 | 
					              </h6>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              <span
 | 
					              <span className="cursor-pointer fs-6" onClick={() => onClosed()}>
 | 
				
			||||||
                className="cursor-pointer fs-6"
 | 
					 | 
				
			||||||
                onClick={() => onClosed()}
 | 
					 | 
				
			||||||
              >
 | 
					 | 
				
			||||||
                <i className="bx bx-x"></i>
 | 
					                <i className="bx bx-x"></i>
 | 
				
			||||||
              </span>
 | 
					              </span>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
@ -509,7 +509,9 @@ const ManageEmployee = ({ employeeId, onClosed }) => {
 | 
				
			|||||||
                        <option disabled value="">
 | 
					                        <option disabled value="">
 | 
				
			||||||
                          Select Role
 | 
					                          Select Role
 | 
				
			||||||
                        </option>
 | 
					                        </option>
 | 
				
			||||||
                        {job_role?.map((item) => (
 | 
					                        {[...job_role]
 | 
				
			||||||
 | 
					                          .sort((a, b) => a?.name?.localeCompare(b.name))
 | 
				
			||||||
 | 
					                          .map((item) => (
 | 
				
			||||||
                            <option value={item?.id} key={item.id}>
 | 
					                            <option value={item?.id} key={item.id}>
 | 
				
			||||||
                              {item?.name}{" "}
 | 
					                              {item?.name}{" "}
 | 
				
			||||||
                            </option>
 | 
					                            </option>
 | 
				
			||||||
 | 
				
			|||||||
@ -177,14 +177,29 @@ const Header = () => {
 | 
				
			|||||||
                  </button>
 | 
					                  </button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                  {projectNames?.length > 1 && (
 | 
					                  {projectNames?.length > 1 && (
 | 
				
			||||||
                    <ul className="dropdown-menu">
 | 
					                    <ul
 | 
				
			||||||
                      {projectNames?.map((project) => (
 | 
					                      className="dropdown-menu"
 | 
				
			||||||
 | 
					                      style={{ overflow: "auto", maxHeight: "300px" }}
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                      {[...projectNames]
 | 
				
			||||||
 | 
					                        .sort((a, b) => a.name.localeCompare(b.name))
 | 
				
			||||||
 | 
					                        .map((project) => (
 | 
				
			||||||
                          <li key={project?.id}>
 | 
					                          <li key={project?.id}>
 | 
				
			||||||
                            <button
 | 
					                            <button
 | 
				
			||||||
                              className="dropdown-item"
 | 
					                              className="dropdown-item"
 | 
				
			||||||
                            onClick={() => dispatch(setProjectId(project?.id))}
 | 
					                              onClick={() =>
 | 
				
			||||||
 | 
					                                dispatch(setProjectId(project?.id))
 | 
				
			||||||
 | 
					                              }
 | 
				
			||||||
                            >
 | 
					                            >
 | 
				
			||||||
                            {project?.name}
 | 
					                              {project?.name}{" "}
 | 
				
			||||||
 | 
					                              {project?.shortName ? (
 | 
				
			||||||
 | 
					                                <span className="text-primary fw-semibold">
 | 
				
			||||||
 | 
					                                  {" "}
 | 
				
			||||||
 | 
					                                  ({project?.shortName})
 | 
				
			||||||
 | 
					                                </span>
 | 
				
			||||||
 | 
					                              ) : (
 | 
				
			||||||
 | 
					                                ""
 | 
				
			||||||
 | 
					                              )}
 | 
				
			||||||
                            </button>
 | 
					                            </button>
 | 
				
			||||||
                          </li>
 | 
					                          </li>
 | 
				
			||||||
                        ))}
 | 
					                        ))}
 | 
				
			||||||
@ -200,7 +215,7 @@ const Header = () => {
 | 
				
			|||||||
          <li className="nav-item dropdown-shortcuts navbar-dropdown dropdown me-2 me-xl-0">
 | 
					          <li className="nav-item dropdown-shortcuts navbar-dropdown dropdown me-2 me-xl-0">
 | 
				
			||||||
            <a
 | 
					            <a
 | 
				
			||||||
              className="nav-link dropdown-toggle hide-arrow"
 | 
					              className="nav-link dropdown-toggle hide-arrow"
 | 
				
			||||||
              href="#;"
 | 
					
 | 
				
			||||||
              data-bs-toggle="dropdown"
 | 
					              data-bs-toggle="dropdown"
 | 
				
			||||||
              data-bs-auto-close="true"
 | 
					              data-bs-auto-close="true"
 | 
				
			||||||
              aria-expanded="false"
 | 
					              aria-expanded="false"
 | 
				
			||||||
@ -309,7 +324,7 @@ const Header = () => {
 | 
				
			|||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
          </li>
 | 
					          </li>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <li className="nav-item dropdown-notifications navbar-dropdown dropdown me-2 me-xl-0">
 | 
					          {/* <li className="nav-item dropdown-notifications navbar-dropdown dropdown me-2 me-xl-0">
 | 
				
			||||||
            <a
 | 
					            <a
 | 
				
			||||||
              className="nav-link dropdown-toggle hide-arrow cursor-pointer"
 | 
					              className="nav-link dropdown-toggle hide-arrow cursor-pointer"
 | 
				
			||||||
              data-bs-toggle="dropdown"
 | 
					              data-bs-toggle="dropdown"
 | 
				
			||||||
@ -603,20 +618,7 @@ const Header = () => {
 | 
				
			|||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                  </li>
 | 
					                  </li>
 | 
				
			||||||
                </ul>
 | 
					                </ul>
 | 
				
			||||||
                {/* <div className="ps__rail-x" style="left: 0px; bottom: 0px;">
 | 
					  
 | 
				
			||||||
                  <div
 | 
					 | 
				
			||||||
                    className="ps__thumb-x"
 | 
					 | 
				
			||||||
                    tabindex="0"
 | 
					 | 
				
			||||||
                    style="left: 0px; width: 0px;"
 | 
					 | 
				
			||||||
                  ></div>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
                <div className="ps__rail-y" style="top: 0px; right: 0px;">
 | 
					 | 
				
			||||||
                  <div
 | 
					 | 
				
			||||||
                    className="ps__thumb-y"
 | 
					 | 
				
			||||||
                    tabindex="0"
 | 
					 | 
				
			||||||
                    style="top: 0px; height: 0px;"
 | 
					 | 
				
			||||||
                  ></div>
 | 
					 | 
				
			||||||
                </div> */}
 | 
					 | 
				
			||||||
              </li>
 | 
					              </li>
 | 
				
			||||||
              <li className="border-top">
 | 
					              <li className="border-top">
 | 
				
			||||||
                <div className="d-grid p-4">
 | 
					                <div className="d-grid p-4">
 | 
				
			||||||
@ -628,7 +630,7 @@ const Header = () => {
 | 
				
			|||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
              </li>
 | 
					              </li>
 | 
				
			||||||
            </ul>
 | 
					            </ul>
 | 
				
			||||||
          </li>
 | 
					          </li> */}
 | 
				
			||||||
          <li className="nav-item navbar-dropdown dropdown-user dropdown">
 | 
					          <li className="nav-item navbar-dropdown dropdown-user dropdown">
 | 
				
			||||||
            <a
 | 
					            <a
 | 
				
			||||||
              aria-label="dropdown profile avatar"
 | 
					              aria-label="dropdown profile avatar"
 | 
				
			||||||
@ -678,7 +680,7 @@ const Header = () => {
 | 
				
			|||||||
                  <span className="align-middle">My Profile</span>
 | 
					                  <span className="align-middle">My Profile</span>
 | 
				
			||||||
                </a>
 | 
					                </a>
 | 
				
			||||||
              </li>
 | 
					              </li>
 | 
				
			||||||
              <li>
 | 
					              <li onClick={handleProfilePage}>
 | 
				
			||||||
                <a
 | 
					                <a
 | 
				
			||||||
                  aria-label="go to setting "
 | 
					                  aria-label="go to setting "
 | 
				
			||||||
                  className="dropdown-item cusor-pointer"
 | 
					                  className="dropdown-item cusor-pointer"
 | 
				
			||||||
@ -687,7 +689,7 @@ const Header = () => {
 | 
				
			|||||||
                  <span className="align-middle">Settings</span>
 | 
					                  <span className="align-middle">Settings</span>
 | 
				
			||||||
                </a>
 | 
					                </a>
 | 
				
			||||||
              </li>
 | 
					              </li>
 | 
				
			||||||
              <li>
 | 
					              {/* <li>
 | 
				
			||||||
                <a
 | 
					                <a
 | 
				
			||||||
                  aria-label="go to billing "
 | 
					                  aria-label="go to billing "
 | 
				
			||||||
                  className="dropdown-item cusor-pointer"
 | 
					                  className="dropdown-item cusor-pointer"
 | 
				
			||||||
@ -702,7 +704,7 @@ const Header = () => {
 | 
				
			|||||||
                    </span>
 | 
					                    </span>
 | 
				
			||||||
                  </span>
 | 
					                  </span>
 | 
				
			||||||
                </a>
 | 
					                </a>
 | 
				
			||||||
              </li>
 | 
					              </li> */}
 | 
				
			||||||
              <li onClick={openChangePassword}>
 | 
					              <li onClick={openChangePassword}>
 | 
				
			||||||
                {" "}
 | 
					                {" "}
 | 
				
			||||||
                {/* Use the function from the context */}
 | 
					                {/* Use the function from the context */}
 | 
				
			||||||
 | 
				
			|||||||
@ -273,7 +273,7 @@ const EditActivityModal = ({
 | 
				
			|||||||
                    activities
 | 
					                    activities
 | 
				
			||||||
                      .slice()
 | 
					                      .slice()
 | 
				
			||||||
                      .sort((a, b) =>
 | 
					                      .sort((a, b) =>
 | 
				
			||||||
                        (a.activityName || "").localeCompare(
 | 
					                        (a.activityName || "")?.localeCompare(
 | 
				
			||||||
                          b.activityName || ""
 | 
					                          b.activityName || ""
 | 
				
			||||||
                        )
 | 
					                        )
 | 
				
			||||||
                      )
 | 
					                      )
 | 
				
			||||||
@ -312,7 +312,7 @@ const EditActivityModal = ({
 | 
				
			|||||||
                    categories
 | 
					                    categories
 | 
				
			||||||
                      .slice()
 | 
					                      .slice()
 | 
				
			||||||
                      .sort((a, b) =>
 | 
					                      .sort((a, b) =>
 | 
				
			||||||
                        (a.name || "").localeCompare(
 | 
					                        (a.name || "")?.localeCompare(
 | 
				
			||||||
                          b.name || ""
 | 
					                          b.name || ""
 | 
				
			||||||
                        )
 | 
					                        )
 | 
				
			||||||
                      )
 | 
					                      )
 | 
				
			||||||
 | 
				
			|||||||
@ -140,7 +140,7 @@ const FloorModel = ({
 | 
				
			|||||||
                    buildings
 | 
					                    buildings
 | 
				
			||||||
                      .filter((building) => building?.name)
 | 
					                      .filter((building) => building?.name)
 | 
				
			||||||
                      .sort((a, b) =>
 | 
					                      .sort((a, b) =>
 | 
				
			||||||
                        (a.name || "").localeCompare(b.name || "")
 | 
					                        (a.name || "")?.localeCompare(b.name || "")
 | 
				
			||||||
                      )
 | 
					                      )
 | 
				
			||||||
                      .map((building) => (
 | 
					                      .map((building) => (
 | 
				
			||||||
                        <option key={building.id} value={building.id}>
 | 
					                        <option key={building.id} value={building.id}>
 | 
				
			||||||
@ -172,7 +172,7 @@ const FloorModel = ({
 | 
				
			|||||||
                        [...selectedBuilding.floors]
 | 
					                        [...selectedBuilding.floors]
 | 
				
			||||||
                          .filter((floor) => floor?.floorName)
 | 
					                          .filter((floor) => floor?.floorName)
 | 
				
			||||||
                          .sort((a, b) =>
 | 
					                          .sort((a, b) =>
 | 
				
			||||||
                            (a.floorName || "").localeCompare(
 | 
					                            (a.floorName || "")?.localeCompare(
 | 
				
			||||||
                              b.floorName || ""
 | 
					                              b.floorName || ""
 | 
				
			||||||
                            )
 | 
					                            )
 | 
				
			||||||
                          )
 | 
					                          )
 | 
				
			||||||
 | 
				
			|||||||
@ -159,7 +159,7 @@ const TaskModel = ({
 | 
				
			|||||||
      const newCategories = categories?.slice()?.sort((a, b) => {
 | 
					      const newCategories = categories?.slice()?.sort((a, b) => {
 | 
				
			||||||
        const nameA = a?.name || "";
 | 
					        const nameA = a?.name || "";
 | 
				
			||||||
        const nameB = b?.name || "";
 | 
					        const nameB = b?.name || "";
 | 
				
			||||||
        return nameA.localeCompare(nameB);
 | 
					        return nameA?.localeCompare(nameB);
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      setCategoryData(newCategories);
 | 
					      setCategoryData(newCategories);
 | 
				
			||||||
      setSelectedCategory(newCategories[0])
 | 
					      setSelectedCategory(newCategories[0])
 | 
				
			||||||
@ -230,7 +230,7 @@ const TaskModel = ({
 | 
				
			|||||||
                        (floor) =>
 | 
					                        (floor) =>
 | 
				
			||||||
                          floor?.floorName && Array.isArray(floor.workAreas)
 | 
					                          floor?.floorName && Array.isArray(floor.workAreas)
 | 
				
			||||||
                      )
 | 
					                      )
 | 
				
			||||||
                      ?.sort((a, b) => a.floorName.localeCompare(b.floorName))
 | 
					                      ?.sort((a, b) => a.floorName?.localeCompare(b.floorName))
 | 
				
			||||||
                      ?.map((floor) => (
 | 
					                      ?.map((floor) => (
 | 
				
			||||||
                        <option key={floor.id} value={floor.id}>
 | 
					                        <option key={floor.id} value={floor.id}>
 | 
				
			||||||
                          {floor.floorName} - ({floor.workAreas.length} Work
 | 
					                          {floor.floorName} - ({floor.workAreas.length} Work
 | 
				
			||||||
@ -263,7 +263,7 @@ const TaskModel = ({
 | 
				
			|||||||
                    <option value="0">Select Work Area</option>
 | 
					                    <option value="0">Select Work Area</option>
 | 
				
			||||||
                    {selectedFloor.workAreas
 | 
					                    {selectedFloor.workAreas
 | 
				
			||||||
                      ?.filter((workArea) => workArea?.areaName)
 | 
					                      ?.filter((workArea) => workArea?.areaName)
 | 
				
			||||||
                      ?.sort((a, b) => a.areaName.localeCompare(b.areaName))
 | 
					                      ?.sort((a, b) => a.areaName?.localeCompare(b.areaName))
 | 
				
			||||||
                      ?.map((workArea) => (
 | 
					                      ?.map((workArea) => (
 | 
				
			||||||
                        <option key={workArea.id} value={workArea.id}>
 | 
					                        <option key={workArea.id} value={workArea.id}>
 | 
				
			||||||
                          {workArea.areaName}
 | 
					                          {workArea.areaName}
 | 
				
			||||||
@ -299,7 +299,7 @@ const TaskModel = ({
 | 
				
			|||||||
                        ?.sort((a, b) => {
 | 
					                        ?.sort((a, b) => {
 | 
				
			||||||
                          const nameA = a?.activityName || "";
 | 
					                          const nameA = a?.activityName || "";
 | 
				
			||||||
                          const nameB = b?.activityName || "";
 | 
					                          const nameB = b?.activityName || "";
 | 
				
			||||||
                          return nameA.localeCompare(nameB);
 | 
					                          return nameA?.localeCompare(nameB);
 | 
				
			||||||
                        })
 | 
					                        })
 | 
				
			||||||
                        ?.map((activity) => (
 | 
					                        ?.map((activity) => (
 | 
				
			||||||
                          <option key={activity.id} value={activity.id}>
 | 
					                          <option key={activity.id} value={activity.id}>
 | 
				
			||||||
 | 
				
			|||||||
@ -197,7 +197,7 @@ const WorkAreaModel = ({
 | 
				
			|||||||
                      ?.sort((a, b) => {
 | 
					                      ?.sort((a, b) => {
 | 
				
			||||||
                        const nameA = a.floorName || "";
 | 
					                        const nameA = a.floorName || "";
 | 
				
			||||||
                        const nameB = b.floorName || "";
 | 
					                        const nameB = b.floorName || "";
 | 
				
			||||||
                        return nameA.localeCompare(nameB);
 | 
					                        return nameA?.localeCompare(nameB);
 | 
				
			||||||
                      })
 | 
					                      })
 | 
				
			||||||
                      ?.map((floor) => (
 | 
					                      ?.map((floor) => (
 | 
				
			||||||
                        <option key={floor.id} value={floor.id}>
 | 
					                        <option key={floor.id} value={floor.id}>
 | 
				
			||||||
@ -231,7 +231,7 @@ const WorkAreaModel = ({
 | 
				
			|||||||
                        ?.sort((a, b) => {
 | 
					                        ?.sort((a, b) => {
 | 
				
			||||||
                          const nameA = a.areaName || "";
 | 
					                          const nameA = a.areaName || "";
 | 
				
			||||||
                          const nameB = b.areaName || "";
 | 
					                          const nameB = b.areaName || "";
 | 
				
			||||||
                          return nameA.localeCompare(nameB);
 | 
					                          return nameA?.localeCompare(nameB);
 | 
				
			||||||
                        })
 | 
					                        })
 | 
				
			||||||
                        ?.map((workArea) => (
 | 
					                        ?.map((workArea) => (
 | 
				
			||||||
                          <option key={workArea.id} value={workArea.id}>
 | 
					                          <option key={workArea.id} value={workArea.id}>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										66
									
								
								src/components/common/ImagePreview.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/components/common/ImagePreview.jsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,66 @@
 | 
				
			|||||||
 | 
					import React, { useState } from "react";
 | 
				
			||||||
 | 
					import "./ImagePreviewstyle.css";
 | 
				
			||||||
 | 
					import GlobalModel from "./GlobalModel";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ImagePreview = ({ images = [], IsReported = false }) => {
 | 
				
			||||||
 | 
					  const [selectedImage, setSelectedImage] = useState(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleOpen = (imgSrc) => {
 | 
				
			||||||
 | 
					    setSelectedImage(imgSrc);
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleClose = () => {
 | 
				
			||||||
 | 
					    setSelectedImage(null);
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <>
 | 
				
			||||||
 | 
					      {IsReported ? (
 | 
				
			||||||
 | 
					        <div className="d-flex flex-wrap gap-2">
 | 
				
			||||||
 | 
					          {images.map((img, index) => (
 | 
				
			||||||
 | 
					            <div
 | 
				
			||||||
 | 
					              key={index}
 | 
				
			||||||
 | 
					              className="img-container position-relative"
 | 
				
			||||||
 | 
					              onClick={() => handleOpen(img)}
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              <img src={img} alt={`thumb-${index}`} className="img-thumbnail" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              <div className="eye-overlay d-flex justify-content-center align-items-center">
 | 
				
			||||||
 | 
					                <i className="fa-solid fa-eye fs-6"></i>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          ))}
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      ) : (
 | 
				
			||||||
 | 
					        <div className="d-flex flex-wrap gap-2">
 | 
				
			||||||
 | 
					          {images.map((img, index) => (
 | 
				
			||||||
 | 
					            <div key={index} className="" onClick={() => handleOpen(img)}>
 | 
				
			||||||
 | 
					              {/* <img src={img} alt={`thumb-${ index }`} className="img-thumbnail" /> */}
 | 
				
			||||||
 | 
					              <i className="fa-regular fa-image fs-3 cursor-pointer"></i>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          ))}
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      )}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      {selectedImage && (
 | 
				
			||||||
 | 
					        <GlobalModel
 | 
				
			||||||
 | 
					          isOpen={selectedImage}
 | 
				
			||||||
 | 
					          size="md"
 | 
				
			||||||
 | 
					          dialogClass="modal-dialog-centered"
 | 
				
			||||||
 | 
					          closeModal={() => setSelectedImage(null)}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					          <div className="mt-3 img-preview" >
 | 
				
			||||||
 | 
					            <img
 | 
				
			||||||
 | 
					              src={selectedImage}
 | 
				
			||||||
 | 
					              alt="Previe Image"
 | 
				
			||||||
 | 
					              className="w-100"
 | 
				
			||||||
 | 
					             
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </GlobalModel>
 | 
				
			||||||
 | 
					      )}
 | 
				
			||||||
 | 
					    </>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default ImagePreview;
 | 
				
			||||||
							
								
								
									
										56
									
								
								src/components/common/ImagePreviewstyle.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/components/common/ImagePreviewstyle.css
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,56 @@
 | 
				
			|||||||
 | 
					.img-container {
 | 
				
			||||||
 | 
					  width: 70px;          /* or whatever size you want */
 | 
				
			||||||
 | 
					  height: 30px;
 | 
				
			||||||
 | 
					  position: relative;    /* to contain the absolute overlay */
 | 
				
			||||||
 | 
					  overflow: hidden;
 | 
				
			||||||
 | 
					  cursor: pointer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.img-container img.img-thumbnail {
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  height: 100%;
 | 
				
			||||||
 | 
					  object-fit: cover;
 | 
				
			||||||
 | 
					  display: block;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.eye-overlay {
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					  top: 0;
 | 
				
			||||||
 | 
					  left: 0;
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  height: 100%;
 | 
				
			||||||
 | 
					  background-color: rgba(0,0,0,0.4);
 | 
				
			||||||
 | 
					  opacity: 0;
 | 
				
			||||||
 | 
					  transition: opacity 0.3s ease;
 | 
				
			||||||
 | 
					  pointer-events: none; 
 | 
				
			||||||
 | 
					  color: white;
 | 
				
			||||||
 | 
					  font-size: 1.5rem;
 | 
				
			||||||
 | 
					  user-select: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* center icon */
 | 
				
			||||||
 | 
					.eye-overlay i {
 | 
				
			||||||
 | 
					  pointer-events: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* fade in on hover */
 | 
				
			||||||
 | 
					.img-container:hover .eye-overlay {
 | 
				
			||||||
 | 
					  opacity: 1;
 | 
				
			||||||
 | 
					  pointer-events: auto; /* enable pointer events on hover */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.iconImage{
 | 
				
			||||||
 | 
					 font-size: 30px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.img-preview {
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  text-align: center;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.img-preview img {
 | 
				
			||||||
 | 
					  max-width: 100%;
 | 
				
			||||||
 | 
					  max-height: 80vh;
 | 
				
			||||||
 | 
					  object-fit: contain;
 | 
				
			||||||
 | 
					  display: block;
 | 
				
			||||||
 | 
					  margin: 0 auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -5,7 +5,7 @@ import AttendanceRepository from "../repositories/AttendanceRepository";
 | 
				
			|||||||
export const useAttendace =(projectId)=>{
 | 
					export const useAttendace =(projectId)=>{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const [attendance, setAttendance] = useState([]);
 | 
					  const [attendance, setAttendance] = useState([]);
 | 
				
			||||||
  const[loading,setLoading] = useState(false)
 | 
					  const[loading,setLoading] = useState(true)
 | 
				
			||||||
  const [error, setError] = useState(null); 
 | 
					  const [error, setError] = useState(null); 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   const fetchData =  () => {
 | 
					   const fetchData =  () => {
 | 
				
			||||||
@ -17,6 +17,7 @@ export const useAttendace =(projectId)=>{
 | 
				
			|||||||
           .then((response) => {
 | 
					           .then((response) => {
 | 
				
			||||||
             setAttendance(response.data);
 | 
					             setAttendance(response.data);
 | 
				
			||||||
             cacheData( "Attendance", {data: response.data, projectId} )
 | 
					             cacheData( "Attendance", {data: response.data, projectId} )
 | 
				
			||||||
 | 
					             setLoading(false)
 | 
				
			||||||
           })
 | 
					           })
 | 
				
			||||||
           .catch((error) => {
 | 
					           .catch((error) => {
 | 
				
			||||||
            setLoading(false)
 | 
					            setLoading(false)
 | 
				
			||||||
 | 
				
			|||||||
@ -143,7 +143,8 @@ export const useEmployeesAllOrByProjectId = (projectId, showInactive) => {
 | 
				
			|||||||
  const [error, setError] = useState(null);
 | 
					  const [error, setError] = useState(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const fetchData = async (showInactive) => {
 | 
					  const fetchData = async (showInactive) => {
 | 
				
			||||||
    if (projectId) {
 | 
					    if ( projectId )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
      const Employees_cache = getCachedData("employeeListByProject");
 | 
					      const Employees_cache = getCachedData("employeeListByProject");
 | 
				
			||||||
      if (!Employees_cache || Employees_cache.projectId !== projectId) {
 | 
					      if (!Employees_cache || Employees_cache.projectId !== projectId) {
 | 
				
			||||||
        setLoading(true);
 | 
					        setLoading(true);
 | 
				
			||||||
@ -166,18 +167,11 @@ export const useEmployeesAllOrByProjectId = (projectId, showInactive) => {
 | 
				
			|||||||
        setEmployees(Employees_cache.data);
 | 
					        setEmployees(Employees_cache.data);
 | 
				
			||||||
        setLoading(false);
 | 
					        setLoading(false);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    } else {
 | 
					    } else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
      const cacheKey = showInactive
 | 
					      const cacheKey = showInactive
 | 
				
			||||||
        ? "allInactiveEmployeeList"
 | 
					        ? "allInactiveEmployeeList"
 | 
				
			||||||
        : "allEmployeeList";
 | 
					        : "allEmployeeList";
 | 
				
			||||||
      const employeesCache = getCachedData(cacheKey);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (employeesCache) {
 | 
					 | 
				
			||||||
        setEmployees(employeesCache.data);
 | 
					 | 
				
			||||||
        setLoading(false);
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        setLoading(true);
 | 
					 | 
				
			||||||
        setError(null);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
          const response = await EmployeeRepository.getAllEmployeeList(
 | 
					          const response = await EmployeeRepository.getAllEmployeeList(
 | 
				
			||||||
@ -190,7 +184,7 @@ export const useEmployeesAllOrByProjectId = (projectId, showInactive) => {
 | 
				
			|||||||
          setError("Failed to fetch data.");
 | 
					          setError("Failed to fetch data.");
 | 
				
			||||||
          setLoading(false);
 | 
					          setLoading(false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -19,7 +19,7 @@ export const useProjects = () => {
 | 
				
			|||||||
    const filterProjects = (projectsList) => {
 | 
					    const filterProjects = (projectsList) => {
 | 
				
			||||||
      return projectsList
 | 
					      return projectsList
 | 
				
			||||||
        .filter((proj) => projectIds.includes(String(proj.id)))
 | 
					        .filter((proj) => projectIds.includes(String(proj.id)))
 | 
				
			||||||
        .sort((a, b) => a.name.localeCompare(b.name));
 | 
					        .sort((a, b) => a?.name?.localeCompare(b.name));
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const projects_cache = getCachedData("projectslist");
 | 
					    const projects_cache = getCachedData("projectslist");
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@ import AttendanceLog from "../../components/Activities/AttendcesLogs";
 | 
				
			|||||||
import Attendance from "../../components/Activities/Attendance";
 | 
					import Attendance from "../../components/Activities/Attendance";
 | 
				
			||||||
import AttendanceModel from "../../components/Activities/AttendanceModel";
 | 
					import AttendanceModel from "../../components/Activities/AttendanceModel";
 | 
				
			||||||
import showToast from "../../services/toastService";
 | 
					import showToast from "../../services/toastService";
 | 
				
			||||||
import { useProjects } from "../../hooks/useProjects";
 | 
					// import { useProjects } from "../../hooks/useProjects";
 | 
				
			||||||
import Regularization from "../../components/Activities/Regularization";
 | 
					import Regularization from "../../components/Activities/Regularization";
 | 
				
			||||||
import { useAttendace } from "../../hooks/useAttendance";
 | 
					import { useAttendace } from "../../hooks/useAttendance";
 | 
				
			||||||
import { useDispatch, useSelector } from "react-redux";
 | 
					import { useDispatch, useSelector } from "react-redux";
 | 
				
			||||||
@ -22,7 +22,7 @@ import eventBus from "../../services/eventBus";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const AttendancePage = () => {
 | 
					const AttendancePage = () => {
 | 
				
			||||||
  const [activeTab, setActiveTab] = useState("all");
 | 
					  const [activeTab, setActiveTab] = useState("all");
 | 
				
			||||||
  const [showOnlyCheckout, setShowOnlyCheckout] = useState(false);
 | 
					  const [ShowPending, setShowPending] = useState(false);
 | 
				
			||||||
  const loginUser = getCachedProfileData();
 | 
					  const loginUser = getCachedProfileData();
 | 
				
			||||||
  var selectedProject = useSelector((store) => store.localVariables.projectId);
 | 
					  var selectedProject = useSelector((store) => store.localVariables.projectId);
 | 
				
			||||||
  const { projects, loading: projectLoading } = useProjects();
 | 
					  const { projects, loading: projectLoading } = useProjects();
 | 
				
			||||||
@ -122,11 +122,11 @@ const AttendancePage = () => {
 | 
				
			|||||||
    setAttendances(attendance);
 | 
					    setAttendances(attendance);
 | 
				
			||||||
  }, [attendance]);
 | 
					  }, [attendance]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  useEffect(() => {
 | 
					  // useEffect(() => {
 | 
				
			||||||
    if (selectedProject === 1 || selectedProject === undefined) {
 | 
					  //   if (selectedProject === 1 || selectedProject === undefined) {
 | 
				
			||||||
      dispatch(setProjectId(loginUser?.projects[0]));
 | 
					  //     dispatch(setProjectId(loginUser?.projects[0]));
 | 
				
			||||||
    }
 | 
					  //   }
 | 
				
			||||||
  }, [selectedProject, loginUser?.projects]);
 | 
					  // }, [selectedProject, loginUser?.projects]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Filter attendance data based on the toggle
 | 
					  // Filter attendance data based on the toggle
 | 
				
			||||||
  // const filteredAttendance = showOnlyCheckout
 | 
					  // const filteredAttendance = showOnlyCheckout
 | 
				
			||||||
@ -134,8 +134,8 @@ const AttendancePage = () => {
 | 
				
			|||||||
  //     (att) => att?.checkOutTime !== null && att?.checkInTime !== null
 | 
					  //     (att) => att?.checkOutTime !== null && att?.checkInTime !== null
 | 
				
			||||||
  //   )
 | 
					  //   )
 | 
				
			||||||
  //   : attendances;
 | 
					  //   : attendances;
 | 
				
			||||||
  const filteredAttendance = showOnlyCheckout
 | 
					  const filteredAttendance = ShowPending
 | 
				
			||||||
    ? attendances?.filter((att) => att?.checkOutTime === null)
 | 
					    ? attendances?.filter((att) => att?.checkInTime !== null && att?.checkOutTime === null)
 | 
				
			||||||
    : attendances;
 | 
					    : attendances;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  useEffect(() => {
 | 
					  useEffect(() => {
 | 
				
			||||||
@ -242,21 +242,23 @@ const AttendancePage = () => {
 | 
				
			|||||||
            </li>
 | 
					            </li>
 | 
				
			||||||
          </ul>
 | 
					          </ul>
 | 
				
			||||||
          <div className="tab-content attedanceTabs py-0 px-1 px-sm-3">
 | 
					          <div className="tab-content attedanceTabs py-0 px-1 px-sm-3">
 | 
				
			||||||
            {projectLoading && <span>Loading..</span>}
 | 
					          
 | 
				
			||||||
            {!projectLoading && !attendances && <span>Not Found</span>}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            {activeTab === "all" && (
 | 
					            {activeTab === "all" && (
 | 
				
			||||||
              <>
 | 
					              <>
 | 
				
			||||||
                {!projectLoading && filteredAttendance?.length === 0 && (
 | 
					               
 | 
				
			||||||
                  <p>No Employee assigned yet.</p>
 | 
					 | 
				
			||||||
                )}
 | 
					 | 
				
			||||||
                <div className="tab-pane fade show active py-0">
 | 
					                <div className="tab-pane fade show active py-0">
 | 
				
			||||||
                  <Attendance
 | 
					                  <Attendance
 | 
				
			||||||
                    attendance={filteredAttendance}
 | 
					                    attendance={filteredAttendance}
 | 
				
			||||||
                    handleModalData={handleModalData}
 | 
					                    handleModalData={handleModalData}
 | 
				
			||||||
                    getRole={getRole}
 | 
					                    getRole={getRole}
 | 
				
			||||||
 | 
					                    setshowOnlyCheckout={setShowPending}
 | 
				
			||||||
 | 
					                    showOnlyCheckout={ShowPending}
 | 
				
			||||||
                  />
 | 
					                  />
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
 | 
					                 {!attLoading && filteredAttendance?.length === 0 && (
 | 
				
			||||||
 | 
					                  <p> {ShowPending ? "No Pending Available" : "No Employee assigned yet."} </p>
 | 
				
			||||||
 | 
					                )}
 | 
				
			||||||
              </>
 | 
					              </>
 | 
				
			||||||
            )}
 | 
					            )}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -265,7 +267,8 @@ const AttendancePage = () => {
 | 
				
			|||||||
                <AttendanceLog
 | 
					                <AttendanceLog
 | 
				
			||||||
                  handleModalData={handleModalData}
 | 
					                  handleModalData={handleModalData}
 | 
				
			||||||
                  projectId={selectedProject}
 | 
					                  projectId={selectedProject}
 | 
				
			||||||
                  showOnlyCheckout={showOnlyCheckout}
 | 
					                  setshowOnlyCheckout={setShowPending}
 | 
				
			||||||
 | 
					                  showOnlyCheckout={ShowPending}
 | 
				
			||||||
                />
 | 
					                />
 | 
				
			||||||
              </div>
 | 
					              </div>
 | 
				
			||||||
            )}
 | 
					            )}
 | 
				
			||||||
@ -275,6 +278,9 @@ const AttendancePage = () => {
 | 
				
			|||||||
                <Regularization handleRequest={handleSubmit} />
 | 
					                <Regularization handleRequest={handleSubmit} />
 | 
				
			||||||
              </div>
 | 
					              </div>
 | 
				
			||||||
            )}
 | 
					            )}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              {attLoading && <span>Loading..</span>}
 | 
				
			||||||
 | 
					            {!attLoading && !attendances && <span>Not Found</span>}
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
				
			|||||||
@ -10,6 +10,7 @@ import DateRangePicker from "../../components/common/DateRangePicker";
 | 
				
			|||||||
import { useSearchParams } from "react-router-dom";
 | 
					import { useSearchParams } from "react-router-dom";
 | 
				
			||||||
import moment from "moment";
 | 
					import moment from "moment";
 | 
				
			||||||
import FilterIcon from "../../components/common/FilterIcon"; // Import the FilterIcon component
 | 
					import FilterIcon from "../../components/common/FilterIcon"; // Import the FilterIcon component
 | 
				
			||||||
 | 
					import GlobalModel from "../../components/common/GlobalModel";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const DailyTask = () => {
 | 
					const DailyTask = () => {
 | 
				
			||||||
  const [searchParams] = useSearchParams();
 | 
					  const [searchParams] = useSearchParams();
 | 
				
			||||||
@ -170,19 +171,14 @@ const DailyTask = () => {
 | 
				
			|||||||
       
 | 
					       
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <div
 | 
					      {isModalOpenComment && (
 | 
				
			||||||
        className={`modal fade ${isModalOpenComment ? "show d-block" : ""}`}
 | 
					        <GlobalModel isOpen={isModalOpenComment} size="lg" closeModal={()=>setIsModalOpenComment(false)}>
 | 
				
			||||||
        tabIndex="-1"
 | 
					 | 
				
			||||||
        role="dialog"
 | 
					 | 
				
			||||||
        style={{ display: isModalOpenComment ? "block" : "none" }}
 | 
					 | 
				
			||||||
        aria-hidden={!isModalOpenComment}
 | 
					 | 
				
			||||||
      >
 | 
					 | 
				
			||||||
           <ReportTaskComments
 | 
					           <ReportTaskComments
 | 
				
			||||||
          commentsData={comments}
 | 
					          commentsData={comments}
 | 
				
			||||||
          closeModal={closeCommentModal}
 | 
					          closeModal={closeCommentModal}
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
   
 | 
					        </GlobalModel>
 | 
				
			||||||
      </div>
 | 
					      )}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <div className="container-xxl flex-grow-1 container-p-y">
 | 
					      <div className="container-xxl flex-grow-1 container-p-y">
 | 
				
			||||||
        <Breadcrumb
 | 
					        <Breadcrumb
 | 
				
			||||||
 | 
				
			|||||||
@ -181,7 +181,7 @@ const Directory = ({ IsPage = true, prefernceContacts }) => {
 | 
				
			|||||||
        (c.bucketIds || []).some((id) => selectedBucketIds.includes(id));
 | 
					        (c.bucketIds || []).some((id) => selectedBucketIds.includes(id));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return matchesSearch && matchesCategory && matchesBucket;
 | 
					      return matchesSearch && matchesCategory && matchesBucket;
 | 
				
			||||||
    }).sort((a, b) => a.name.localeCompare(b.name));
 | 
					    }).sort((a, b) => a?.name?.localeCompare(b.name));
 | 
				
			||||||
  }, [
 | 
					  }, [
 | 
				
			||||||
    ContactList,
 | 
					    ContactList,
 | 
				
			||||||
    searchText,
 | 
					    searchText,
 | 
				
			||||||
 | 
				
			|||||||
@ -42,7 +42,7 @@ const AttendancesEmployeeRecords = ({ employee }) => {
 | 
				
			|||||||
  const sortByName = (a, b) => {
 | 
					  const sortByName = (a, b) => {
 | 
				
			||||||
    const nameA = a.firstName.toLowerCase() + a.lastName.toLowerCase();
 | 
					    const nameA = a.firstName.toLowerCase() + a.lastName.toLowerCase();
 | 
				
			||||||
    const nameB = b.firstName.toLowerCase() + b.lastName.toLowerCase();
 | 
					    const nameB = b.firstName.toLowerCase() + b.lastName.toLowerCase();
 | 
				
			||||||
    return nameA.localeCompare(nameB);
 | 
					    return nameA?.localeCompare(nameB);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const group1 = data
 | 
					  const group1 = data
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@ 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 { ITEMS_PER_PAGE, MANAGE_EMPLOYEES } from "../../utils/constants";
 | 
				
			||||||
import { clearCacheKey } from "../../slices/apiDataManager";
 | 
					import { clearCacheKey } from "../../slices/apiDataManager";
 | 
				
			||||||
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
 | 
					import { useHasUserPermission } from "../../hooks/useHasUserPermission";
 | 
				
			||||||
import SuspendEmp from "../../components/Employee/SuspendEmp";
 | 
					import SuspendEmp from "../../components/Employee/SuspendEmp";
 | 
				
			||||||
@ -29,10 +29,9 @@ const EmployeeList = () => {
 | 
				
			|||||||
  const [selectedProject, setSelectedProject] = useState(() => selectedProjectId || "");
 | 
					  const [selectedProject, setSelectedProject] = useState(() => selectedProjectId || "");
 | 
				
			||||||
  const { projects, loading: projectLoading } = useProjects();
 | 
					  const { projects, loading: projectLoading } = useProjects();
 | 
				
			||||||
  const [showInactive, setShowInactive] = useState(false);
 | 
					  const [showInactive, setShowInactive] = useState(false);
 | 
				
			||||||
  const [showAllEmployees, setShowAllEmployees] = useState(false); // New state for "All Employee"
 | 
					  const [showAllEmployees, setShowAllEmployees] = useState(false); 
 | 
				
			||||||
  const Manage_Employee = useHasUserPermission(MANAGE_EMPLOYEES);
 | 
					  const Manage_Employee = useHasUserPermission(MANAGE_EMPLOYEES);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Modify the hook to conditionally pass selectedProject or null based on showAllEmployees
 | 
					 | 
				
			||||||
  const { employees, loading, setLoading, error, recallEmployeeData } =
 | 
					  const { employees, loading, setLoading, error, recallEmployeeData } =
 | 
				
			||||||
    useEmployeesAllOrByProjectId(showAllEmployees ? null : selectedProject, showInactive);
 | 
					    useEmployeesAllOrByProjectId(showAllEmployees ? null : selectedProject, showInactive);
 | 
				
			||||||
  const [projectsList, setProjectsList] = useState(projects || []);
 | 
					  const [projectsList, setProjectsList] = useState(projects || []);
 | 
				
			||||||
@ -40,7 +39,7 @@ const EmployeeList = () => {
 | 
				
			|||||||
  const [employeeList, setEmployeeList] = useState([]);
 | 
					  const [employeeList, setEmployeeList] = useState([]);
 | 
				
			||||||
  const [modelConfig, setModelConfig] = useState();
 | 
					  const [modelConfig, setModelConfig] = useState();
 | 
				
			||||||
  const [currentPage, setCurrentPage] = useState(1);
 | 
					  const [currentPage, setCurrentPage] = useState(1);
 | 
				
			||||||
  const [itemsPerPage] = useState(15);
 | 
					  const [itemsPerPage] = useState(ITEMS_PER_PAGE);
 | 
				
			||||||
  const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
 | 
					  const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
 | 
				
			||||||
  const [isEmployeeModalOpen, setIsEmployeeModalOpen] = useState(false);
 | 
					  const [isEmployeeModalOpen, setIsEmployeeModalOpen] = useState(false);
 | 
				
			||||||
  const [searchText, setSearchText] = useState("");
 | 
					  const [searchText, setSearchText] = useState("");
 | 
				
			||||||
@ -61,7 +60,16 @@ const EmployeeList = () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    const results = employeeList.filter((item) => {
 | 
					    const results = employeeList.filter((item) => {
 | 
				
			||||||
      const fullName = `${item.firstName} ${item.lastName}`.toLowerCase();
 | 
					      const fullName = `${item.firstName} ${item.lastName}`.toLowerCase();
 | 
				
			||||||
      return fullName.includes(value);
 | 
					      const email = item.email ? item.email.toLowerCase() : "";
 | 
				
			||||||
 | 
					      const phoneNumber = item.phoneNumber ? item.phoneNumber.toLowerCase() : "";
 | 
				
			||||||
 | 
					      const jobRole = item.jobRole ? item.jobRole.toLowerCase() : ""; // Get jobRole and convert to lowercase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return (
 | 
				
			||||||
 | 
					        fullName.includes(value) ||
 | 
				
			||||||
 | 
					        email.includes(value) ||
 | 
				
			||||||
 | 
					        phoneNumber.includes(value) ||
 | 
				
			||||||
 | 
					        jobRole.includes(value) // Include jobRole in the search
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    setFilteredData(results);
 | 
					    setFilteredData(results);
 | 
				
			||||||
@ -77,7 +85,7 @@ const EmployeeList = () => {
 | 
				
			|||||||
          }`.toLowerCase();
 | 
					          }`.toLowerCase();
 | 
				
			||||||
        const nameB = `${b.firstName || ""}${b.middleName || ""}${b.lastName || ""
 | 
					        const nameB = `${b.firstName || ""}${b.middleName || ""}${b.lastName || ""
 | 
				
			||||||
          }`.toLowerCase();
 | 
					          }`.toLowerCase();
 | 
				
			||||||
        return nameA.localeCompare(nameB);
 | 
					        return nameA?.localeCompare(nameB);
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      setEmployeeList(sorted);
 | 
					      setEmployeeList(sorted);
 | 
				
			||||||
@ -180,12 +188,11 @@ const EmployeeList = () => {
 | 
				
			|||||||
    recallEmployeeData(e.target.checked);
 | 
					    recallEmployeeData(e.target.checked);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // New handler for "All Employee" toggle
 | 
					 | 
				
			||||||
  const handleAllEmployeesToggle = (e) => {
 | 
					  const handleAllEmployeesToggle = (e) => {
 | 
				
			||||||
    const isChecked = e.target.checked;
 | 
					    const isChecked = e.target.checked;
 | 
				
			||||||
 | 
					    setShowInactive(false)
 | 
				
			||||||
    setShowAllEmployees( isChecked );
 | 
					    setShowAllEmployees( isChecked );
 | 
				
			||||||
    // If "All Employees" is checked, we don't want to filter by project,
 | 
					
 | 
				
			||||||
    // so we pass null for selected project. Otherwise, use the currently selected project.
 | 
					 | 
				
			||||||
    recallEmployeeData(showInactive, isChecked ? null : selectedProject);
 | 
					    recallEmployeeData(showInactive, isChecked ? null : selectedProject);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -203,7 +210,6 @@ const EmployeeList = () => {
 | 
				
			|||||||
  const handleProjectSelection = (e) => {
 | 
					  const handleProjectSelection = (e) => {
 | 
				
			||||||
    const newProjectId = e.target.value;
 | 
					    const newProjectId = e.target.value;
 | 
				
			||||||
    setSelectedProject(newProjectId);
 | 
					    setSelectedProject(newProjectId);
 | 
				
			||||||
    // If a specific project is selected, uncheck "All Employees"
 | 
					 | 
				
			||||||
    if (newProjectId) {
 | 
					    if (newProjectId) {
 | 
				
			||||||
      setShowAllEmployees(false);
 | 
					      setShowAllEmployees(false);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -279,28 +285,48 @@ const EmployeeList = () => {
 | 
				
			|||||||
                className="dataTables_wrapper dt-bootstrap5 no-footer"
 | 
					                className="dataTables_wrapper dt-bootstrap5 no-footer"
 | 
				
			||||||
                style={{ width: "98%" }}
 | 
					                style={{ width: "98%" }}
 | 
				
			||||||
              >
 | 
					              >
 | 
				
			||||||
                <div className="row  mb-2  ">
 | 
					                <div className="d-flex flex-wrap align-items-center justify-content-between gap-3 mb-3">
 | 
				
			||||||
                  <div className="col-md-3 col-sm-6 ">
 | 
					                  {/* Switches: All Employees + Inactive */}
 | 
				
			||||||
                    <div className="form-check text-start">
 | 
					                  <div className="d-flex flex-wrap align-items-center gap-3">
 | 
				
			||||||
 | 
					                    {/* All Employees Switch */}
 | 
				
			||||||
 | 
					                    <div className="form-check form-switch text-start">
 | 
				
			||||||
                      <input
 | 
					                      <input
 | 
				
			||||||
                        type="checkbox"
 | 
					                        type="checkbox"
 | 
				
			||||||
                        className="form-check-input"
 | 
					                        className="form-check-input"
 | 
				
			||||||
 | 
					                        role="switch"
 | 
				
			||||||
                        id="allEmployeesCheckbox"
 | 
					                        id="allEmployeesCheckbox"
 | 
				
			||||||
                        checked={showAllEmployees}
 | 
					                        checked={showAllEmployees}
 | 
				
			||||||
                        onChange={handleAllEmployeesToggle}
 | 
					                        onChange={handleAllEmployeesToggle}
 | 
				
			||||||
                      />
 | 
					                      />
 | 
				
			||||||
                      <label className="form-check-label" htmlFor="allEmployeesCheckbox">
 | 
					                      <label className="form-check-label ms-0" htmlFor="allEmployeesCheckbox">
 | 
				
			||||||
                        All Employees
 | 
					                        All Employees
 | 
				
			||||||
                      </label>
 | 
					                      </label>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    {/* Show Inactive Employees Switch */}
 | 
				
			||||||
 | 
					                    {showAllEmployees && (
 | 
				
			||||||
 | 
					                      <div className="form-check form-switch text-start">
 | 
				
			||||||
 | 
					                        <input
 | 
				
			||||||
 | 
					                          type="checkbox"
 | 
				
			||||||
 | 
					                          className="form-check-input"
 | 
				
			||||||
 | 
					                          role="switch"
 | 
				
			||||||
 | 
					                          id="inactiveEmployeesCheckbox"
 | 
				
			||||||
 | 
					                          checked={showInactive}
 | 
				
			||||||
 | 
					                          onChange={handleToggle}
 | 
				
			||||||
 | 
					                        />
 | 
				
			||||||
 | 
					                        <label className="form-check-label ms-0" htmlFor="inactiveEmployeesCheckbox">
 | 
				
			||||||
 | 
					                          Show Inactive Employees
 | 
				
			||||||
 | 
					                        </label>
 | 
				
			||||||
                      </div>
 | 
					                      </div>
 | 
				
			||||||
                  <div className="col-md-9 col-sm-6">
 | 
					                    )}
 | 
				
			||||||
                    <div className="dt-action-buttons text-xl-end text-lg-start text-md-end text-start d-flex align-items-center justify-content-sm-end justify-content-between gap-2 flex-md-row flex-sm-column mb-3 mb-md-0 mt-1 mt-md-0 gap-md-4">
 | 
					
 | 
				
			||||||
                      <div
 | 
					                  </div>
 | 
				
			||||||
                        id="DataTables_Table_0_filter"
 | 
					
 | 
				
			||||||
                        className="dataTables_filter"
 | 
					                  {/* Right side: Search + Export + Add Employee */}
 | 
				
			||||||
                      >
 | 
					                  <div className="d-flex flex-wrap align-items-center justify-content-end gap-3 flex-grow-1">
 | 
				
			||||||
                        <label>
 | 
					                    {/* Search */}
 | 
				
			||||||
 | 
					                    <div className="dataTables_filter">
 | 
				
			||||||
 | 
					                      <label className="mb-0">
 | 
				
			||||||
                        <input
 | 
					                        <input
 | 
				
			||||||
                          type="search"
 | 
					                          type="search"
 | 
				
			||||||
                          value={searchText}
 | 
					                          value={searchText}
 | 
				
			||||||
@ -308,15 +334,15 @@ const EmployeeList = () => {
 | 
				
			|||||||
                          className="form-control form-control-sm"
 | 
					                          className="form-control form-control-sm"
 | 
				
			||||||
                          placeholder="Search User"
 | 
					                          placeholder="Search User"
 | 
				
			||||||
                          aria-controls="DataTables_Table_0"
 | 
					                          aria-controls="DataTables_Table_0"
 | 
				
			||||||
                          ></input>
 | 
					                        />
 | 
				
			||||||
                      </label>
 | 
					                      </label>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                      <div className="dt-buttons btn-group flex-wrap">
 | 
					
 | 
				
			||||||
                        {" "}
 | 
					                    {/* Export Dropdown */}
 | 
				
			||||||
                        <div className=" d-flex justify-contend-end">
 | 
					                    <div className="dropdown">
 | 
				
			||||||
                      <button
 | 
					                      <button
 | 
				
			||||||
                        aria-label="Click me"
 | 
					                        aria-label="Click me"
 | 
				
			||||||
                            className="btn btn-sm  btn-label-secondary me-4  dropdown-toggle "
 | 
					                        className="btn btn-sm btn-label-secondary dropdown-toggle"
 | 
				
			||||||
                        type="button"
 | 
					                        type="button"
 | 
				
			||||||
                        data-bs-toggle="dropdown"
 | 
					                        data-bs-toggle="dropdown"
 | 
				
			||||||
                        aria-expanded="false"
 | 
					                        aria-expanded="false"
 | 
				
			||||||
@ -325,82 +351,43 @@ const EmployeeList = () => {
 | 
				
			|||||||
                      </button>
 | 
					                      </button>
 | 
				
			||||||
                      <ul className="dropdown-menu">
 | 
					                      <ul className="dropdown-menu">
 | 
				
			||||||
                        <li>
 | 
					                        <li>
 | 
				
			||||||
                              <a
 | 
					                          <a className="dropdown-item" href="#" onClick={() => handleExport("print")}>
 | 
				
			||||||
                                className="dropdown-item"
 | 
					 | 
				
			||||||
                                href="#"
 | 
					 | 
				
			||||||
                                onClick={() => handleExport("print")}
 | 
					 | 
				
			||||||
                              >
 | 
					 | 
				
			||||||
                            <i className="bx bx-printer me-1"></i> Print
 | 
					                            <i className="bx bx-printer me-1"></i> Print
 | 
				
			||||||
                          </a>
 | 
					                          </a>
 | 
				
			||||||
                        </li>
 | 
					                        </li>
 | 
				
			||||||
                        <li>
 | 
					                        <li>
 | 
				
			||||||
                              <a
 | 
					                          <a className="dropdown-item" href="#" onClick={() => handleExport("csv")}>
 | 
				
			||||||
                                className="dropdown-item"
 | 
					 | 
				
			||||||
                                href="#"
 | 
					 | 
				
			||||||
                                onClick={() => handleExport("csv")}
 | 
					 | 
				
			||||||
                              >
 | 
					 | 
				
			||||||
                            <i className="bx bx-file me-1"></i> CSV
 | 
					                            <i className="bx bx-file me-1"></i> CSV
 | 
				
			||||||
                          </a>
 | 
					                          </a>
 | 
				
			||||||
                        </li>
 | 
					                        </li>
 | 
				
			||||||
                        <li>
 | 
					                        <li>
 | 
				
			||||||
                              <a
 | 
					                          <a className="dropdown-item" href="#" onClick={() => handleExport("excel")}>
 | 
				
			||||||
                                className="dropdown-item"
 | 
					                            <i className="bx bxs-file-export me-1"></i> Excel
 | 
				
			||||||
                                href="#"
 | 
					 | 
				
			||||||
                                onClick={() => handleExport("excel")}
 | 
					 | 
				
			||||||
                              >
 | 
					 | 
				
			||||||
                                <i className="bx bxs-file-export me-1"></i>{" "}
 | 
					 | 
				
			||||||
                                Excel
 | 
					 | 
				
			||||||
                          </a>
 | 
					                          </a>
 | 
				
			||||||
                        </li>
 | 
					                        </li>
 | 
				
			||||||
                        <li>
 | 
					                        <li>
 | 
				
			||||||
                              <a
 | 
					                          <a className="dropdown-item" href="#" onClick={() => handleExport("pdf")}>
 | 
				
			||||||
                                className="dropdown-item"
 | 
					 | 
				
			||||||
                                href="#"
 | 
					 | 
				
			||||||
                                onClick={() => handleExport("pdf")}
 | 
					 | 
				
			||||||
                              >
 | 
					 | 
				
			||||||
                            <i className="bx bxs-file-pdf me-1"></i> PDF
 | 
					                            <i className="bx bxs-file-pdf me-1"></i> PDF
 | 
				
			||||||
                          </a>
 | 
					                          </a>
 | 
				
			||||||
                        </li>
 | 
					                        </li>
 | 
				
			||||||
                      </ul>
 | 
					                      </ul>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    {/* Add Employee */}
 | 
				
			||||||
 | 
					                    {Manage_Employee && (
 | 
				
			||||||
                      <button
 | 
					                      <button
 | 
				
			||||||
                            className={`btn btn-sm add-new btn-primary ${!Manage_Employee && "d-none"
 | 
					                        className="btn btn-sm btn-primary"
 | 
				
			||||||
                              }`}
 | 
					 | 
				
			||||||
                            tabIndex="0"
 | 
					 | 
				
			||||||
                        type="button"
 | 
					                        type="button"
 | 
				
			||||||
                            onClick={() => {
 | 
					                        onClick={() => handleEmployeeModel(null)}
 | 
				
			||||||
                              handleEmployeeModel(null);
 | 
					 | 
				
			||||||
                            }}
 | 
					 | 
				
			||||||
                      >
 | 
					                      >
 | 
				
			||||||
                            <span>
 | 
					 | 
				
			||||||
                        <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 Employee</span>
 | 
				
			||||||
                                Add New Employee
 | 
					                      </button>
 | 
				
			||||||
                              </span>
 | 
					                    )}
 | 
				
			||||||
                            </span>
 | 
					 | 
				
			||||||
                          </button>{" "}
 | 
					 | 
				
			||||||
                        </div>
 | 
					 | 
				
			||||||
                      </div>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                  </div>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
                <div className="d-flex justify-content-end mb-2">
 | 
					 | 
				
			||||||
                  {/* Show Inactive Employees Checkbox */}
 | 
					 | 
				
			||||||
                  <div className={`${showAllEmployees ? '' : selectedProject ? 'd-none' : ''}`}>
 | 
					 | 
				
			||||||
                    <div className="form-check">
 | 
					 | 
				
			||||||
                      <input
 | 
					 | 
				
			||||||
                        type="checkbox"
 | 
					 | 
				
			||||||
                        className="form-check-input"
 | 
					 | 
				
			||||||
                        id="inactiveEmployeesCheckbox"
 | 
					 | 
				
			||||||
                        checked={showInactive}
 | 
					 | 
				
			||||||
                        onChange={handleToggle}
 | 
					 | 
				
			||||||
                      />
 | 
					 | 
				
			||||||
                      <label className="form-check-label" htmlFor="inactiveEmployeesCheckbox">
 | 
					 | 
				
			||||||
                        Show Inactive Employees
 | 
					 | 
				
			||||||
                      </label>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                  </div>
 | 
					                  </div>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <table
 | 
					                <table
 | 
				
			||||||
                  className="datatables-users table border-top dataTable no-footer dtr-column text-nowrap"
 | 
					                  className="datatables-users table border-top dataTable no-footer dtr-column text-nowrap"
 | 
				
			||||||
                  id="DataTables_Table_0"
 | 
					                  id="DataTables_Table_0"
 | 
				
			||||||
@ -572,7 +559,7 @@ const EmployeeList = () => {
 | 
				
			|||||||
                          </td>
 | 
					                          </td>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                          <td className=" d-none  d-md-table-cell">
 | 
					                          <td className=" d-none  d-md-table-cell">
 | 
				
			||||||
                            {moment(item.joiningDate).format("DD-MMM-YYYY")}
 | 
					                            {moment(item.joiningDate)?.format("DD-MMM-YYYY")}
 | 
				
			||||||
                          </td>
 | 
					                          </td>
 | 
				
			||||||
                          <td>
 | 
					                          <td>
 | 
				
			||||||
                            {showInactive ? (
 | 
					                            {showInactive ? (
 | 
				
			||||||
 | 
				
			|||||||
@ -34,7 +34,7 @@ const MasterTable = ({ data, columns, loading, handleModalData }) => {
 | 
				
			|||||||
    if (!sortKey) return 0;
 | 
					    if (!sortKey) return 0;
 | 
				
			||||||
    const aValue = a[sortKey] || "";
 | 
					    const aValue = a[sortKey] || "";
 | 
				
			||||||
    const bValue = b[sortKey] || "";
 | 
					    const bValue = b[sortKey] || "";
 | 
				
			||||||
    return aValue.localeCompare(bValue);
 | 
					    return aValue?.localeCompare(bValue);
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Pagination logic
 | 
					  // Pagination logic
 | 
				
			||||||
 | 
				
			|||||||
@ -52,7 +52,7 @@ const ProjectList = () => {
 | 
				
			|||||||
        .filter((statusId) => grouped[statusId])
 | 
					        .filter((statusId) => grouped[statusId])
 | 
				
			||||||
        .flatMap((statusId) =>
 | 
					        .flatMap((statusId) =>
 | 
				
			||||||
          grouped[statusId].sort((a, b) =>
 | 
					          grouped[statusId].sort((a, b) =>
 | 
				
			||||||
            a.name.toLowerCase().localeCompare(b.name.toLowerCase())
 | 
					            a.name.toLowerCase()?.localeCompare(b.name.toLowerCase())
 | 
				
			||||||
          )
 | 
					          )
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
      setProjectList(sortedGrouped);
 | 
					      setProjectList(sortedGrouped);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user