Compare commits
10 Commits
0b797a8c58
...
55fed17fe2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55fed17fe2 | ||
|
|
c3d3529d34 | ||
|
|
062f0d98d5 | ||
|
|
8e04dd2191 | ||
|
|
cb2950338c | ||
|
|
22be64d393 | ||
|
|
4e2c7e2adb | ||
|
|
6372362a33 | ||
|
|
ceba57884c | ||
|
|
58c3f22744 |
@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import Avatar from "../common/Avatar";
|
import Avatar from "../common/Avatar";
|
||||||
import { convertShortTime } from "../../utils/dateUtils";
|
import { convertShortTime } from "../../utils/dateUtils";
|
||||||
@ -7,17 +7,38 @@ import usePagination from "../../hooks/usePagination";
|
|||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
const Attendance = ({ attendance, getRole, handleModalData }) => {
|
const Attendance = ({ attendance, getRole, handleModalData }) => {
|
||||||
const { currentPage, totalPages, currentItems, paginate } = usePagination(
|
|
||||||
attendance,
|
|
||||||
5
|
|
||||||
);
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
// Ensure attendance is an array
|
||||||
|
const attendanceList = Array.isArray(attendance) ? attendance : [];
|
||||||
|
|
||||||
|
// Function to sort by first and last name
|
||||||
|
const sortByName = (a, b) => {
|
||||||
|
const nameA = (a.firstName + a.lastName).toLowerCase();
|
||||||
|
const nameB = (b.firstName + b.lastName).toLowerCase();
|
||||||
|
return nameA.localeCompare(nameB);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Filter employees based on activity
|
||||||
|
const group1 = attendanceList
|
||||||
|
.filter((d) => d.activity === 1 || d.activity === 4)
|
||||||
|
.sort(sortByName);
|
||||||
|
const group2 = attendanceList
|
||||||
|
.filter((d) => d.activity === 0)
|
||||||
|
.sort(sortByName);
|
||||||
|
|
||||||
|
const filteredData = [...group1, ...group2];
|
||||||
|
|
||||||
|
const { currentPage, totalPages, currentItems, paginate } = usePagination(
|
||||||
|
filteredData,
|
||||||
|
5
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="table-responsive text-nowrap">
|
<div className="table-responsive text-nowrap">
|
||||||
{attendance && attendance.length > 0 ? (
|
{attendance && attendance.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<table className="table ">
|
<table className="table ">
|
||||||
<thead>
|
<thead>
|
||||||
@ -96,6 +117,9 @@ const Attendance = ({ attendance, getRole, handleModalData }) => {
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
|
{!attendance && (
|
||||||
|
<span>No employees assigned to the project</span>
|
||||||
|
)}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@ -145,8 +169,6 @@ const Attendance = ({ attendance, getRole, handleModalData }) => {
|
|||||||
</nav>
|
</nav>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
) : (
|
|
||||||
<span>No employees assigned to the project</span>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -15,10 +15,44 @@ const AttendanceLog = ({ handleModalData, projectId }) => {
|
|||||||
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);
|
||||||
const [isRefreshing, setIsRefreshing] = useState(true);
|
const [ isRefreshing, setIsRefreshing ] = useState( true );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const today = new Date();
|
||||||
|
today.setHours(0, 0, 0, 0); // Strip time to compare dates only
|
||||||
|
|
||||||
|
const isSameDay = (dateStr) => {
|
||||||
|
if (!dateStr) return false;
|
||||||
|
const d = new Date(dateStr);
|
||||||
|
d.setHours(0, 0, 0, 0);
|
||||||
|
return d.getTime() === today.getTime();
|
||||||
|
};
|
||||||
|
|
||||||
|
const isBeforeToday = (dateStr) => {
|
||||||
|
if (!dateStr) return false;
|
||||||
|
const d = new Date(dateStr);
|
||||||
|
d.setHours(0, 0, 0, 0);
|
||||||
|
return d.getTime() < today.getTime();
|
||||||
|
};
|
||||||
|
|
||||||
|
const sortByName = (a, b) => {
|
||||||
|
const nameA = a.firstName.toLowerCase() + a.lastName.toLowerCase();
|
||||||
|
const nameB = b.firstName.toLowerCase() + b.lastName.toLowerCase();
|
||||||
|
return nameA.localeCompare(nameB);
|
||||||
|
};
|
||||||
|
|
||||||
|
const group1 = data.filter(d => d.activity === 1 && isSameDay(d.checkInTime)).sort(sortByName);
|
||||||
|
const group2 = data.filter(d => d.activity === 4 && isSameDay(d.checkOutTime)).sort(sortByName);
|
||||||
|
const group3 = data.filter(d => d.activity === 1 && isBeforeToday(d.checkInTime)).sort(sortByName);
|
||||||
|
const group4 = data.filter(d => d.activity === 4 && isBeforeToday(d.checkOutTime)).sort(sortByName);
|
||||||
|
const group5 = data.filter(d => d.activity === 5).sort(sortByName);
|
||||||
|
|
||||||
|
const sortedFinalList = [...group1, ...group2, ...group3, ...group4, ...group5];
|
||||||
|
|
||||||
const currentDate = new Date().toLocaleDateString( "en-CA" );
|
const currentDate = new Date().toLocaleDateString( "en-CA" );
|
||||||
const { currentPage, totalPages, currentItems, paginate } = usePagination(
|
const { currentPage, totalPages, currentItems, paginate } = usePagination(
|
||||||
data,
|
sortedFinalList,
|
||||||
5
|
5
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -34,7 +68,8 @@ const AttendanceLog = ({ handleModalData, projectId }) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [dateRange, projectId, isRefreshing]);
|
}, [dateRange, projectId, isRefreshing]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@ -16,11 +16,11 @@ const schema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const CheckCheckOutmodel = ({modeldata,closeModal,handleSubmitForm,}) => {
|
const CheckCheckOutmodel = ({modeldata,closeModal,handleSubmitForm,}) => {
|
||||||
|
|
||||||
const projectId = useSelector((store)=>store.localVariables.projectId)
|
const projectId = useSelector((store)=>store.localVariables.projectId)
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const coords = usePositionTracker();
|
const coords = usePositionTracker();
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
|
console.log(modeldata)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
@ -72,7 +72,9 @@ const CheckCheckOutmodel = ({modeldata,closeModal,handleSubmitForm,}) => {
|
|||||||
<TimePicker
|
<TimePicker
|
||||||
label="Choose a time"
|
label="Choose a time"
|
||||||
onChange={(e) => setValue("markTime", e)}
|
onChange={(e) => setValue("markTime", e)}
|
||||||
interval={10}
|
interval={10}
|
||||||
|
checkOutTime={modeldata?.checkOutTime}
|
||||||
|
checkInTime={modeldata?.checkInTime}
|
||||||
/>
|
/>
|
||||||
{errors. markTime && <p className="text-danger">{errors.markTime.message}</p>}
|
{errors. markTime && <p className="text-danger">{errors.markTime.message}</p>}
|
||||||
</div>
|
</div>
|
||||||
@ -124,7 +126,8 @@ const schemaReg = z.object({
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const Regularization = ({modeldata,closeModal,handleSubmitForm})=>{
|
export const Regularization = ( {modeldata, closeModal, handleSubmitForm} ) =>
|
||||||
|
{
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const coords = usePositionTracker();
|
const coords = usePositionTracker();
|
||||||
|
|
||||||
|
|||||||
@ -5,16 +5,31 @@ import RegularizationActions from "./RegularizationActions";
|
|||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { useRegularizationRequests } from "../../hooks/useAttendance";
|
import { useRegularizationRequests } from "../../hooks/useAttendance";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
|
import usePagination from "../../hooks/usePagination";
|
||||||
|
|
||||||
const Regularization = ({ handleRequest }) => {
|
const Regularization = ({ handleRequest }) => {
|
||||||
var selectedProject = useSelector((store) => store.localVariables.projectId);
|
var selectedProject = useSelector( ( store ) => store.localVariables.projectId );
|
||||||
|
|
||||||
const [regularizesList, setregularizedList] = useState([]);
|
const [regularizesList, setregularizedList] = useState([]);
|
||||||
const { regularizes, loading, error, refetch } =
|
const { regularizes, loading, error, refetch } =
|
||||||
useRegularizationRequests(selectedProject);
|
useRegularizationRequests(selectedProject);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setregularizedList(regularizes);
|
setregularizedList(regularizes);
|
||||||
}, [regularizes]);
|
}, [ regularizes ] );
|
||||||
|
|
||||||
|
const sortByName = (a, b) => {
|
||||||
|
const nameA = a.firstName.toLowerCase() + a.lastName.toLowerCase();
|
||||||
|
const nameB = b.firstName.toLowerCase() + b.lastName.toLowerCase();
|
||||||
|
return nameA.localeCompare(nameB);
|
||||||
|
};
|
||||||
|
|
||||||
|
const filteredData = regularizesList.sort(sortByName)
|
||||||
|
|
||||||
|
const { currentPage, totalPages, currentItems, paginate } = usePagination(
|
||||||
|
filteredData,
|
||||||
|
5
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="table-responsive text-nowrap">
|
<div className="table-responsive text-nowrap">
|
||||||
@ -79,6 +94,52 @@ const Regularization = ({ handleRequest }) => {
|
|||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
{!loading && (
|
||||||
|
<nav aria-label="Page ">
|
||||||
|
<ul className="pagination pagination-sm justify-content-end py-1">
|
||||||
|
<li
|
||||||
|
className={`page-item ${
|
||||||
|
currentPage === 1 ? "disabled" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
className="page-link btn-xs"
|
||||||
|
onClick={() => paginate(currentPage - 1)}
|
||||||
|
>
|
||||||
|
«
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
{[...Array(totalPages)].map((_, index) => (
|
||||||
|
<li
|
||||||
|
key={index}
|
||||||
|
className={`page-item ${
|
||||||
|
currentPage === index + 1 ? "active" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
className="page-link "
|
||||||
|
onClick={() => paginate(index + 1)}
|
||||||
|
>
|
||||||
|
{index + 1}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
<li
|
||||||
|
className={`page-item ${
|
||||||
|
currentPage === totalPages ? "disabled" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
className="page-link "
|
||||||
|
onClick={() => paginate(currentPage + 1)}
|
||||||
|
>
|
||||||
|
»
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,8 +4,7 @@ import useAttendanceStatus from "../../hooks/useAttendanceStatus";
|
|||||||
|
|
||||||
const RenderAttendanceStatus = ({ attendanceData, handleModalData,Tab,currentDate}) => {
|
const RenderAttendanceStatus = ({ attendanceData, handleModalData,Tab,currentDate}) => {
|
||||||
|
|
||||||
const { text, color, disabled, action,checkInTime } = useAttendanceStatus(attendanceData);
|
const {text, color, disabled, action, checkInTime} = useAttendanceStatus( attendanceData );
|
||||||
|
|
||||||
const handleButtonClick = (key) => {
|
const handleButtonClick = (key) => {
|
||||||
|
|
||||||
if(key === 6){
|
if(key === 6){
|
||||||
@ -17,7 +16,9 @@ const RenderAttendanceStatus = ({ attendanceData, handleModalData,Tab,currentDat
|
|||||||
action,
|
action,
|
||||||
employeeId: attendanceData?.employeeId,
|
employeeId: attendanceData?.employeeId,
|
||||||
id: attendanceData?.id,
|
id: attendanceData?.id,
|
||||||
currentDate
|
currentDate,
|
||||||
|
checkInTime: attendanceData.checkInTime,
|
||||||
|
checkOutTime:attendanceData.checkOutTime
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -40,7 +41,7 @@ const RenderAttendanceStatus = ({ attendanceData, handleModalData,Tab,currentDat
|
|||||||
{attendanceData?.checkInTime && (
|
{attendanceData?.checkInTime && (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-xs btn-success ms-2"
|
className="btn btn-xs btn-secondary ms-2"
|
||||||
tabIndex="0"
|
tabIndex="0"
|
||||||
aria-controls="DataTables_Table_0"
|
aria-controls="DataTables_Table_0"
|
||||||
data-bs-toggle="modal"
|
data-bs-toggle="modal"
|
||||||
|
|||||||
@ -70,7 +70,7 @@ const Header = () => {
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="navbar-nav-right d-flex align-items-center"
|
className="navbar-nav-right d-flex align-items-center justify-content-between"
|
||||||
id="navbar-collapse"
|
id="navbar-collapse"
|
||||||
>
|
>
|
||||||
{/* Search */}
|
{/* Search */}
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import { employee } from "../../data/masters";
|
|||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { getCachedData } from "../../slices/apiDataManager";
|
import { getCachedData } from "../../slices/apiDataManager";
|
||||||
import { useModal } from "../../ModalContext";
|
|
||||||
import { useProjects } from "../../hooks/useProjects";
|
import { useProjects } from "../../hooks/useProjects";
|
||||||
import { useEmployeesAllOrByProjectId } from "../../hooks/useEmployees";
|
import { useEmployeesAllOrByProjectId } from "../../hooks/useEmployees";
|
||||||
import { TasksRepository } from "../../repositories/ProjectRepository";
|
import { TasksRepository } from "../../repositories/ProjectRepository";
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { useModal } from "../../../ModalContext";
|
|
||||||
import AssignRoleModel from "../AssignRole";
|
import AssignRoleModel from "../AssignRole";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import GlobalModel from "../../common/GlobalModel";
|
import GlobalModel from "../../common/GlobalModel";
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import React, { useState, useRef, useEffect } from "react";
|
import React, {useState, useRef, useEffect} from "react";
|
||||||
|
import {THRESH_HOLD} from "../../utils/constants"
|
||||||
|
|
||||||
const TimePicker = ({ label, onChange, interval = 10, value }) => {
|
const TimePicker = ({ label, onChange, interval = 10, value,checkInTime, checkOutTime }) => {
|
||||||
const [time, setTime] = useState(value || "");
|
const [time, setTime] = useState(value || "");
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const dropdownRef = useRef(null);
|
const dropdownRef = useRef(null);
|
||||||
@ -9,7 +10,7 @@ const TimePicker = ({ label, onChange, interval = 10, value }) => {
|
|||||||
const getCurrentTime = () => {
|
const getCurrentTime = () => {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const minutes = now.getMinutes();
|
const minutes = now.getMinutes();
|
||||||
const roundedMinutes = Math.round(minutes / interval) * interval; // Round to nearest interval
|
const roundedMinutes = Math.round(minutes / interval) * interval;
|
||||||
now.setMinutes(roundedMinutes);
|
now.setMinutes(roundedMinutes);
|
||||||
now.setSeconds(0);
|
now.setSeconds(0);
|
||||||
now.setMilliseconds(0);
|
now.setMilliseconds(0);
|
||||||
@ -28,39 +29,66 @@ const TimePicker = ({ label, onChange, interval = 10, value }) => {
|
|||||||
|
|
||||||
return `${hoursFormatted}:${minutesFormatted} ${period}`;
|
return `${hoursFormatted}:${minutesFormatted} ${period}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateTimeSlots = () => {
|
const generateTimeSlots = () => {
|
||||||
const slots = [];
|
const slots = [];
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
now.setSeconds(0);
|
|
||||||
now.setMilliseconds(0);
|
|
||||||
|
|
||||||
// Round current time DOWN to nearest interval
|
|
||||||
const currentSlot = new Date();
|
const currentSlot = new Date();
|
||||||
currentSlot.setMinutes(
|
currentSlot.setMinutes(Math.floor(currentSlot.getMinutes() / interval) * interval);
|
||||||
Math.floor(currentSlot.getMinutes() / interval) * interval
|
|
||||||
);
|
|
||||||
currentSlot.setSeconds(0);
|
currentSlot.setSeconds(0);
|
||||||
currentSlot.setMilliseconds(0);
|
currentSlot.setMilliseconds(0);
|
||||||
|
|
||||||
let slot = new Date();
|
const checkInDate = checkInTime ? new Date(checkInTime) : null;
|
||||||
slot.setHours(0, 0, 0, 0); // Start from midnight
|
const checkOutDate = checkOutTime ? new Date(checkOutTime) : null;
|
||||||
|
|
||||||
for (let i = 0; i < 144; i++) {
|
const dayStart = new Date();
|
||||||
|
const dayEnd = new Date();
|
||||||
|
if (checkInDate) {
|
||||||
|
dayStart.setTime(checkInDate.getTime());
|
||||||
|
dayEnd.setTime(checkInDate.getTime());
|
||||||
|
}
|
||||||
|
dayStart.setHours(0, 0, 0, 0);
|
||||||
|
dayEnd.setHours(23, 59, 59, 999);
|
||||||
|
|
||||||
|
let minSelectable = null;
|
||||||
|
let maxSelectable = null;
|
||||||
|
|
||||||
|
if (!checkInDate) {
|
||||||
|
// Case 1: No check-in time (new check-in)
|
||||||
|
minSelectable = new Date(dayStart);
|
||||||
|
maxSelectable = new Date(currentSlot);
|
||||||
|
} else if (checkInDate && !checkOutDate) {
|
||||||
|
const hoursDiff = (now - checkInDate) / (1000 * 60 * 60);
|
||||||
|
if (hoursDiff < THRESH_HOLD) {
|
||||||
|
// Case 2: Check-in present, no checkout, within THRESH_HOLD hours
|
||||||
|
minSelectable = new Date(checkInDate);
|
||||||
|
maxSelectable = new Date(currentSlot);
|
||||||
|
} else {
|
||||||
|
// Case 4: Check-in present, no checkout, more than THRESH_HOLD hours
|
||||||
|
minSelectable = new Date(checkInDate);
|
||||||
|
maxSelectable = new Date(dayEnd);
|
||||||
|
}
|
||||||
|
} else if (checkInDate && checkOutDate) {
|
||||||
|
// Case 3: Both check-in and checkout present
|
||||||
|
const isSameDay = new Date(checkOutDate).toDateString() === new Date().toDateString();
|
||||||
|
minSelectable = new Date(checkOutDate);
|
||||||
|
maxSelectable = isSameDay ? new Date(dayEnd) : new Date(currentSlot);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const slot = new Date(dayStart.getTime());
|
||||||
|
while (slot <= dayEnd) {
|
||||||
const formatted = formatTime(slot);
|
const formatted = formatTime(slot);
|
||||||
const diffInMinutes = (currentSlot - slot) / 60000;
|
const isSelectable = slot >= minSelectable && slot <= maxSelectable;
|
||||||
const isSelectable = diffInMinutes >= 0 && diffInMinutes <= interval * 5;
|
slots.push({ time: formatted, isSelectable });
|
||||||
|
|
||||||
slots.push({
|
|
||||||
time: formatted,
|
|
||||||
isSelectable,
|
|
||||||
});
|
|
||||||
|
|
||||||
slot.setMinutes(slot.getMinutes() + interval);
|
slot.setMinutes(slot.getMinutes() + interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
return slots;
|
return slots;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleSelect = (selectedTime) => {
|
const handleSelect = (selectedTime) => {
|
||||||
setTime(selectedTime);
|
setTime(selectedTime);
|
||||||
@ -68,7 +96,6 @@ const TimePicker = ({ label, onChange, interval = 10, value }) => {
|
|||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle click outside the dropdown to close it
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleClickOutside = (event) => {
|
const handleClickOutside = (event) => {
|
||||||
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
||||||
@ -79,7 +106,6 @@ const TimePicker = ({ label, onChange, interval = 10, value }) => {
|
|||||||
return () => document.removeEventListener("mousedown", handleClickOutside);
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// If there's no value, set the default time
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
const defaultTime = formatTime(getCurrentTime());
|
const defaultTime = formatTime(getCurrentTime());
|
||||||
@ -88,7 +114,6 @@ const TimePicker = ({ label, onChange, interval = 10, value }) => {
|
|||||||
}
|
}
|
||||||
}, [value, interval, onChange]);
|
}, [value, interval, onChange]);
|
||||||
|
|
||||||
// Scroll to the selected slot when it's open
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpen && time && slotRefs.current[time]) {
|
if (isOpen && time && slotRefs.current[time]) {
|
||||||
const selectedSlot = slotRefs.current[time];
|
const selectedSlot = slotRefs.current[time];
|
||||||
@ -97,7 +122,11 @@ const TimePicker = ({ label, onChange, interval = 10, value }) => {
|
|||||||
block: "center",
|
block: "center",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [isOpen, time]);
|
}, [ isOpen, time ] );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="position-relative w-100" ref={dropdownRef}>
|
<div className="position-relative w-100" ref={dropdownRef}>
|
||||||
@ -159,4 +188,4 @@ const TimePicker = ({ label, onChange, interval = 10, value }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TimePicker;
|
export default TimePicker;
|
||||||
@ -74,15 +74,31 @@ const useAttendanceStatus = (attendanceData) => {
|
|||||||
text: "Regularize",
|
text: "Regularize",
|
||||||
color: 'btn-warning',
|
color: 'btn-warning',
|
||||||
});
|
});
|
||||||
}else if(activity === 4 && checkInTime !== null && checkOutTime !== null && !timeElapsed(checkInTime,THRESH_HOLD) ){
|
} else if ( activity === 4 && checkInTime !== null && checkOutTime !== null && !timeElapsed( checkInTime, THRESH_HOLD ) )
|
||||||
setStatus({
|
{
|
||||||
status: "Check-In",
|
|
||||||
action: ACTIONS.CHECK_IN,
|
if ( activity === 4 && checkInTime !== null && checkOutTime !== null && new Date(checkOutTime).toDateString() !== new Date().toDateString())
|
||||||
disabled: false,
|
{
|
||||||
text: "Check In",
|
setStatus( {
|
||||||
color: 'btn-primary',
|
status: "Approved",
|
||||||
})
|
action: ACTIONS.APPROVED,
|
||||||
}else if(activity === 2 && checkInTime !== null ){
|
disabled: true,
|
||||||
|
text: "Approved",
|
||||||
|
color: 'btn-success',
|
||||||
|
} );
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
setStatus( {
|
||||||
|
status: "Check-In",
|
||||||
|
action: ACTIONS.CHECK_IN,
|
||||||
|
disabled: false,
|
||||||
|
text: "Check In",
|
||||||
|
color: 'btn-primary',
|
||||||
|
} )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( activity === 2 && checkInTime !== null )
|
||||||
|
{
|
||||||
setStatus({
|
setStatus({
|
||||||
status: "Requested",
|
status: "Requested",
|
||||||
action: ACTIONS.REQUESTED,
|
action: ACTIONS.REQUESTED,
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
export const THRESH_HOLD = 12; // hours
|
export const THRESH_HOLD = 48; // hours
|
||||||
export const DURATION_TIME = 10; // minutes
|
export const DURATION_TIME = 10; // minutes
|
||||||
|
|
||||||
export const MANAGE_MASTER = "588a8824-f924-4955-82d8-fc51956cf323";
|
export const MANAGE_MASTER = "588a8824-f924-4955-82d8-fc51956cf323";
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user