diff --git a/admin/class-twp-admin.php b/admin/class-twp-admin.php index a79d331..24c2ec3 100644 --- a/admin/class-twp-admin.php +++ b/admin/class-twp-admin.php @@ -3973,7 +3973,47 @@ class TWP_Admin { ORDER BY c.position ASC ", $user_id)); - wp_send_json_success($waiting_calls); + wp_send_json_success(array( + 'count' => count($waiting_calls), + 'calls' => $waiting_calls + )); + } + + /** + * AJAX handler for getting agent's assigned queues + */ + public function ajax_get_agent_queues() { + // Check for either admin or frontend nonce + if (!$this->verify_ajax_nonce()) { + wp_send_json_error('Invalid nonce'); + return; + } + + if (!current_user_can('manage_options') && !current_user_can('twp_access_agent_queue')) { + wp_send_json_error('Unauthorized - Agent queue access required'); + return; + } + + global $wpdb; + $user_id = get_current_user_id(); + $queues_table = $wpdb->prefix . 'twp_call_queues'; + $groups_table = $wpdb->prefix . 'twp_group_members'; + $calls_table = $wpdb->prefix . 'twp_queued_calls'; + + // Get queues where user is a member of the assigned agent group + $user_queues = $wpdb->get_results($wpdb->prepare(" + SELECT DISTINCT q.*, + COUNT(c.id) as waiting_count, + COALESCE(SUM(CASE WHEN c.status = 'waiting' THEN 1 ELSE 0 END), 0) as current_waiting + FROM $queues_table q + LEFT JOIN $groups_table gm ON gm.group_id = q.agent_group_id + LEFT JOIN $calls_table c ON c.queue_id = q.id AND c.status = 'waiting' + WHERE gm.user_id = %d AND gm.is_active = 1 + GROUP BY q.id + ORDER BY q.queue_name ASC + ", $user_id)); + + wp_send_json_success($user_queues); } /** diff --git a/assets/css/browser-phone-frontend.css b/assets/css/browser-phone-frontend.css index c799b0d..78fe1ca 100644 --- a/assets/css/browser-phone-frontend.css +++ b/assets/css/browser-phone-frontend.css @@ -293,8 +293,8 @@ font-weight: 500; } -/* Queue Controls */ -.twp-queue-controls { +/* Queue Management Section */ +.twp-queue-section { background: #fff; padding: 16px; border-radius: 8px; @@ -302,18 +302,148 @@ margin-bottom: 20px; } -.twp-queue-controls h4 { - margin: 0 0 12px 0; +.twp-queue-section h4 { + margin: 0 0 16px 0; color: #333; font-size: 1.1rem; + text-align: center; } -.queue-status { - margin-bottom: 12px; +/* Queue List */ +.twp-queue-list { + margin-bottom: 16px; +} + +.queue-loading, +.no-queues { + text-align: center; color: #6c757d; + font-style: italic; + padding: 20px; +} + +.no-queues { + background: #f8f9fa; + border: 2px dashed #e9ecef; + border-radius: 8px; +} + +.queue-item { + background: #f8f9fa; + border: 2px solid #e9ecef; + border-radius: 8px; + padding: 12px; + margin-bottom: 8px; + cursor: pointer; + transition: all 0.2s ease; + position: relative; +} + +.queue-item:hover { + border-color: #007cba; + background: #e3f2fd; +} + +.queue-item.selected { + border-color: #007cba; + background: #e3f2fd; + box-shadow: 0 0 0 1px #007cba; +} + +.queue-item.has-calls { + border-left: 4px solid #28a745; +} + +.queue-item.has-calls::after { + content: ''; + position: absolute; + top: 8px; + right: 8px; + width: 8px; + height: 8px; + background: #28a745; + border-radius: 50%; + animation: pulse 2s infinite; +} + +.queue-name { + font-weight: 600; + color: #333; + margin-bottom: 4px; +} + +.queue-info { + display: flex; + justify-content: space-between; + align-items: center; + font-size: 0.9rem; + color: #6c757d; +} + +.queue-waiting { font-weight: 500; } +.queue-waiting.has-calls { + color: #28a745; + font-weight: 600; +} + +.queue-capacity { + font-size: 0.8rem; +} + +/* Queue Controls */ +.twp-queue-controls { + background: #f8f9fa; + padding: 16px; + border-radius: 8px; + border: 2px solid #e9ecef; + margin-top: 16px; +} + +.selected-queue-info { + margin-bottom: 16px; + text-align: center; +} + +.selected-queue-info h5 { + margin: 0 0 8px 0; + color: #333; + font-size: 1rem; +} + +.queue-stats { + display: flex; + justify-content: center; + gap: 20px; + font-size: 0.9rem; + color: #6c757d; +} + +.queue-stats span { + font-weight: 500; +} + +.queue-actions { + display: flex; + gap: 8px; +} + +.queue-actions .twp-btn { + flex: 1; +} + +.twp-btn-secondary { + background: #6c757d; + color: white; +} + +.twp-btn-secondary:hover { + background: #5a6268; + transform: translateY(-1px); +} + /* Messages */ .twp-messages { margin-top: 16px; @@ -397,6 +527,26 @@ min-height: 45px; font-size: 16px; } + + /* Queue section mobile adjustments */ + .queue-stats { + flex-direction: column; + gap: 8px; + } + + .queue-actions { + flex-direction: column; + } + + .queue-item { + padding: 10px; + } + + .queue-info { + flex-direction: column; + align-items: flex-start; + gap: 4px; + } } /* Dark mode support */ diff --git a/assets/js/browser-phone-frontend.js b/assets/js/browser-phone-frontend.js index c88c46b..025319e 100644 --- a/assets/js/browser-phone-frontend.js +++ b/assets/js/browser-phone-frontend.js @@ -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('