const SchedulesUI = {
schedules: [],
async load() {
try {
SchedulesUI.schedules = await API.schedules.list();
SchedulesUI.render();
} catch (err) {
Toast.error(`Erro ao carregar agendamentos: ${err.message}`);
}
},
render() {
const tbody = document.getElementById('schedules-tbody');
if (!tbody) return;
if (SchedulesUI.schedules.length === 0) {
tbody.innerHTML = `
|
Nenhum agendamento configurado
|
`;
if (window.lucide) lucide.createIcons({ nodes: [tbody] });
return;
}
tbody.innerHTML = SchedulesUI.schedules.map((schedule) => {
const cronExpr = schedule.cronExpression || schedule.cronExpr || '';
const statusClass = schedule.active ? 'badge-active' : 'badge-inactive';
const statusLabel = schedule.active ? 'Ativo' : 'Inativo';
const humanCron = SchedulesUI.cronToHuman(cronExpr);
const nextRun = schedule.nextRun
? new Date(schedule.nextRun).toLocaleString('pt-BR')
: '—';
return `
| ${schedule.agentName || schedule.agentId || '—'} |
${schedule.taskDescription || '—'} |
${humanCron}
${cronExpr}
|
${nextRun} |
${statusLabel} |
|
`;
}).join('');
if (window.lucide) lucide.createIcons({ nodes: [tbody] });
},
async openCreateModal() {
try {
const agents = await API.agents.list();
const select = document.getElementById('schedule-agent');
if (select) {
select.innerHTML = '' +
agents
.filter((a) => a.status === 'active')
.map((a) => ``)
.join('');
}
const taskEl = document.getElementById('schedule-task');
if (taskEl) taskEl.value = '';
const cronEl = document.getElementById('schedule-cron');
if (cronEl) cronEl.value = '';
Modal.open('schedule-modal-overlay');
} catch (err) {
Toast.error(`Erro ao abrir modal de agendamento: ${err.message}`);
}
},
async save() {
const agentId = document.getElementById('schedule-agent')?.value;
const taskDescription = document.getElementById('schedule-task')?.value.trim();
const cronExpression = document.getElementById('schedule-cron')?.value.trim();
if (!agentId) {
Toast.warning('Selecione um agente');
return;
}
if (!taskDescription) {
Toast.warning('Descrição da tarefa é obrigatória');
return;
}
if (!cronExpression) {
Toast.warning('Expressão cron é obrigatória');
return;
}
try {
await API.schedules.create({ agentId, taskDescription, cronExpression });
Toast.success('Agendamento criado com sucesso');
Modal.close('schedule-modal-overlay');
await SchedulesUI.load();
} catch (err) {
Toast.error(`Erro ao criar agendamento: ${err.message}`);
}
},
async delete(taskId) {
const confirmed = await Modal.confirm(
'Remover agendamento',
'Tem certeza que deseja remover este agendamento?'
);
if (!confirmed) return;
try {
await API.schedules.delete(taskId);
Toast.success('Agendamento removido com sucesso');
await SchedulesUI.load();
} catch (err) {
Toast.error(`Erro ao remover agendamento: ${err.message}`);
}
},
cronToHuman(expression) {
if (!expression) return '—';
const presets = {
'* * * * *': 'A cada minuto',
'*/5 * * * *': 'A cada 5 minutos',
'*/10 * * * *': 'A cada 10 minutos',
'*/15 * * * *': 'A cada 15 minutos',
'*/30 * * * *': 'A cada 30 minutos',
'0 * * * *': 'A cada hora',
'0 */2 * * *': 'A cada 2 horas',
'0 */6 * * *': 'A cada 6 horas',
'0 */12 * * *': 'A cada 12 horas',
'0 0 * * *': 'Todo dia à meia-noite',
'0 9 * * *': 'Todo dia às 9h',
'0 18 * * *': 'Todo dia às 18h',
'0 0 * * 1': 'Toda segunda-feira',
'0 0 * * 1-5': 'Dias úteis à meia-noite',
'0 9 * * 1-5': 'Dias úteis às 9h',
'0 9 * * 1': 'Semanal (seg 09:00)',
'0 0 1 * *': 'Todo primeiro do mês',
'0 0 1 1 *': 'Todo 1º de janeiro',
};
if (presets[expression]) return presets[expression];
const parts = expression.split(' ');
if (parts.length !== 5) return expression;
const [minute, hour, day, month, weekday] = parts;
if (minute.startsWith('*/')) return `A cada ${minute.slice(2)} minutos`;
if (hour.startsWith('*/') && minute === '0') return `A cada ${hour.slice(2)} horas`;
if (minute === '0' && hour !== '*' && day === '*' && month === '*' && weekday === '*') {
return `Todo dia às ${hour.padStart(2, '0')}h`;
}
return expression;
},
};
window.SchedulesUI = SchedulesUI;