Add worker filter input to shift timetable and update rendering logic

This commit is contained in:
Ross
2025-08-12 11:20:51 +01:00
parent f31a54d512
commit 0599586f47
+82 -70
View File
@@ -494,75 +494,90 @@ function rgb2hex(rgb) {
return "#ffe066"; return "#ffe066";
} }
// Wrap timetable rendering in a function so we can call it for both views // Add a worker filter input to the shift timetable section
$("#shift-timetable-options").prepend(`
<div id="shift-timetable-worker-filter" style="margin-bottom:8px;">
<label for="worker-filter-input"><b>Filter workers:</b></label>
<input type="text" id="worker-filter-input" placeholder="Type to filter by name..." style="margin-left:4px; padding:2px 6px;"/>
</div>
`);
// Store the current filter value
let workerFilterValue = "";
// Update the filter value on input
$("#worker-filter-input").on("input", function() {
workerFilterValue = $(this).val().toLowerCase();
renderShiftTimetable();
});
// Patch renderShiftTimetable to filter workers in both linear and grid views
function renderShiftTimetable() { function renderShiftTimetable() {
$("#shift-timetable-div").empty(); $("#shift-timetable-div").empty();
if (selectedShifts.size === 0) return; if (selectedShifts.size === 0) return;
if (!gridViewEnabled) { // Helper: returns true if worker name matches filter
function workerMatchesFilter(workerName) {
// Original (list) view if (!workerFilterValue) return true;
let table = $("<table id='linear-shift-timetable'>"); return workerName.toLowerCase().includes(workerFilterValue);
// Add a header row with "Date", "Week", "Day", "Worker"
let headerRow = $("<tr>");
headerRow.append("<th>Date</th><th>Week</th><th>Day</th><th>Worker(s)</th>");
table.append(headerRow);
$("table#main-table th.date").each((n, th) => {
let date = th.dataset.date;
// Try to get week and day from the first matching td
let week = "";
let day = "";
let firstTd = $(`table#main-table td[data-date='${date}']`).first();
if (firstTd.length) {
week = firstTd.attr("data-week") || "";
day = firstTd.attr("data-day") || "";
}
let row = $("<tr>");
row.append(`<td>${date}</td>`);
row.append(`<td>${week}</td>`);
row.append(`<td>${day}</td>`);
// For each worker assigned to a selected shift on this date, add a cell
let workerCells = [];
$(`table#main-table td[data-date='${date}']`).filter(function () {
let shifts = $(this).attr("data-shift");
if (!shifts) return false;
let cell_shifts = shifts.split(",").map(s => s.trim());
// Show if any selected shift is present
return Array.from(selectedShifts).some(s => cell_shifts.includes(s));
}).each((n, td) => {
let workerTd = $(td).closest("tr").children("td:first");
let workerName = workerTd.find("span.name").text().trim();
// Find which selected shift(s) are present in this cell
let cell_shifts = $(td).attr("data-shift").split(",").map(s => s.trim());
let matchedShifts = Array.from(selectedShifts).filter(s => cell_shifts.includes(s));
let color = "#fff";
if (matchedShifts.length === 1) {
color = shiftColors[matchedShifts[0]];
} else if (matchedShifts.length > 1) {
// Use a 50/50 split background for two shifts
color = `linear-gradient(90deg, ${shiftColors[matchedShifts[0]]} 0 50%, ${shiftColors[matchedShifts[1]]} 50% 100%)`;
}
workerCells.push(`<td style="background:${color}">${workerName}</td>`);
});
// If no workers, add an empty cell
if (workerCells.length === 0) {
row.append("<td></td>");
} else {
// If multiple workers, join their names with commas
row.append(workerCells.join(""));
}
table.append(row);
});
$("#shift-timetable-div").append(table);
return;
} }
//// Get all weeks and days if (!gridViewEnabled) {
// Linear view
let table = $("<table id='linear-shift-timetable'>");
let headerRow = $("<tr>");
headerRow.append("<th>Date</th><th>Week</th><th>Day</th><th>Worker(s)</th>");
table.append(headerRow);
$("table#main-table th.date").each((n, th) => {
let date = th.dataset.date;
let week = "";
let day = "";
let firstTd = $(`table#main-table td[data-date='${date}']`).first();
if (firstTd.length) {
week = firstTd.attr("data-week") || "";
day = firstTd.attr("data-day") || "";
}
let row = $("<tr>");
row.append(`<td>${date}</td>`);
row.append(`<td>${week}</td>`);
row.append(`<td>${day}</td>`);
let workerCells = [];
$(`table#main-table td[data-date='${date}']`).filter(function () {
let shifts = $(this).attr("data-shift");
if (!shifts) return false;
let cell_shifts = shifts.split(",").map(s => s.trim());
return Array.from(selectedShifts).some(s => cell_shifts.includes(s));
}).each((n, td) => {
let workerTd = $(td).closest("tr").children("td:first");
let workerName = workerTd.find("span.name").text().trim();
if (!workerMatchesFilter(workerName)) return;
let cell_shifts = $(td).attr("data-shift").split(",").map(s => s.trim());
let matchedShifts = Array.from(selectedShifts).filter(s => cell_shifts.includes(s));
let color = "#fff";
if (matchedShifts.length === 1) {
color = shiftColors[matchedShifts[0]];
} else if (matchedShifts.length > 1) {
color = `linear-gradient(90deg, ${shiftColors[matchedShifts[0]]} 0 50%, ${shiftColors[matchedShifts[1]]} 50% 100%)`;
}
workerCells.push(`<td style="background:${color}">${workerName}</td>`);
});
if (workerCells.length === 0) {
row.append("<td></td>");
} else {
row.append(workerCells.join(""));
}
table.append(row);
});
$("#shift-timetable-div").append(table);
return;
}
// Grid view
let weeks = []; let weeks = [];
let daysOfWeek = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; let daysOfWeek = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
$("table#main-table td[data-week]").each(function () { $("table#main-table td[data-week]").each(function () {
@@ -571,20 +586,19 @@ function renderShiftTimetable() {
}); });
weeks = weeks.sort((a, b) => parseInt(a) - parseInt(b)); weeks = weeks.sort((a, b) => parseInt(a) - parseInt(b));
// Get all workers who have at least one selected shift
let workerIds = []; let workerIds = [];
let workerIdToName = {}; let workerIdToName = {};
$("table#main-table td.worker").each(function () { $("table#main-table td.worker").each(function () {
let workerId = $(this).attr("data-worker-id"); let workerId = $(this).attr("data-worker-id");
if (workerId && !workerIds.includes(workerId)) { if (workerId && !workerIds.includes(workerId)) {
workerIds.push(workerId);
let workerName = $(this).find("span.name").text().trim(); let workerName = $(this).find("span.name").text().trim();
workerIdToName[workerId] = workerName; if (workerMatchesFilter(workerName)) {
workerIds.push(workerId);
workerIdToName[workerId] = workerName;
}
} }
}); });
// workerId -> week -> day -> {shifts: [...], name: ...}
let cellMap = {}; let cellMap = {};
$("table#main-table td.worker").each(function () { $("table#main-table td.worker").each(function () {
let workerId = $(this).attr("data-worker-id"); let workerId = $(this).attr("data-worker-id");
@@ -634,8 +648,6 @@ function renderShiftTimetable() {
gridTable.append(row); gridTable.append(row);
}); });
$("#shift-timetable-div").append(gridTable); $("#shift-timetable-div").append(gridTable);
} }
// Patch the timetable button logic to use renderShiftTimetable // Patch the timetable button logic to use renderShiftTimetable