/** * Supera Glia - Tab de Alertas de Aulas * @module tabs/turmas/AlertasTab * * Este módulo gerencia o monitoramento de alertas de aulas enviados via WhatsApp. * Inclui dashboard de execuções, lista de alertas e detalhes por execução. */ (function() { 'use strict'; SuperaGlia.initAlertasTab = function() { const { useState, useEffect } = SuperaGlia.hooks; const { API_BASE } = SuperaGlia.config; const { Icon, getStatusColor, getRespostaColor } = SuperaGlia; const { formatDateTime, formatDate } = SuperaGlia.utils; // Função auxiliar para formatar data_aula sem conversão de timezone // Evita o problema de mostrar dia anterior por causa do fuso horário const formatDataAula = (data) => { if (!data) return '-'; const dataStr = String(data); // Se vier no formato YYYY-MM-DD ou com timestamp, extrair e converter para DD/MM/YYYY if (dataStr.includes('-')) { const partes = dataStr.split('T')[0].split('-'); if (partes.length === 3) { return `${partes[2]}/${partes[1]}/${partes[0]}`; } } // Fallback para formato já formatado return formatDate(data); }; SuperaGlia.AlertasTab = () => { const [loading, setLoading] = useState(true); const [resumo, setResumo] = useState(null); const [alertas, setAlertas] = useState([]); const [execucoes, setExecucoes] = useState([]); const [filtros, setFiltros] = useState({ status: 'todos', dias: 7 }); const [subTab, setSubTab] = useState('dashboard'); const [execucaoSelecionada, setExecucaoSelecionada] = useState(null); const [detalhesExecucao, setDetalhesExecucao] = useState(null); const [loadingDetalhes, setLoadingDetalhes] = useState(false); useEffect(() => { carregarDados(); }, [filtros.dias]); const carregarDados = async () => { setLoading(true); try { const [resumoRes, alertasRes, execucoesRes] = await Promise.all([ fetch(`${API_BASE}/alertas/resumo`).then(r => r.json()).catch(() => ({ resumo: {} })), fetch(`${API_BASE}/alertas/lista?dias=${filtros.dias}`).then(r => r.json()).catch(() => ({ alertas: [] })), fetch(`${API_BASE}/alertas/execucoes?dias=${filtros.dias}`).then(r => r.json()).catch(() => ({ execucoes: [] })) ]); setResumo(resumoRes.resumo || {}); setAlertas(alertasRes.alertas || []); setExecucoes(execucoesRes.execucoes || []); } catch (e) { console.error('Erro ao carregar alertas:', e); } setLoading(false); }; const abrirDetalhesExecucao = async (exec) => { setExecucaoSelecionada(exec); setLoadingDetalhes(true); console.log('🔍 Abrindo detalhes da execução:', exec); console.log('📋 Total de alertas carregados:', alertas.length); if (alertas.length > 0) { console.log('📋 Exemplo de alerta:', alertas[0]); } // Função para filtrar alertas localmente const filtrarAlertasLocais = () => { const dataExecucao = exec.data_aula || exec.data_alvo; console.log('📊 Filtrando alertas localmente:', { execId: exec.id, dataExecucao, dataExecucaoTipo: typeof dataExecucao, turno: exec.turno, totalAlertas: alertas.length }); // Função para normalizar data - extrair apenas YYYY-MM-DD const normalizarData = (data) => { if (!data) return null; const dataStr = String(data); // Garantir que é string // Se tem 'T', pegar só a parte antes do T // Senão, pegar os primeiros 10 caracteres return dataStr.includes('T') ? dataStr.split('T')[0] : dataStr.substring(0, 10); }; const dataExecNormalizada = normalizarData(dataExecucao); console.log('📅 Data execução normalizada:', dataExecNormalizada); // Debug: mostrar as datas dos primeiros alertas if (alertas.length > 0) { console.log('📋 Primeiros alertas (data_aula):'); alertas.slice(0, 5).forEach((a, i) => { const dataNorm = normalizarData(a.data_aula); console.log(` ${i}: ${a.nome} | data_aula=${a.data_aula} (${typeof a.data_aula}) -> ${dataNorm} | match=${dataNorm === dataExecNormalizada}`); }); } const alertasExec = alertas.filter(a => { const dataAlertaNormalizada = normalizarData(a.data_aula); return dataAlertaNormalizada === dataExecNormalizada; }); console.log(`✅ Alertas encontrados: ${alertasExec.length}`); return { alertas: alertasExec, resumo: { total: alertasExec.length, confirmados: alertasExec.filter(a => a.resposta_tipo === 'confirmado').length, nao_confirmados: alertasExec.filter(a => a.resposta_tipo === 'nao_confirmado').length, talvez: alertasExec.filter(a => a.resposta_tipo === 'talvez').length, aguardando: alertasExec.filter(a => !a.resposta_tipo || a.resposta_tipo === null).length }, _debug: { dataExecucao, dataExecNormalizada, totalAlertasAnalisados: alertas.length } }; }; // Tentar buscar da API, mas se falhar usar fallback local try { const res = await fetch(`${API_BASE}/alertas/execucao/${exec.id}`); const data = await res.json(); console.log('📡 Resposta da API /alertas/execucao:', data); if (data.detalhes && data.detalhes.alertas && data.detalhes.alertas.length > 0) { setDetalhesExecucao(data.detalhes); } else { // API não retornou dados, usar fallback console.log('⚠️ API não retornou detalhes, usando fallback local'); setDetalhesExecucao(filtrarAlertasLocais()); } } catch (e) { // Erro na API (CORS, rede, etc), usar fallback local console.log('⚠️ Erro na API, usando fallback local:', e.message); setDetalhesExecucao(filtrarAlertasLocais()); } setLoadingDetalhes(false); }; const fecharDetalhesExecucao = () => { setExecucaoSelecionada(null); setDetalhesExecucao(null); }; // Sub-tabs de navegação const subTabs = [ { id: 'dashboard', label: 'Dashboard', icon: 'layout-dashboard' }, { id: 'lista', label: 'Lista de Alertas', icon: 'list' }, { id: 'execucoes', label: 'Execuções', icon: 'play-circle' } ]; if (loading) { return React.createElement('div', { className: 'flex items-center justify-center h-64' }, React.createElement('div', { className: 'text-center' }, React.createElement('div', { className: 'w-10 h-10 border-4 border-orange-200 border-t-orange-500 rounded-full animate-spin mx-auto mb-4' }), React.createElement('p', { className: 'text-gray-500' }, 'Carregando alertas...') ) ); } return React.createElement('div', { className: 'space-y-4' }, // Sub-navegação React.createElement('div', { className: 'flex gap-2 border-b border-gray-200 pb-3' }, subTabs.map(tab => React.createElement('button', { key: tab.id, onClick: () => setSubTab(tab.id), className: `flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium transition-colors ${ subTab === tab.id ? 'bg-orange-500 text-white' : 'text-gray-600 hover:bg-gray-100' }` }, React.createElement(Icon, { name: tab.icon, className: 'w-4 h-4' }), tab.label )) ), // DASHBOARD subTab === 'dashboard' && React.createElement('div', { className: 'space-y-4' }, // Cards de resumo React.createElement('div', { className: 'grid grid-cols-2 md:grid-cols-4 gap-4' }, React.createElement('div', { className: 'stat-card bg-white rounded-xl p-5 shadow-sm border border-gray-100' }, React.createElement('div', { className: 'flex items-center justify-between mb-3' }, React.createElement('div', { className: 'w-12 h-12 bg-green-100 rounded-xl flex items-center justify-center' }, React.createElement(Icon, { name: 'send', className: 'w-6 h-6 text-green-600' }) ), React.createElement('span', { className: 'text-xs px-2 py-1 bg-green-50 text-green-600 rounded-full' }, 'Hoje') ), React.createElement('p', { className: 'text-3xl font-bold text-gray-900' }, resumo?.enviados_hoje || 0), React.createElement('p', { className: 'text-sm text-gray-500' }, 'Alertas Enviados') ), React.createElement('div', { className: 'stat-card bg-white rounded-xl p-5 shadow-sm border border-gray-100' }, React.createElement('div', { className: 'flex items-center justify-between mb-3' }, React.createElement('div', { className: 'w-12 h-12 bg-red-100 rounded-xl flex items-center justify-center' }, React.createElement(Icon, { name: 'alert-circle', className: 'w-6 h-6 text-red-600' }) ), React.createElement('span', { className: 'text-xs px-2 py-1 bg-red-50 text-red-600 rounded-full' }, 'Hoje') ), React.createElement('p', { className: 'text-3xl font-bold text-gray-900' }, resumo?.erros_hoje || 0), React.createElement('p', { className: 'text-sm text-gray-500' }, 'Erros de Envio') ), React.createElement('div', { className: 'stat-card bg-white rounded-xl p-5 shadow-sm border border-gray-100' }, React.createElement('div', { className: 'flex items-center justify-between mb-3' }, React.createElement('div', { className: 'w-12 h-12 bg-blue-100 rounded-xl flex items-center justify-center' }, React.createElement(Icon, { name: 'play-circle', className: 'w-6 h-6 text-blue-600' }) ), React.createElement('span', { className: 'text-xs px-2 py-1 bg-blue-50 text-blue-600 rounded-full' }, 'Hoje') ), React.createElement('p', { className: 'text-3xl font-bold text-gray-900' }, resumo?.total_execucoes || 0), React.createElement('p', { className: 'text-sm text-gray-500' }, 'Execuções do Workflow') ), React.createElement('div', { className: 'stat-card bg-white rounded-xl p-5 shadow-sm border border-gray-100' }, React.createElement('div', { className: 'flex items-center justify-between mb-3' }, React.createElement('div', { className: 'w-12 h-12 bg-purple-100 rounded-xl flex items-center justify-center' }, React.createElement(Icon, { name: 'percent', className: 'w-6 h-6 text-purple-600' }) ), React.createElement('span', { className: 'text-xs px-2 py-1 bg-purple-50 text-purple-600 rounded-full' }, 'Semana') ), React.createElement('p', { className: 'text-3xl font-bold text-gray-900' }, resumo?.total_semana ? Math.round((resumo.enviados_semana / resumo.total_semana) * 100) + '%' : '0%' ), React.createElement('p', { className: 'text-sm text-gray-500' }, 'Taxa de Sucesso') ) ), // Última Execução resumo?.ultima_execucao && React.createElement('div', { className: 'bg-white rounded-xl p-5 shadow-sm border border-gray-100' }, React.createElement('h3', { className: 'text-lg font-semibold text-gray-900 mb-4 flex items-center gap-2' }, React.createElement(Icon, { name: 'clock', className: 'w-5 h-5 text-gray-500' }), 'Última Execução' ), React.createElement('div', { className: 'grid grid-cols-2 md:grid-cols-5 gap-4' }, React.createElement('div', null, React.createElement('p', { className: 'text-xs text-gray-500 uppercase tracking-wide' }, 'Data/Hora'), React.createElement('p', { className: 'font-medium text-gray-900' }, formatDateTime(resumo.ultima_execucao)) ), React.createElement('div', null, React.createElement('p', { className: 'text-xs text-gray-500 uppercase tracking-wide' }, 'Turno'), React.createElement('p', { className: 'font-medium text-gray-900 capitalize' }, resumo.ultimo_turno || '-') ), React.createElement('div', null, React.createElement('p', { className: 'text-xs text-gray-500 uppercase tracking-wide' }, 'Status'), React.createElement('span', { className: `text-sm px-2 py-1 rounded-full ${getStatusColor(resumo.ultimo_status)}` }, resumo.ultimo_status || '-') ), React.createElement('div', null, React.createElement('p', { className: 'text-xs text-gray-500 uppercase tracking-wide' }, 'Enviados'), React.createElement('p', { className: 'font-medium text-emerald-600' }, resumo.ultimo_enviados || 0) ), React.createElement('div', null, React.createElement('p', { className: 'text-xs text-gray-500 uppercase tracking-wide' }, 'Erros'), React.createElement('p', { className: 'font-medium text-red-600' }, resumo.ultimo_erros || 0) ) ) ), // Lista de execuções recentes React.createElement('div', { className: 'bg-white rounded-xl p-5 shadow-sm border border-gray-100' }, React.createElement('h3', { className: 'text-lg font-semibold text-gray-900 mb-4 flex items-center gap-2' }, React.createElement(Icon, { name: 'activity', className: 'w-5 h-5 text-gray-500' }), 'Execuções Recentes' ), execucoes.length === 0 ? React.createElement('p', { className: 'text-gray-500 text-center py-4' }, 'Nenhuma execução registrada') : React.createElement('div', { className: 'space-y-3' }, execucoes.slice(0, 8).map((exec, idx) => React.createElement('div', { key: exec.id, className: 'flex items-start gap-4 pb-3 border-b border-gray-100 last:border-0 cursor-pointer hover:bg-gray-50 rounded-lg p-2 -m-2 transition-colors', onClick: () => abrirDetalhesExecucao(exec), title: 'Clique para ver detalhes' }, React.createElement('div', { className: `w-10 h-10 rounded-full flex items-center justify-center flex-shrink-0 ${ exec.status === 'concluido' ? 'bg-emerald-100' : exec.status === 'erro' ? 'bg-red-100' : 'bg-amber-100' }` }, React.createElement(Icon, { name: exec.status === 'concluido' ? 'check' : exec.status === 'erro' ? 'x' : 'clock', className: `w-5 h-5 ${ exec.status === 'concluido' ? 'text-emerald-600' : exec.status === 'erro' ? 'text-red-600' : 'text-amber-600' }` }) ), React.createElement('div', { className: 'flex-1 min-w-0' }, React.createElement('div', { className: 'flex items-center gap-2' }, React.createElement('p', { className: 'font-medium text-gray-900' }, formatDateTime(exec.iniciado_em)), React.createElement('span', { className: `text-xs px-2 py-0.5 rounded-full ${getStatusColor(exec.status)}` }, exec.status), React.createElement('span', { className: 'text-xs text-gray-500 capitalize' }, exec.turno) ), React.createElement('p', { className: 'text-sm text-gray-500' }, `${exec.total_enviados || 0} enviados • ${exec.total_erros || 0} erros • Tentativa ${exec.tentativa || 1}` ) ) ) ) ) ) ), // LISTA DE ALERTAS subTab === 'lista' && React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden' }, // Filtros React.createElement('div', { className: 'p-4 border-b border-gray-100 flex flex-wrap gap-4 items-center' }, React.createElement('select', { value: filtros.status, onChange: e => setFiltros({...filtros, status: e.target.value}), className: 'px-3 py-2 border border-gray-200 rounded-lg text-sm' }, React.createElement('option', { value: 'todos' }, 'Todos os status'), React.createElement('option', { value: 'enviado' }, 'Enviados'), React.createElement('option', { value: 'erro' }, 'Com erro'), React.createElement('option', { value: 'confirmado' }, 'Confirmados'), React.createElement('option', { value: 'nao_confirmado' }, 'Não confirmados') ), React.createElement('select', { value: filtros.dias, onChange: e => setFiltros({...filtros, dias: parseInt(e.target.value)}), className: 'px-3 py-2 border border-gray-200 rounded-lg text-sm' }, React.createElement('option', { value: 3 }, 'Últimos 3 dias'), React.createElement('option', { value: 7 }, 'Últimos 7 dias'), React.createElement('option', { value: 14 }, 'Últimos 14 dias'), React.createElement('option', { value: 30 }, 'Últimos 30 dias') ), React.createElement('button', { onClick: carregarDados, className: 'px-3 py-2 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm text-gray-600 transition-colors flex items-center gap-2' }, React.createElement(Icon, { name: 'refresh-cw', className: 'w-4 h-4' }), 'Atualizar' ) ), // Tabela React.createElement('div', { className: 'overflow-x-auto' }, React.createElement('table', { className: 'w-full' }, React.createElement('thead', { className: 'bg-gray-50' }, React.createElement('tr', null, ['Aluno', 'Turma', 'Data Aula', 'Enviado em', 'Status', 'Resposta'].map(h => React.createElement('th', { key: h, className: 'text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase' }, h) ) ) ), React.createElement('tbody', { className: 'divide-y divide-gray-50' }, alertas.length === 0 ? React.createElement('tr', null, React.createElement('td', { colSpan: 6, className: 'px-4 py-8 text-center text-gray-500' }, 'Nenhum alerta encontrado') ) : alertas .filter(a => filtros.status === 'todos' || a.status === filtros.status || a.resposta_tipo === filtros.status) .slice(0, 100) .map((alerta, i) => React.createElement('tr', { key: i, className: 'hover:bg-gray-50' }, React.createElement('td', { className: 'px-4 py-3 font-medium text-gray-900' }, alerta.nome || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-600' }, alerta.turma || '-'), React.createElement('td', { className: 'px-4 py-3 text-sm' }, formatDataAula(alerta.data_aula)), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-500' }, formatDateTime(alerta.enviado_em)), React.createElement('td', { className: 'px-4 py-3' }, React.createElement('span', { className: `text-xs px-2 py-1 rounded-full ${getStatusColor(alerta.status)}` }, alerta.status) ), React.createElement('td', { className: 'px-4 py-3' }, alerta.resposta_tipo ? React.createElement('span', { className: `text-xs px-2 py-1 rounded-full ${getRespostaColor(alerta.resposta_tipo)}` }, alerta.resposta_tipo.replace('_', ' ') ) : React.createElement('span', { className: 'text-xs text-gray-400' }, 'Aguardando') ) ) ) ) ) ) ), // EXECUÇÕES subTab === 'execucoes' && React.createElement('div', { className: 'bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden' }, React.createElement('div', { className: 'p-4 border-b border-gray-100 flex items-center justify-between' }, React.createElement('h3', { className: 'font-semibold text-gray-900' }, 'Histórico de Execuções'), React.createElement('button', { onClick: carregarDados, className: 'px-3 py-1.5 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm text-gray-600 transition-colors flex items-center gap-2' }, React.createElement(Icon, { name: 'refresh-cw', className: 'w-4 h-4' }), 'Atualizar' ) ), React.createElement('div', { className: 'overflow-x-auto' }, React.createElement('table', { className: 'w-full' }, React.createElement('thead', { className: 'bg-gray-50' }, React.createElement('tr', null, ['Data/Hora', 'Turno', 'Status', 'Enviados', 'Erros', 'Tentativa', 'Duração'].map(h => React.createElement('th', { key: h, className: 'text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase' }, h) ) ) ), React.createElement('tbody', { className: 'divide-y divide-gray-50' }, execucoes.length === 0 ? React.createElement('tr', null, React.createElement('td', { colSpan: 7, className: 'px-4 py-8 text-center text-gray-500' }, 'Nenhuma execução registrada') ) : execucoes.map((exec, i) => React.createElement('tr', { key: i, className: 'hover:bg-gray-50 cursor-pointer', onClick: () => abrirDetalhesExecucao(exec) }, React.createElement('td', { className: 'px-4 py-3 font-medium text-gray-900' }, formatDateTime(exec.iniciado_em)), React.createElement('td', { className: 'px-4 py-3 text-sm capitalize' }, exec.turno), React.createElement('td', { className: 'px-4 py-3' }, React.createElement('span', { className: `text-xs px-2 py-1 rounded-full ${getStatusColor(exec.status)}` }, exec.status) ), React.createElement('td', { className: 'px-4 py-3 text-sm text-emerald-600 font-medium' }, exec.total_enviados || 0), React.createElement('td', { className: 'px-4 py-3 text-sm text-red-600 font-medium' }, exec.total_erros || 0), React.createElement('td', { className: 'px-4 py-3 text-sm' }, exec.tentativa || 1), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-500' }, exec.duracao || '-') ) ) ) ) ) ), // Modal de detalhes da execução execucaoSelecionada && React.createElement('div', { className: 'fixed inset-0 modal-overlay z-50 flex items-center justify-center p-4', onClick: fecharDetalhesExecucao }, React.createElement('div', { className: 'bg-white rounded-2xl shadow-2xl w-full max-w-4xl max-h-[90vh] overflow-hidden', onClick: e => e.stopPropagation() }, React.createElement('div', { className: 'p-6 border-b border-gray-200 flex items-center justify-between' }, React.createElement('div', null, React.createElement('h2', { className: 'text-xl font-bold text-gray-900' }, 'Detalhes da Execução'), React.createElement('p', { className: 'text-sm text-gray-500 mt-1' }, `${formatDateTime(execucaoSelecionada.iniciado_em)} - ${execucaoSelecionada.turno}` ) ), React.createElement('button', { onClick: fecharDetalhesExecucao, className: 'p-2 hover:bg-gray-100 rounded-lg transition-colors' }, React.createElement(Icon, { name: 'x', className: 'w-5 h-5 text-gray-500' }) ) ), React.createElement('div', { className: 'p-6 overflow-y-auto max-h-[70vh]' }, loadingDetalhes ? React.createElement('div', { className: 'flex items-center justify-center py-12' }, React.createElement('div', { className: 'w-10 h-10 border-4 border-orange-200 border-t-orange-500 rounded-full animate-spin' }) ) : detalhesExecucao && React.createElement('div', { className: 'space-y-6' }, // Mensagem de erro se houver detalhesExecucao.erro && React.createElement('div', { className: 'bg-amber-50 border border-amber-200 rounded-lg p-4 text-amber-700 text-sm' }, detalhesExecucao.erro), // Resumo da execução React.createElement('div', { className: 'grid grid-cols-4 gap-4' }, React.createElement('div', { className: 'bg-emerald-50 rounded-lg p-4 text-center' }, React.createElement('p', { className: 'text-2xl font-bold text-emerald-600' }, detalhesExecucao.resumo?.confirmados || 0), React.createElement('p', { className: 'text-sm text-emerald-700' }, 'Confirmados') ), React.createElement('div', { className: 'bg-red-50 rounded-lg p-4 text-center' }, React.createElement('p', { className: 'text-2xl font-bold text-red-600' }, detalhesExecucao.resumo?.nao_confirmados || 0), React.createElement('p', { className: 'text-sm text-red-700' }, 'Não Confirmados') ), React.createElement('div', { className: 'bg-amber-50 rounded-lg p-4 text-center' }, React.createElement('p', { className: 'text-2xl font-bold text-amber-600' }, detalhesExecucao.resumo?.talvez || 0), React.createElement('p', { className: 'text-sm text-amber-700' }, 'Talvez') ), React.createElement('div', { className: 'bg-gray-50 rounded-lg p-4 text-center' }, React.createElement('p', { className: 'text-2xl font-bold text-gray-600' }, detalhesExecucao.resumo?.aguardando || 0), React.createElement('p', { className: 'text-sm text-gray-700' }, 'Aguardando') ) ), // Tabela de alertas desta execução React.createElement('div', { className: 'border border-gray-200 rounded-lg overflow-hidden' }, React.createElement('div', { className: 'bg-gray-50 px-4 py-3 border-b border-gray-200' }, React.createElement('h3', { className: 'font-semibold text-gray-900' }, `Alertas (${detalhesExecucao.alertas?.length || 0})` ) ), (detalhesExecucao.alertas?.length || 0) === 0 ? React.createElement('div', { className: 'text-center py-8 text-gray-500' }, React.createElement(Icon, { name: 'inbox', className: 'w-12 h-12 mx-auto mb-3 text-gray-300' }), React.createElement('p', null, 'Nenhum alerta encontrado para esta execução'), React.createElement('p', { className: 'text-xs mt-2' }, `Data aula: ${execucaoSelecionada.data_aula ? formatDataAula(execucaoSelecionada.data_aula) : 'N/A'} | Turno: ${execucaoSelecionada.turno || 'N/A'}` ), detalhesExecucao._debug && React.createElement('p', { className: 'text-xs mt-1 text-gray-400' }, `${detalhesExecucao._debug.totalAlertasAnalisados} alertas analisados` ) ) : React.createElement('div', { className: 'overflow-x-auto' }, React.createElement('table', { className: 'w-full' }, React.createElement('thead', { className: 'bg-gray-50 border-b border-gray-200' }, React.createElement('tr', null, React.createElement('th', { className: 'text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase' }, 'Aluno'), React.createElement('th', { className: 'text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase' }, 'Turma'), React.createElement('th', { className: 'text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase' }, 'Data Aula'), React.createElement('th', { className: 'text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase' }, 'Enviado em'), React.createElement('th', { className: 'text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase' }, 'Status'), React.createElement('th', { className: 'text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase' }, 'Resposta') ) ), React.createElement('tbody', { className: 'divide-y divide-gray-100' }, (detalhesExecucao.alertas || []).map((alerta, i) => React.createElement('tr', { key: i, className: 'hover:bg-gray-50' }, React.createElement('td', { className: 'px-4 py-3 font-medium text-gray-900' }, alerta.nome_aluno || alerta.nome || '-' ), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-600' }, alerta.turma || '-' ), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-600' }, formatDataAula(alerta.data_aula) ), React.createElement('td', { className: 'px-4 py-3 text-sm text-gray-500' }, formatDateTime(alerta.enviado_em) ), React.createElement('td', { className: 'px-4 py-3' }, React.createElement('span', { className: `text-xs px-2 py-1 rounded-full ${getStatusColor(alerta.status)}` }, alerta.status || 'enviado') ), React.createElement('td', { className: 'px-4 py-3' }, React.createElement('span', { className: `text-xs px-2 py-1 rounded-full ${getRespostaColor(alerta.resposta_tipo)}` }, alerta.resposta_tipo?.replace('_', ' ') || 'Aguardando') ) ) ) ) ) ) ) ) ) ) ) ); }; }; })();