'use client'; import { useState, useEffect } from 'react'; import { invoke } from '@tauri-apps/api/core'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'; import { Switch } from '@/components/ui/switch'; import { Label } from '@/components/ui/label'; import { Plus, Trash2, Clock, Play, Pause, CheckCircle2, XCircle, X, ArrowLeft } from 'lucide-react'; import { useRouter } from 'next/navigation'; import { TitleBar } from '@/components/titlebar'; import { Badge } from '@/components/ui/badge'; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog'; import { Input } from '@/components/ui/input'; import { Textarea } from '@/components/ui/textarea'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; interface Task { id: string; label: string; cron_schedule: string; action: { type: 'search_and_summarize' | 'just_ping' | 'custom_prompt'; query?: string; model?: string; max_results?: number; message?: string; prompt?: string; }; enabled: boolean; last_run: string | null; created_at: string; updated_at: string; } export default function TasksPage() { const router = useRouter(); const [tasks, setTasks] = useState([]); const [loading, setLoading] = useState(true); const [isDialogOpen, setIsDialogOpen] = useState(false); useEffect(() => { loadTasks(); }, []); const loadTasks = async () => { try { setLoading(true); const loaded = await invoke('list_tasks'); setTasks(loaded); } catch (error) { console.error('Erro ao carregar tasks:', error); } finally { setLoading(false); } }; const toggleTask = async (id: string, currentEnabled: boolean) => { try { await invoke('toggle_task', { id, enabled: !currentEnabled }); await loadTasks(); } catch (error) { console.error('Erro ao alternar task:', error); } }; const deleteTask = async (id: string) => { if (!confirm('Tem certeza que deseja excluir esta task?')) { return; } try { await invoke('delete_task', { id }); await loadTasks(); } catch (error) { console.error('Erro ao excluir task:', error); } }; const formatCron = (cron: string) => { // Formatação básica de cron para exibição const parts = cron.split(' '); if (parts.length === 5) { const [min, hour, day, month, weekday] = parts; if (min === '0' && hour !== '*' && day === '*' && month === '*' && weekday === '*') { return `Todo dia às ${hour}:00`; } if (min === '0' && hour === '8' && day === '*' && month === '*' && weekday === '*') { return 'Todo dia às 8:00'; } } return cron; }; const formatLastRun = (lastRun: string | null) => { if (!lastRun) return 'Nunca'; try { const date = new Date(lastRun); return date.toLocaleString('pt-BR'); } catch { return lastRun; } }; return (

Tarefas Agendadas

Gerencie tarefas que executam automaticamente em segundo plano

{loading ? (
Carregando tasks...
) : tasks.length === 0 ? (

Nenhuma task agendada ainda.

Criar Nova Task Configure uma tarefa para executar automaticamente { setIsDialogOpen(false); loadTasks(); }} />
) : ( <>
Criar Nova Task Configure uma tarefa para executar automaticamente { setIsDialogOpen(false); loadTasks(); }} />
{tasks.map(task => (
{task.label} {task.enabled ? ( Ativa ) : ( Pausada )}
{formatCron(task.cron_schedule)} Última execução: {formatLastRun(task.last_run)}
toggleTask(task.id, task.enabled)} />

Tipo: { task.action.type === 'search_and_summarize' ? 'Pesquisar e Resumir' : task.action.type === 'just_ping' ? 'Notificação' : 'Prompt Customizado' }

{task.action.query && (

Query: {task.action.query}

)} {task.action.model && (

Modelo: {task.action.model}

)}
))}
)}
); } function TaskFormDialog({ onSuccess }: { onSuccess: () => void }) { const [label, setLabel] = useState(''); const [scheduleType, setScheduleType] = useState<'daily' | 'weekly' | 'hourly' | 'custom'>('daily'); const [hour, setHour] = useState('8'); const [minute, setMinute] = useState('0'); const [intervalHours, setIntervalHours] = useState('1'); const [customCron, setCustomCron] = useState(''); const [taskType, setTaskType] = useState<'search_and_summarize' | 'just_ping' | 'custom_prompt'>('search_and_summarize'); const [query, setQuery] = useState(''); const [model, setModel] = useState('llama3.2'); const [maxResults, setMaxResults] = useState(3); const [message, setMessage] = useState(''); const [customPrompt, setCustomPrompt] = useState(''); const [submitting, setSubmitting] = useState(false); const generateCron = (): string => { if (scheduleType === 'custom') { return customCron; } if (scheduleType === 'hourly') { return `0 */${intervalHours} * * *`; } if (scheduleType === 'daily') { return `${minute} ${hour} * * *`; } // Weekly (every Monday at hour:minute) return `${minute} ${hour} * * 1`; }; const getCronPreview = (): string => { const cron = generateCron(); if (scheduleType === 'hourly') { return `A cada ${intervalHours} hora(s)`; } if (scheduleType === 'daily') { return `Todo dia às ${hour.padStart(2, '0')}:${minute.padStart(2, '0')}`; } if (scheduleType === 'weekly') { return `Toda segunda-feira às ${hour.padStart(2, '0')}:${minute.padStart(2, '0')}`; } return cron; }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setSubmitting(true); try { let action: any; if (taskType === 'search_and_summarize') { action = { type: 'search_and_summarize', query, model, max_results: maxResults, }; } else if (taskType === 'just_ping') { action = { type: 'just_ping', message, }; } else { action = { type: 'custom_prompt', prompt: customPrompt, model, }; } await invoke('create_task', { label, cronSchedule: generateCron(), action, }); onSuccess(); } catch (error) { console.error('Erro ao criar task:', error); alert('Erro ao criar task. Verifique o console para mais detalhes.'); } finally { setSubmitting(false); } }; return (
setLabel(e.target.value)} placeholder="Ex: Resumo de Notícias Diário" required />
{/* Cron Preview */}
Agendamento: {getCronPreview()}
Cron: {generateCron()}
{scheduleType === 'custom' ? (
setCustomCron(e.target.value)} placeholder="0 8 * * * (todo dia às 8h)" required />

Formato: minuto hora dia mês dia-da-semana (ex: 0 8 * * * = todo dia às 8h)

) : scheduleType === 'hourly' ? (
setIntervalHours(e.target.value)} required />

A task será executada a cada {intervalHours} hora(s)

) : (
setHour(e.target.value)} required />
setMinute(e.target.value)} required />
)}
{taskType === 'search_and_summarize' && ( <>
setQuery(e.target.value)} placeholder="Ex: notícias sobre inteligência artificial hoje" required />
setModel(e.target.value)} placeholder="llama3.2" required />
setMaxResults(parseInt(e.target.value))} required />
)} {taskType === 'just_ping' && (