diff --git a/footer.php b/footer.php index 655a6742..0c4364cf 100644 --- a/footer.php +++ b/footer.php @@ -15,6 +15,7 @@ + @@ -26,6 +27,7 @@ + diff --git a/js/header_timers.js b/js/header_timers.js new file mode 100644 index 00000000..b7059480 --- /dev/null +++ b/js/header_timers.js @@ -0,0 +1,147 @@ +// ticketCounter.js +(function() { + function getRunningTicketCount() { + let count = 0; + for (let i = 0; i < localStorage.length; i++) { + let key = localStorage.key(i); + if (key.includes("ticket-timer-running")) { + let isRunning = JSON.parse(localStorage.getItem(key)); + if (isRunning) { + count++; + } + } + } + return count; + } + + function updateTicketCountDisplay() { + let count = getRunningTicketCount(); + let countDisplay = document.getElementById("runningTicketsCount"); + if (countDisplay) { + countDisplay.innerText = count; + } + if (count == 0) { + countDisplay.classList.remove('badge-danger'); + } else { + //check to see if more than one ticket + if (count > 1) { + countDisplay.classList.add('badge-danger'); + } + //if count is one, check to see if its open in the current window by looking at the post variable ticket_id in url + if (count == 1) { + let urlParams = new URLSearchParams(window.location.search); + let ticketID = urlParams.get('ticket_id'); + console.log(ticketID); + // If ticket number equals one in local storage, then add badge-danger class + if (localStorage.getItem("ticket-timer-running-") == ticketID) { + countDisplay.classList.add('badge-danger'); + } else { + countDisplay.classList.remove('badge-danger'); + } + } + } + } + + function getElapsedSeconds(ticketID) { + let storedStartTime = parseInt(localStorage.getItem(ticketID + "-startTime") || "0"); + let pausedTime = parseInt(localStorage.getItem(ticketID + "-pausedTime") || "0"); + if (!storedStartTime) return pausedTime; + let timeSinceStart = Math.floor((Date.now() - storedStartTime) / 1000); + return pausedTime + timeSinceStart; + } + + function formatTime(seconds) { + let hours = Math.floor(seconds / 3600); + let minutes = Math.floor((seconds % 3600) / 60); + let secs = seconds % 60; + return `${hours}h ${minutes}m ${secs}s`; + } + + function loadOpenTickets() { + let openTicketsContainer = document.getElementById('openTicketsContainer'); + openTicketsContainer.innerHTML = ''; // Clear existing content + + for (let i = 0; i < localStorage.length; i++) { + let key = localStorage.key(i); + + if (key.startsWith("ticket-timer-running-")) { + let ticketID = key.replace("ticket-timer-running-", ""); + let isRunning = JSON.parse(localStorage.getItem(key)); + + let ticketDiv = document.createElement('div'); + ticketDiv.classList.add('card', 'card-outline', 'mb-3'); + // Add class based on ticket status + ticketDiv.classList.add(isRunning ? 'card-info' : 'card-warning'); + ticketDiv.id = 'ticket-' + ticketID; + + let elapsedSecs = getElapsedSeconds(ticketID); + let timeString = formatTime(elapsedSecs); + + ticketDiv.innerHTML = ` +
+

Ticket ID: ${ticketID}

+ View Ticket +
+
+

Total Time: ${timeString}

+
+ `; + + openTicketsContainer.appendChild(ticketDiv); + } + } + + requestAnimationFrame(() => updateRunningTickets()); + } + + function updateRunningTickets() { + let runningTickets = document.querySelectorAll('[id^="ticket-"]'); + runningTickets.forEach(ticket => { + let ticketID = ticket.id.replace("ticket-", ""); + let isRunning = JSON.parse(localStorage.getItem("ticket-timer-running-" + ticketID)); + + if (isRunning) { + let updatedTime = formatTime(getElapsedSeconds(ticketID)); + document.getElementById('time-' + ticketID).innerText = 'Total Time: ' + updatedTime; + } + }); + + requestAnimationFrame(updateRunningTickets); + } + + function clearAllTimers() { + // Collect keys to be removed + let keysToRemove = []; + for (let i = 0; i < localStorage.length; i++) { + let key = localStorage.key(i); + if (key.startsWith("ticket-timer-running-") || key.endsWith("-startTime") || key.endsWith("-pausedTime")) { + keysToRemove.push(key); + } + } + + // Remove collected keys + keysToRemove.forEach(key => localStorage.removeItem(key)); + + // Update the display and redirect + updateTicketCountDisplay(); + window.location.href = "/tickets.php"; + } + + // Initial update on script load + updateTicketCountDisplay(); + + // update every 10 seconds + setInterval(updateTicketCountDisplay, 10000); + + // Add event listener to modal + document.addEventListener('DOMContentLoaded', function() { + let modal = document.getElementById('openTicketsModal'); + if (modal) { + $('#openTicketsModal').on('show.bs.modal', loadOpenTickets); + } + }); + + // Add event listener to clear all timers button + document.getElementById('clearAllTimers').addEventListener('click', clearAllTimers); + +})(); diff --git a/js/ticket_time_tracking.js b/js/ticket_time_tracking.js index c50bf1a9..f60a7016 100644 --- a/js/ticket_time_tracking.js +++ b/js/ticket_time_tracking.js @@ -8,6 +8,8 @@ var ticketID = getCurrentTicketID(); var elapsedSecs = getElapsedSeconds(); + updateRunningTicketsCount(); + function getCurrentTicketID() { const urlParams = new URLSearchParams(window.location.search); return urlParams.get('ticket_id'); @@ -53,6 +55,9 @@ timerInterval = setInterval(countTime, 1000); isPaused = false; document.getElementById("startStopTimer").innerText = "Pause"; + updateRunningTicketsCount(); + localStorage.setItem("ticket-timer-running-" + ticketID, "true"); + } function pauseTimer() { @@ -65,11 +70,15 @@ localStorage.removeItem(getLocalStorageKey("startTime")); isPaused = true; document.getElementById("startStopTimer").innerText = "Start"; + updateRunningTicketsCount(); + localStorage.setItem("ticket-timer-running-" + ticketID, "false"); + } function clearTimeStorage() { localStorage.removeItem(getLocalStorageKey("startTime")); localStorage.removeItem(getLocalStorageKey("pausedTime")); + localStorage.removeItem("ticket-timer-running-" + ticketID); } function resetTimer() { @@ -81,6 +90,8 @@ displayTime(); document.getElementById("startStopTimer").innerText = "Start"; } + localStorage.setItem("ticket-timer-running-" + ticketID, "false"); + updateRunningTicketsCount(); } function forceResetTimer() { @@ -116,6 +127,18 @@ } + function updateRunningTicketsCount() { + let runningTickets = parseInt(document.getElementById('runningTicketsCount').innerText, 10); + + if (!isPaused && timerInterval) { + runningTickets += 1; + } else { + runningTickets = Math.max(0, runningTickets - 1); + } + + document.getElementById('runningTicketsCount').innerText = runningTickets.toString(); + } + // Function to check status and pause timer function checkStatusAndPauseTimer() { var status = document.querySelector('select[name="status"]').value; @@ -124,6 +147,7 @@ } } + document.getElementById("hours").addEventListener('change', updateTimeFromInput); document.getElementById("minutes").addEventListener('change', updateTimeFromInput); @@ -153,7 +177,12 @@ // Wait for other synchronous actions (if any) to complete before resetting the timer. setTimeout(forceResetTimer, 100); // 100ms delay should suffice, but you can adjust as needed. }); - + + document.getElementById("ticket_close").addEventListener('click', function() { + // Wait for other synchronous actions (if any) to complete before resetting the timer. + setTimeout(clearTimeStorage, 100); // 100ms delay should suffice, but you can adjust as needed. + }); + try { displayTime(); if (!localStorage.getItem(getLocalStorageKey("startTime")) && !localStorage.getItem(getLocalStorageKey("pausedTime"))) { diff --git a/ticket.php b/ticket.php index 3a6d0a9f..b442057e 100644 --- a/ticket.php +++ b/ticket.php @@ -315,6 +315,7 @@ if (isset($_GET['ticket_id'])) { +
@@ -325,6 +326,7 @@ if (isset($_GET['ticket_id'])) {
+
@@ -332,6 +334,7 @@ if (isset($_GET['ticket_id'])) {
+
@@ -817,7 +820,7 @@ if (isset($_GET['ticket_id'])) { - + Close Ticket diff --git a/top_nav.php b/top_nav.php index 4973b63a..db278138 100644 --- a/top_nav.php +++ b/top_nav.php @@ -36,6 +36,15 @@ + + + + + + \ No newline at end of file diff --git a/top_nav_tickets_modal.php b/top_nav_tickets_modal.php new file mode 100644 index 00000000..fda85b4c --- /dev/null +++ b/top_nav_tickets_modal.php @@ -0,0 +1,21 @@ + +