'use client' import { useState, useEffect } from 'react' import { Clock, Plus, X, Calendar, AlertTriangle, CheckCircle2, XCircle, Filter, Loader2, Trash2, Edit3, Building2, FileText, } from 'lucide-react' interface Prazo { id: string title: string description: string | null processNumber: string | null court: string | null deadline: string alertDays: number status: 'PENDENTE' | 'CONCLUIDO' | 'VENCIDO' | 'CANCELADO' priority: 'ALTA' | 'MEDIA' | 'BAIXA' createdAt: string } const priorityConfig = { ALTA: { label: 'Alta', color: 'text-red-400', bg: 'bg-red-500/15 border-red-500/30', dot: 'bg-red-500' }, MEDIA: { label: 'Média', color: 'text-yellow-400', bg: 'bg-yellow-500/15 border-yellow-500/30', dot: 'bg-yellow-500' }, BAIXA: { label: 'Baixa', color: 'text-green-400', bg: 'bg-green-500/15 border-green-500/30', dot: 'bg-green-500' }, } const statusConfig = { PENDENTE: { label: 'Pendente', color: 'text-blue-400', bg: 'bg-blue-500/15 border-blue-500/30', icon: Clock }, CONCLUIDO: { label: 'Concluído', color: 'text-green-400', bg: 'bg-green-500/15 border-green-500/30', icon: CheckCircle2 }, VENCIDO: { label: 'Vencido', color: 'text-red-400', bg: 'bg-red-500/15 border-red-500/30', icon: AlertTriangle }, CANCELADO: { label: 'Cancelado', color: 'text-zinc-400', bg: 'bg-zinc-500/15 border-zinc-500/30', icon: XCircle }, } export default function PrazosPage() { const [prazos, setPrazos] = useState([]) const [loading, setLoading] = useState(true) const [showModal, setShowModal] = useState(false) const [editingPrazo, setEditingPrazo] = useState(null) const [filterStatus, setFilterStatus] = useState('') const [filterPriority, setFilterPriority] = useState('') const [saving, setSaving] = useState(false) // Form state const [form, setForm] = useState({ title: '', description: '', processNumber: '', court: '', deadline: '', alertDays: 3, priority: 'MEDIA' as 'ALTA' | 'MEDIA' | 'BAIXA', }) useEffect(() => { fetchPrazos() }, [filterStatus, filterPriority]) async function fetchPrazos() { setLoading(true) try { const params = new URLSearchParams() if (filterStatus) params.set('status', filterStatus) if (filterPriority) params.set('priority', filterPriority) const res = await fetch(`/api/prazos?${params}`) if (res.ok) { const data = await res.json() setPrazos(data.prazos || []) } } catch (e) { console.error('Failed to load prazos:', e) } finally { setLoading(false) } } function openNewModal() { setEditingPrazo(null) setForm({ title: '', description: '', processNumber: '', court: '', deadline: '', alertDays: 3, priority: 'MEDIA' }) setShowModal(true) } function openEditModal(prazo: Prazo) { setEditingPrazo(prazo) setForm({ title: prazo.title, description: prazo.description || '', processNumber: prazo.processNumber || '', court: prazo.court || '', deadline: prazo.deadline.split('T')[0], alertDays: prazo.alertDays, priority: prazo.priority, }) setShowModal(true) } async function handleSave() { if (!form.title || !form.deadline) return setSaving(true) try { if (editingPrazo) { await fetch(`/api/prazos/${editingPrazo.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(form), }) } else { await fetch('/api/prazos', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(form), }) } setShowModal(false) fetchPrazos() } catch (e) { console.error('Failed to save:', e) } finally { setSaving(false) } } async function handleStatusChange(id: string, status: string) { try { await fetch(`/api/prazos/${id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ status }), }) fetchPrazos() } catch (e) { console.error('Failed to update status:', e) } } async function handleDelete(id: string) { if (!confirm('Tem certeza que deseja excluir este prazo?')) return try { await fetch(`/api/prazos/${id}`, { method: 'DELETE' }) fetchPrazos() } catch (e) { console.error('Failed to delete:', e) } } function getDaysUntil(deadline: string) { const now = new Date() now.setHours(0, 0, 0, 0) const dl = new Date(deadline) dl.setHours(0, 0, 0, 0) return Math.ceil((dl.getTime() - now.getTime()) / (1000 * 60 * 60 * 24)) } function formatDate(dateStr: string) { return new Date(dateStr).toLocaleDateString('pt-BR', { day: '2-digit', month: '2-digit', year: 'numeric' }) } // Stats const stats = { total: prazos.length, pendentes: prazos.filter(p => p.status === 'PENDENTE').length, vencidos: prazos.filter(p => p.status === 'VENCIDO').length, concluidos: prazos.filter(p => p.status === 'CONCLUIDO').length, } // Auto-mark overdue const processedPrazos = prazos.map(p => { if (p.status === 'PENDENTE' && getDaysUntil(p.deadline) < 0) { return { ...p, status: 'VENCIDO' as const } } return p }) return (
{/* Header */}

Gestão de Prazos

Gerencie seus prazos processuais e compromissos

{/* Stats Cards */}
{[ { label: 'Total', value: stats.total, color: 'text-white', bg: 'bg-white/5 border-white/10' }, { label: 'Pendentes', value: stats.pendentes, color: 'text-blue-400', bg: 'bg-blue-500/10 border-blue-500/20' }, { label: 'Vencidos', value: stats.vencidos, color: 'text-red-400', bg: 'bg-red-500/10 border-red-500/20' }, { label: 'Concluídos', value: stats.concluidos, color: 'text-green-400', bg: 'bg-green-500/10 border-green-500/20' }, ].map(s => (

{s.label}

{s.value}

))}
{/* Filters */}
{/* Prazos List */} {loading ? (
) : processedPrazos.length === 0 ? (

Nenhum prazo encontrado

) : (
{processedPrazos.map(prazo => { const days = getDaysUntil(prazo.deadline) const isUrgent = prazo.status === 'PENDENTE' && days >= 0 && days <= 3 const isOverdue = days < 0 && prazo.status === 'PENDENTE' const prio = priorityConfig[prazo.priority] const stat = statusConfig[prazo.status] const StatusIcon = stat.icon return (
{/* Priority indicator */}

{prazo.title}

{prazo.description && (

{prazo.description}

)}
{prio.label} {stat.label}
{formatDate(prazo.deadline)} {prazo.processNumber && ( {prazo.processNumber} )} {prazo.court && ( {prazo.court} )} {prazo.status === 'PENDENTE' && ( {isOverdue ? `Vencido há ${Math.abs(days)} dia${Math.abs(days) !== 1 ? 's' : ''}` : days === 0 ? 'Vence hoje!' : days === 1 ? 'Vence amanhã' : `${days} dias restantes` } )}
{/* Actions */}
{prazo.status === 'PENDENTE' && ( )}
) })}
)} {/* Modal */} {showModal && (

{editingPrazo ? 'Editar Prazo' : 'Novo Prazo'}

setForm(f => ({ ...f, title: e.target.value }))} className="w-full rounded-lg border border-white/10 bg-white/5 px-3 py-2 text-sm text-white outline-none focus:border-teal-500/40" placeholder="Ex: Contestação - Processo 1234567" />