Add comprehensive queue management to browser phone shortcode

Features Added:
- Queue display showing all assigned queues for the current user
- Real-time queue statistics (waiting calls, capacity)
- Visual indicators for queues with waiting calls (green border, pulse animation)
- Queue selection with click interaction
- Accept next call from selected queue functionality
- Auto-refresh of queue data every 30 seconds
- Mobile-responsive queue interface

Backend Changes:
- New ajax_get_agent_queues() handler to fetch user's assigned queues
- Enhanced ajax_get_waiting_calls() to return structured data
- Proper permission checking for twp_access_agent_queue capability

Frontend Enhancements:
- Interactive queue list with selection states
- Queue controls panel showing selected queue info
- Refresh button for manual queue updates
- Visual feedback for queues with active calls
- Mobile-optimized layout for smaller screens

UI/UX Improvements:
- Queues with waiting calls highlighted with green accent
- Pulsing indicator for active queues
- Auto-selection of first queue with calls
- Responsive design for mobile devices
- Dark mode support for queue elements

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-08-13 13:58:24 -07:00
parent 9bef599406
commit 12c285dc90
5 changed files with 341 additions and 43 deletions

View File

@@ -11,6 +11,8 @@
let callStartTime = null;
let isConnected = false;
let availableNumbers = [];
let userQueues = [];
let selectedQueue = null;
// Initialize when document is ready
$(document).ready(function() {
@@ -22,6 +24,7 @@
initializeBrowserPhone();
bindEvents();
loadPhoneNumbers();
loadUserQueues();
});
/**
@@ -191,6 +194,17 @@
acceptQueueCall();
});
// Refresh queues button
$('#twp-refresh-queues').on('click', function() {
loadUserQueues();
});
// Queue item selection
$(document).on('click', '.queue-item', function() {
const queueId = $(this).data('queue-id');
selectQueue(queueId);
});
// Manual number input
$('#twp-dial-number').on('input', function() {
// Only allow valid phone number characters
@@ -336,21 +350,123 @@
}
/**
* Accept next call from queue
* Load user's assigned queues
*/
function loadUserQueues() {
$.ajax({
url: twp_frontend_ajax.ajax_url,
method: 'POST',
data: {
action: 'twp_get_agent_queues',
nonce: twp_frontend_ajax.nonce
},
success: function(response) {
if (response.success) {
userQueues = response.data;
displayQueues();
} else {
showMessage('Failed to load queues: ' + (response.data || 'Unknown error'), 'error');
}
},
error: function() {
showMessage('Failed to load queues', 'error');
}
});
}
/**
* Display queues in the UI
*/
function displayQueues() {
const $queueList = $('#twp-queue-list');
if (userQueues.length === 0) {
$queueList.html('<div class="no-queues">No queues assigned to you.</div>');
$('#twp-queue-section').hide();
return;
}
$('#twp-queue-section').show();
let html = '';
userQueues.forEach(function(queue) {
const hasWaiting = parseInt(queue.current_waiting) > 0;
const waitingCount = queue.current_waiting || 0;
html += `
<div class="queue-item ${hasWaiting ? 'has-calls' : ''}" data-queue-id="${queue.id}">
<div class="queue-name">${queue.queue_name}</div>
<div class="queue-info">
<span class="queue-waiting ${hasWaiting ? 'has-calls' : ''}">
${waitingCount} waiting
</span>
<span class="queue-capacity">
Max: ${queue.max_size}
</span>
</div>
</div>
`;
});
$queueList.html(html);
// Auto-select first queue with calls, or first queue if none have calls
const firstQueueWithCalls = userQueues.find(q => parseInt(q.current_waiting) > 0);
const queueToSelect = firstQueueWithCalls || userQueues[0];
if (queueToSelect) {
selectQueue(queueToSelect.id);
}
}
/**
* Select a queue
*/
function selectQueue(queueId) {
selectedQueue = userQueues.find(q => q.id == queueId);
if (!selectedQueue) return;
// Update UI selection
$('.queue-item').removeClass('selected');
$(`.queue-item[data-queue-id="${queueId}"]`).addClass('selected');
// Update queue controls
$('#selected-queue-name').text(selectedQueue.queue_name);
$('#twp-waiting-count').text(selectedQueue.current_waiting || 0);
$('#twp-queue-max-size').text(selectedQueue.max_size);
// Show queue controls if there are waiting calls
if (parseInt(selectedQueue.current_waiting) > 0) {
$('#twp-queue-controls').show();
} else {
$('#twp-queue-controls').hide();
}
}
/**
* Accept next call from selected queue
*/
function acceptQueueCall() {
if (!selectedQueue) {
showMessage('Please select a queue first', 'error');
return;
}
$.ajax({
url: twp_frontend_ajax.ajax_url,
method: 'POST',
data: {
action: 'twp_accept_next_queue_call',
queue_id: selectedQueue.id,
nonce: twp_frontend_ajax.nonce
},
success: function(response) {
if (response.success) {
showMessage('Connecting to next caller...', 'info');
// Refresh queue data after accepting call
setTimeout(loadUserQueues, 1000);
} else {
showMessage(response.data || 'No calls waiting', 'info');
showMessage(response.data || 'No calls waiting in this queue', 'info');
}
},
error: function() {
@@ -467,34 +583,9 @@
// Periodic status updates
setInterval(function() {
if (isConnected) {
loadWaitingCallsCount();
loadUserQueues(); // This will refresh all queue data including waiting counts
}
}, 30000); // Every 30 seconds
/**
* Load waiting calls count for queue display
*/
function loadWaitingCallsCount() {
$.ajax({
url: twp_frontend_ajax.ajax_url,
method: 'POST',
data: {
action: 'twp_get_waiting_calls',
nonce: twp_frontend_ajax.nonce
},
success: function(response) {
if (response.success) {
$('#twp-waiting-count').text(response.data.count || 0);
// Show queue controls if user has permission and there are waiting calls
if (response.data.count > 0) {
$('#twp-queue-controls').show();
} else {
$('#twp-queue-controls').hide();
}
}
}
});
}
})(jQuery);