// ─────────────────────────────────────────────────────────── // Huio Control Panel — Bot Chat Logs View (cp-bot-logs-view.jsx) // ─────────────────────────────────────────────────────────── if (!window.CP_STYLES) throw new Error('[cp-bot-logs-view] window.CP_STYLES not loaded (check cp-styles.jsx)'); function renderBotLogs({ lang, t, appStyles: rawAppStyles, botLogs = [], botLogsSearch = '', setBotLogsSearch, botLogsDateFilter = '', setBotLogsDateFilter, botLogsUserFilter = 'all', setBotLogsUserFilter, botLogsCurrentPage = 1, setBotLogsCurrentPage, botLogsPerPage = 15, hasMoreBotLogs, isLoadingMoreBotLogs, loadMoreBotLogs, setSelectedBotChat, onRefresh, }) { const appStyles = rawAppStyles || window.CP_STYLES || {}; const tr = typeof t === 'function' ? t : ((k) => k); const logs = Array.isArray(botLogs) ? botLogs : []; // High-Load Pre-normalization (hoist invariants outside loop for O(N) efficiency) const query = (botLogsSearch && typeof botLogsSearch === 'string') ? botLogsSearch.trim().toLowerCase() : ''; const targetDate = (botLogsDateFilter && typeof botLogsDateFilter === 'string') ? botLogsDateFilter.trim() : ''; const targetUser = (botLogsUserFilter != null) ? String(botLogsUserFilter) : 'all'; // Filter bot logs const filteredBotLogs = logs.filter(log => { if (!log) return false; // Date filter with zero-allocation ISO substring optimization & NaN protection if (targetDate) { let logDateStr = ''; if (typeof log.created_at === 'string' && log.created_at.length >= 10) { logDateStr = log.created_at.substring(0, 10); } else if (log.created_at) { const d = new Date(log.created_at); if (!isNaN(d.getTime())) { logDateStr = d.toISOString().substring(0, 10); } } if (logDateStr !== targetDate) return false; } // User filter if (targetUser !== 'all') { const tgIdStr = log.telegram_id != null ? String(log.telegram_id) : ''; if (tgIdStr !== targetUser) return false; } // Search query if (query) { const userMsg = (log.message_text || '').toLowerCase(); const botResp = (log.response_text || '').toLowerCase(); const tester = (log.tester_name || '').toLowerCase(); const tgId = log.telegram_id != null ? String(log.telegram_id) : ''; if (!userMsg.includes(query) && !botResp.includes(query) && !tester.includes(query) && !tgId.includes(query)) { return false; } } return true; }); // Unique testers list for filter dropdown (Single-pass Map aggregation with name retention) const uniqueTestersMap = new Map(); for (let i = 0; i < logs.length; i++) { const log = logs[i]; if (log && log.telegram_id != null) { const tgIdStr = String(log.telegram_id); const existingName = uniqueTestersMap.get(tgIdStr); const name = log.tester_name || existingName || `ID: ${tgIdStr}`; uniqueTestersMap.set(tgIdStr, name); } } const uniqueTesters = Array.from(uniqueTestersMap.entries()).map(([id, name]) => ({ id, name })); // Pagination with boundary protection const perPage = Math.max(1, Number(botLogsPerPage) || 15); const totalItems = filteredBotLogs.length; const totalPages = Math.max(1, Math.ceil(totalItems / perPage)); const safeCurrentPage = Math.min(Math.max(1, Number(botLogsCurrentPage) || 1), totalPages); const startIndex = (safeCurrentPage - 1) * perPage; const endIndex = startIndex + perPage; const paginatedBotLogs = filteredBotLogs.slice(startIndex, endIndex); // Pagination Windowing helper (avoids DOM blowup if totalPages is large) const getPaginationPages = () => { if (totalPages <= 7) { return Array.from({ length: totalPages }, (_, i) => i + 1); } const pages = [1]; let start = Math.max(2, safeCurrentPage - 1); let end = Math.min(totalPages - 1, safeCurrentPage + 1); if (safeCurrentPage <= 3) { end = 4; } else if (safeCurrentPage >= totalPages - 2) { start = totalPages - 3; } if (start > 2) pages.push('...'); for (let p = start; p <= end; p++) pages.push(p); if (end < totalPages - 1) pages.push('...'); pages.push(totalPages); return pages; }; return (
{lang === 'vi' ? 'Giám sát lịch sử trò chuyện thời gian thực giữa các kiểm thử viên và Trợ lý ảo QA.' : 'Monitor real-time communication histories between app testers and the QA virtual assistant.'}
| {lang === 'vi' ? 'Thời gian' : 'Time'} | {lang === 'vi' ? 'Kiểm thử viên' : 'Tester'} | {lang === 'vi' ? 'Tin nhắn' : 'Message'} | {lang === 'vi' ? 'Trả lời của bot' : 'Bot Response'} | {lang === 'vi' ? 'Thao tác' : 'Action'} |
|---|---|---|---|---|
| {lang === 'vi' ? 'Không tìm thấy nhật ký chat nào' : 'No bot chat logs found'} | ||||
|
{formattedTime}
{formattedDate}
|
{log.tester_name || 'Tester'}
TG ID: {log.telegram_id || 'N/A'}
|
{log.message_text} | {log.response_text} | |