breakhours-transform/public/index.html

332 lines
11 KiB
HTML
Raw Normal View History

2024-10-03 11:55:18 +00:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Break Hour Processing</title>
<script>
document.addEventListener('DOMContentLoaded', () => {
// const url = 'https://breakhours.fleks.c7a.nl'
const url = 'https://localhost:22000'
const shiftsUrl = `${url}/api/shifts`;
const timeTableUrl = `${url}/api/time-table`;
const postUrl = `${url}/api/shift-update`;
const putUrl = `${url}/api/shifts`;
document.getElementById('refresh-data').addEventListener('click', async () => {
const apiKey = document.getElementById('api-key').value;
const userName = document.getElementById('username').value;
const passWord = document.getElementById('password').value;
if (!userName || !passWord || !apiKey) {
alert('Please enter username, password and apiKey');
return;
}
try {
const shiftsData = await fetchData('POST', shiftsUrl, apiKey);
const timeTable = await fetchData('GET', timeTableUrl);
const resultContainer = document.getElementById('result');
resultContainer.innerHTML = '';
const summaryStats = { totalNeedsChange: 0, totalDoesNotNeedChange: 0, totalNoMatch: 0 };
const shiftsTable = createShiftsTable(shiftsData, timeTable, summaryStats);
const statsTable = createStatsTable(summaryStats, shiftsData.results.length);
resultContainer.appendChild(statsTable);
resultContainer.appendChild(shiftsTable);
const selectAllCheckbox = document.getElementById('select-all');
if (selectAllCheckbox) {
selectAllCheckbox.addEventListener('click', () => {
const checkboxes = document.querySelectorAll('.shift-row.needs-change input[type="checkbox"]');
checkboxes.forEach(checkbox => checkbox.checked = true);
});
}
} catch (error) {
console.error('Failed to fetch data:', error);
alert('Error fetching data. Check the console for more details.');
}
});
document.addEventListener('click', async (event) => {
if (event.target.classList.contains('post-button')) {
const row = event.target.closest('tr');
const shiftUuid = event.target.dataset.uuid;
const newBreakMinutes = parseInt(row.cells[7].textContent.split(' ')[0]); // Assuming new break hours are in the format "XX min"
const newBreakHours = minutesToHoursMinutes(newBreakMinutes); // Convert to h:mm format
const userName = document.getElementById('username').value;
const passWord = document.getElementById('password').value;
const apiKey = document.getElementById('api-key').value;
const limit = document.getElementById('limit').value || 0;
if (!userName || !passWord || !apiKey) {
alert('Please enter username, password and apiKey');
return;
}
const body = [
{ uuid: shiftUuid, break_hours: newBreakHours, userName, passWord, limit: null }
];
try {
await fetch(putUrl, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body)
});
alert(`Break hour update for ${shiftUuid} was successful.`);
} catch (error) {
alert(`Break hour update for ${shiftUuid} failed.`);
}
}
});
document.getElementById('queue-requests').addEventListener('click', async () => {
const userName = document.getElementById('username').value;
const passWord = document.getElementById('password').value;
const apiKey = document.getElementById('api-key').value;
const limit = 0 // document.getElementById('limit').value || 0;
if (!userName || !passWord || !apiKey) {
alert('Please enter username, password and apiKey');
return;
}
const config = { userName, passWord, apiKey, limit }
const selectedCheckboxes = document.querySelectorAll('.shift-row input[type="checkbox"]:checked');
const shifts = [];
selectedCheckboxes.forEach(checkbox => {
const row = checkbox.closest('tr');
const shiftUuid = checkbox.dataset.uuid;
const newBreakMinutes = parseInt(row.cells[7].textContent.split(' ')[0]);
const newBreakHours = minutesToHoursMinutes(newBreakMinutes);
shifts.push({ uuid: shiftUuid, break_hours: newBreakHours });
});
if (shifts.length === 0) {
alert('No shifts selected.');
return;
}
try {
await fetch(putUrl, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ config, shifts })
});
alert('Break hour updates were successful.');
} catch (error) {
alert('Break hour updates failed.');
}
});
});
function minutesToHoursMinutes(minutes) {
const hours = Math.floor(minutes / 60);
const mins = minutes % 60;
return `${hours}:${mins.toString().padStart(2, '0')}`;
}
async function fetchData(method, url, apiKey) {
const options = {
method: method || 'GET',
headers: { 'Content-Type': 'application/json' },
};
if (method === 'POST') {
options.body = JSON.stringify({ apiKey })
}
const response = await fetch(url, options);
if (!response.ok) throw new Error('Network response was not ok.');
return await response.json();
}
function createShiftsTable(shiftsData, timeTable, summaryStats) {
const sortedShifts = shiftsData.results.sort((a, b) => a.project_title.localeCompare(b.project_title));
const table = document.createElement('table');
table.innerHTML = `
<tr>
<th><input type="checkbox" id="select-all"></th>
<th>Shift UUID</th>
<th>Job ID</th>
<th>Project Title</th>
<th>Start Time</th>
<th>End Time</th>
<th>Old Break Hours (Decimal/Minutes)</th>
<th>New Break Hours</th>
<th>Post</th>
</tr>`;
sortedShifts.forEach(shift => {
const row = createShiftRow(shift, timeTable, summaryStats);
table.appendChild(row);
});
return table;
}
function createShiftRow(shift, timeTable, summaryStats) {
const startTime = shift.start_time.slice(0, 5);
const endTime = shift.end_time.slice(0, 5);
const matchedTime = timeTable.find(entry =>
entry.start_time.replace('.', ':') === startTime &&
entry.end_time.replace('.', ':') === endTime
);
const oldBreakDecimal = parseFloat(shift.break_compensation);
const oldBreakMinutes = Math.round(oldBreakDecimal * 60);
const newBreakMinutes = matchedTime ? Math.round(parseFloat(matchedTime.break_hours) * 60) : "N/A";
const statusColor = newBreakMinutes === "N/A" ? 'red' : (oldBreakMinutes === newBreakMinutes ? 'green' : 'orange');
const statusClass = newBreakMinutes === "N/A" ? 'no-match' : (oldBreakMinutes === newBreakMinutes ? 'no-change' : 'needs-change');
updateSummaryStats(newBreakMinutes, oldBreakMinutes, summaryStats);
const tr = document.createElement('tr');
tr.classList.add('shift-row', statusClass);
tr.innerHTML = `
<td><input type="checkbox" data-uuid="${shift.shifts_uuid}"></td>
<td>${shift.shifts_uuid}</td>
<td>${shift.job_id}</td>
<td>${shift.project_title}</td>
<td>${startTime}</td>
<td>${endTime}</td>
<td>${oldBreakDecimal.toFixed(2)} / ${oldBreakMinutes} min</td>
<td style="background-color: ${statusColor}">${newBreakMinutes} min</td>
<td><button class="post-button" data-uuid="${shift.shifts_uuid}">Post</button></td>
`;
return tr;
}
function updateSummaryStats(newBreakMinutes, oldBreakMinutes, summaryStats) {
if (newBreakMinutes === "N/A") summaryStats.totalNoMatch++;
else if (oldBreakMinutes === newBreakMinutes) summaryStats.totalDoesNotNeedChange++;
else summaryStats.totalNeedsChange++;
}
function createStatsTable(summaryStats, totalShifts) {
const table = document.createElement('table');
table.classList.add('stats-table');
table.innerHTML = `<tr><th>Type</th><th>Count</th><th>Show</th></tr>
<tr>
<td>Needs Change</td><td>${summaryStats.totalNeedsChange}</td>
<td><input type="checkbox" checked onclick="toggleVisibility('needs-change', this.checked)"></td>
</tr>
<tr>
<td>Does Not Need Change</td><td>${summaryStats.totalDoesNotNeedChange}</td>
<td><input type="checkbox" checked onclick="toggleVisibility('no-change', this.checked)"></td>
</tr>
<tr>
<td>No Match</td><td>${summaryStats.totalNoMatch}</td>
<td><input type="checkbox" checked onclick="toggleVisibility('no-match', this.checked)"></td>
</tr>
<tr><th>Total Shifts</th><th colspan="2">${totalShifts}</th></tr>`;
return table;
}
function toggleVisibility(className, isVisible) {
const rows = document.querySelectorAll(`.${className}`);
rows.forEach(row => {
row.style.display = isVisible ? '' : 'none';
});
}
</script>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
.container {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 20px;
}
.inputs-container {
display: flex;
align-items: center;
gap: 10px;
}
.inputs-container input {
flex: 1;
padding: 5px;
font-size: 1em;
}
.button-container {
display: flex;
align-items: center;
gap: 10px;
}
.button-container button {
padding: 5px 10px;
font-size: 1em;
width: 150px;
}
table,
th,
td {
border: 1px solid black;
border-collapse: collapse;
margin: 10px 0;
width: 100%;
table-layout: fixed;
}
th,
td {
padding: 10px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
td:nth-child(1),
th:nth-child(1) {
width: 11.11%;
}
.stats-table th:nth-child(1),
.stats-table td:nth-child(1) {
width: 50px;
text-align: center;
}
</style>
</head>
<body>
<div class="container">
<h1>Break Hour Processing</h1>
<div class="inputs-container">
<input type="text" id="username" placeholder="Enter your username" size="30">
<input type="password" id="password" placeholder="Enter your password" size="30">
<input type="text" id="api-key" placeholder="Enter your API key here" size="30">
</div>
<div class="button-container">
<button id="refresh-data">Refresh Data</button>
<button id="queue-requests">Queue Requests</button>
</div>
<div id="result"></div>
</div>
</body>
</html>