Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save fMoro1999/2f664abb6a7cc96f69f4e663ce249f6d to your computer and use it in GitHub Desktop.
Save fMoro1999/2f664abb6a7cc96f69f4e663ce249f6d to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Work Clock-Out Calculator
// @namespace http://tampermonkey.net/
// @version 0.9
// @description Calculate when to clock out based on clock-in times and lunch break requirements
// @author You
// @match https://abacus.casale.ch/portal/myabacus/proj_inandout
// @grant GM_addStyle
// @run-at document-end
// ==/UserScript==
(function() {
'use strict';
// Add CSS for better UI
GM_addStyle(`
#clock-calculator {
position: fixed;
bottom: 20px;
right: 20px;
background-color: #f8f9fa;
padding: 15px;
border-radius: 8px;
box-shadow: 0 3px 10px rgba(0,0,0,0.2);
z-index: 9999;
width: 320px;
font-family: Arial, sans-serif;
}
#clock-calculator h3 {
margin-top: 0;
margin-bottom: 10px;
color: #333;
}
#clock-info {
margin-bottom: 15px;
font-size: 14px;
}
#clock-out-time {
font-weight: bold;
margin-bottom: 10px;
font-size: 16px;
}
#time-remaining {
color: #0066cc;
margin-bottom: 15px;
font-size: 15px;
}
.calculator-btn {
background-color: #4CAF50;
color: white;
border: none;
padding: 8px 12px;
border-radius: 4px;
cursor: pointer;
margin-right: 5px;
}
#close-calculator {
background-color: #f44336;
}
.warning {
color: #e65100;
}
`);
// Create the UI for the calculator
function createUI() {
// Check if the calculator already exists
if (document.getElementById('clock-calculator')) {
return; // Do not create multiple instances
}
const container = document.createElement('div');
container.id = 'clock-calculator';
container.innerHTML = `
<h3>Clock-Out Calculator</h3>
<div id="clock-info">Loading clock data...</div>
<div id="clock-out-time"></div>
<div id="time-remaining"></div>
<button id="refresh-clock-data" class="calculator-btn">Refresh Data</button>
<button id="close-calculator" class="calculator-btn">Close</button>
<div style="margin-top: 10px">
<button id="toggle-calculator" class="calculator-btn" style="background-color: #ff9800;">Toggle Calculator</button>
</div>
`;
document.body.appendChild(container);
// Add event listeners to buttons
document.getElementById('refresh-clock-data').addEventListener('click', calculateClockOutTime);
document.getElementById('close-calculator').addEventListener('click', function() {
document.getElementById('clock-calculator').style.display = 'none';
});
document.getElementById('toggle-calculator').addEventListener('click', function() {
const infoEl = document.getElementById('clock-info');
const clockOutEl = document.getElementById('clock-out-time');
const timeRemainingEl = document.getElementById('time-remaining');
if (infoEl.style.display === 'none') {
infoEl.style.display = 'block';
clockOutEl.style.display = 'block';
timeRemainingEl.style.display = 'block';
this.textContent = 'Hide Details';
} else {
infoEl.style.display = 'none';
clockOutEl.style.display = 'none';
timeRemainingEl.style.display = 'none';
this.textContent = 'Show Details';
}
});
// Initial calculation
calculateClockOutTime();
// Set up auto-refresh timer (every minute)
setInterval(calculateClockOutTime, 60000);
}
// Parse time string in 24h format to Date object
function parseTime(timeStr) {
if (!timeStr) return null;
const now = new Date();
const [hours, minutes] = timeStr.trim().split(':').map(Number);
const timeDate = new Date(now);
timeDate.setHours(hours, minutes, 0, 0);
return timeDate;
}
// Format Date object to HH:MM string
function formatTime(date) {
if (!date) return 'N/A';
return date.toTimeString().substring(0, 5);
}
// Calculate time difference in minutes
function getMinutesDifference(startTime, endTime) {
if (!startTime || !endTime) return 0;
return Math.round((endTime - startTime) / (1000 * 60));
}
// Main function to calculate clock out time
function calculateClockOutTime() {
// Get clock times from the page - USING THE EXACT IDs PROVIDED
const firstClockInEl = document.getElementById('id_history_from_1');
const secondClockInEl = document.getElementById('id_history_to_1');
const thirdClockInEl = document.getElementById('id_history_from_2');
// Get the values from the elements
let firstClockIn = firstClockInEl && firstClockInEl.value ? firstClockInEl.value : null;
let secondClockIn = secondClockInEl && secondClockInEl.value ? secondClockInEl.value : null;
let thirdClockIn = thirdClockInEl && thirdClockInEl.value ? thirdClockInEl.value : null;
// Get the clock info element
const clockInfoEl = document.getElementById('clock-info');
const clockOutTimeEl = document.getElementById('clock-out-time');
const timeRemainingEl = document.getElementById('time-remaining');
// If elements don't exist in DOM, show error
if (!clockInfoEl || !clockOutTimeEl || !timeRemainingEl) {
console.error('Clock calculator elements not found in DOM');
return;
}
// If we don't have first clock in time, show error message
if (!firstClockIn) {
clockInfoEl.innerHTML = 'No clock-in times found on this page. Make sure you are on the correct timesheet page.';
clockOutTimeEl.innerHTML = '';
timeRemainingEl.innerHTML = '';
return;
}
// Parse time strings to Date objects
const firstClockInTime = parseTime(firstClockIn);
const secondClockInTime = parseTime(secondClockIn);
const thirdClockInTime = parseTime(thirdClockIn);
const currentTime = new Date();
let clockOutTime;
let totalWorkMinutes = 480; // Default to 8 hours (480 minutes)
let lunchBreakMinutes = 0;
let minimumLunchBreak = 45; // default to 45 minutes
let infoText = '';
// If planning to work 9+ hours, minimum lunch break is 60 minutes
if (totalWorkMinutes >= 540) {
minimumLunchBreak = 60;
}
// Display the clock in times
infoText += `First Clock In: ${formatTime(firstClockInTime)}<br>`;
// Calculate based on available clock times
if (firstClockInTime && secondClockInTime && thirdClockInTime) {
// We have all three clock times, so lunch break is from second to third
infoText += `Second Clock In (Lunch Start): ${formatTime(secondClockInTime)}<br>`;
infoText += `Third Clock In (Lunch End): ${formatTime(thirdClockInTime)}<br>`;
// Calculate actual lunch break taken
lunchBreakMinutes = getMinutesDifference(secondClockInTime, thirdClockInTime);
infoText += `Actual Lunch Break: ${lunchBreakMinutes} min<br>`;
infoText += `Required Lunch Break: ${minimumLunchBreak} min<br>`;
// Calculate total work minutes before lunch
const morningWorkMinutes = getMinutesDifference(firstClockInTime, secondClockInTime);
// Calculate clock-out time
clockOutTime = new Date(thirdClockInTime);
clockOutTime.setMinutes(clockOutTime.getMinutes() + (totalWorkMinutes - morningWorkMinutes));
// If the actual lunch break was shorter than required, adjust clock-out time
if (lunchBreakMinutes < minimumLunchBreak) {
const additionalMinutes = minimumLunchBreak - lunchBreakMinutes;
clockOutTime.setMinutes(clockOutTime.getMinutes() + additionalMinutes);
infoText += `<span class="warning">Short lunch! Adding ${additionalMinutes} min to total time.</span><br>`;
}
} else if (firstClockInTime && secondClockInTime) {
// We have first and second clock times, assume second is lunch start and user hasn't returned yet
infoText += `Second Clock In (Lunch Start): ${formatTime(secondClockInTime)}<br>`;
infoText += `Third Clock In (Lunch End): Not yet clocked<br>`;
// Calculate work minutes before lunch
const morningWorkMinutes = getMinutesDifference(firstClockInTime, secondClockInTime);
infoText += `Required Lunch Break: ${minimumLunchBreak} min<br>`;
// Calculate potential clock-out time if user returned from lunch now
const potentialReturnTime = new Date();
lunchBreakMinutes = getMinutesDifference(secondClockInTime, potentialReturnTime);
// Calculate clock-out time assuming user returns now
clockOutTime = new Date(potentialReturnTime);
clockOutTime.setMinutes(clockOutTime.getMinutes() + (totalWorkMinutes - morningWorkMinutes));
// If current lunch break is shorter than required, adjust clock-out time
if (lunchBreakMinutes < minimumLunchBreak) {
const additionalMinutes = minimumLunchBreak - lunchBreakMinutes;
clockOutTime.setMinutes(clockOutTime.getMinutes() + additionalMinutes);
infoText += `<span class="warning">If you clock in now, lunch break (${lunchBreakMinutes} min) is shorter than required.</span><br>`;
}
infoText += `Current Lunch Duration: ${lunchBreakMinutes} min<br>`;
} else if (firstClockInTime) {
// We only have first clock in, no lunch break yet
infoText += `Second Clock In (Lunch Start): Not yet clocked<br>`;
infoText += `Third Clock In (Lunch End): Not yet clocked<br>`;
infoText += `Required Lunch Break: ${minimumLunchBreak} min<br>`;
// Calculate earliest possible clock-out time (assuming minimum lunch break)
clockOutTime = new Date(firstClockInTime);
clockOutTime.setMinutes(clockOutTime.getMinutes() + totalWorkMinutes + minimumLunchBreak);
}
// Display clock-out time
clockInfoEl.innerHTML = infoText;
clockOutTimeEl.innerHTML = `Recommended Clock Out: <span style="font-size: 18px; color: #2E7D32;">${formatTime(clockOutTime)}</span>`;
// Calculate and display time remaining
const minutesRemaining = getMinutesDifference(currentTime, clockOutTime);
if (minutesRemaining > 0) {
const hoursRemaining = Math.floor(minutesRemaining / 60);
const minsRemaining = minutesRemaining % 60;
let timeRemainingText = 'Time remaining: ';
if (hoursRemaining > 0) {
timeRemainingText += `${hoursRemaining} hr `;
}
if (minsRemaining > 0 || hoursRemaining === 0) {
timeRemainingText += `${minsRemaining} min`;
}
timeRemainingEl.innerHTML = timeRemainingText;
} else {
timeRemainingEl.innerHTML = '<span style="color: #2E7D32; font-weight: bold;">You can clock out now!</span>';
}
}
// Create a floating button to toggle the calculator
function createToggleButton() {
const button = document.createElement('button');
button.id = 'show-clock-calculator';
button.textContent = 'Calculate Clock-Out';
button.style.cssText = 'position: fixed; bottom: 10px; right: 10px; background-color: #4CAF50; color: white; border: none; padding: 10px; border-radius: 5px; cursor: pointer; z-index: 9998;';
document.body.appendChild(button);
button.addEventListener('click', function() {
// Check if calculator exists
let calculator = document.getElementById('clock-calculator');
if (calculator) {
// Toggle visibility
calculator.style.display = calculator.style.display === 'none' ? 'block' : 'none';
} else {
// Create the calculator
createUI();
}
// Hide the toggle button
this.style.display = 'none';
});
}
// Initialize after a slight delay to ensure page loads
setTimeout(function() {
createToggleButton();
}, 1500);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment