'use client'; import { useState } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { Button, Card, CardContent, Input, Label, Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, } from '@horux/shared-ui'; import { apiClient } from '@/lib/api/client'; import { Plus, Trash2, Edit, CheckCircle2, Circle, Sparkles } from 'lucide-react'; const RECURRENCIAS = [ { value: 'semanal', label: 'Semanal' }, { value: 'quincenal', label: 'Quincenal' }, { value: 'mensual', label: 'Mensual' }, { value: 'bimestral', label: 'Bimestral' }, { value: 'trimestral', label: 'Trimestral' }, { value: 'semestral', label: 'Semestral' }, { value: 'anual', label: 'Anual' }, ]; const DIAS_SEMANA = [ { value: 1, label: 'Lunes' }, { value: 2, label: 'Martes' }, { value: 3, label: 'Miércoles' }, { value: 4, label: 'Jueves' }, { value: 5, label: 'Viernes' }, { value: 6, label: 'Sábado' }, { value: 7, label: 'Domingo' }, ]; interface Tarea { id: string; contribuyenteId: string; nombre: string; descripcion: string | null; recurrencia: string; diaSemana: number | null; diaMes: number | null; soloSupervisorCompleta: boolean; esDefault: boolean; active: boolean; orden: number; periodoActual: { id: string; fechaLimite: string; completada: boolean; completadaAt: string | null; } | null; } interface FormState { nombre: string; descripcion: string; recurrencia: string; diaSemana: number; diaMes: number; soloSupervisorCompleta: boolean; } const EMPTY_FORM: FormState = { nombre: '', descripcion: '', recurrencia: 'mensual', diaSemana: 5, diaMes: 10, soloSupervisorCompleta: false, }; export function TareasTab({ contribuyenteId }: { contribuyenteId: string | null }) { const queryClient = useQueryClient(); const [showForm, setShowForm] = useState(false); const [editingId, setEditingId] = useState(null); const [form, setForm] = useState(EMPTY_FORM); const tareasQuery = useQuery({ queryKey: ['tareas', contribuyenteId], queryFn: async () => { const params = new URLSearchParams({ contribuyenteId: contribuyenteId! }); const { data } = await apiClient.get(`/tareas?${params}`); return data; }, enabled: !!contribuyenteId, }); const invalidate = () => queryClient.invalidateQueries({ queryKey: ['tareas', contribuyenteId] }); const seedMutation = useMutation({ mutationFn: async () => { const params = new URLSearchParams({ contribuyenteId: contribuyenteId! }); await apiClient.post(`/tareas/seed?${params}`); }, onSuccess: invalidate, }); const saveMutation = useMutation({ mutationFn: async () => { const payload = { nombre: form.nombre, descripcion: form.descripcion || null, recurrencia: form.recurrencia, diaSemana: form.recurrencia === 'semanal' || form.recurrencia === 'quincenal' ? form.diaSemana : null, diaMes: form.recurrencia === 'semanal' || form.recurrencia === 'quincenal' ? null : form.diaMes, soloSupervisorCompleta: form.soloSupervisorCompleta, }; if (editingId) { await apiClient.patch(`/tareas/${editingId}`, payload); } else { const params = new URLSearchParams({ contribuyenteId: contribuyenteId! }); await apiClient.post(`/tareas?${params}`, payload); } }, onSuccess: () => { setShowForm(false); setEditingId(null); setForm(EMPTY_FORM); invalidate(); }, }); const deleteMutation = useMutation({ mutationFn: async (id: string) => apiClient.delete(`/tareas/${id}`), onSuccess: invalidate, }); const completarMutation = useMutation({ mutationFn: async (periodoId: string) => apiClient.post(`/tareas/periodo/${periodoId}/completar`), onSuccess: invalidate, onError: (err: unknown) => { const e = err as { response?: { data?: { message?: string } } }; alert(e.response?.data?.message || 'No se pudo marcar como completada'); }, }); const descompletarMutation = useMutation({ mutationFn: async (periodoId: string) => apiClient.delete(`/tareas/periodo/${periodoId}/completar`), onSuccess: invalidate, }); const handleEdit = (t: Tarea) => { setEditingId(t.id); setForm({ nombre: t.nombre, descripcion: t.descripcion ?? '', recurrencia: t.recurrencia, diaSemana: t.diaSemana ?? 5, diaMes: t.diaMes ?? 10, soloSupervisorCompleta: t.soloSupervisorCompleta, }); setShowForm(true); }; const handleNew = () => { setEditingId(null); setForm(EMPTY_FORM); setShowForm(true); }; if (!contribuyenteId) { return ( Selecciona un contribuyente para gestionar sus tareas. ); } const tareas = tareasQuery.data ?? []; const isWeekly = form.recurrencia === 'semanal' || form.recurrencia === 'quincenal'; return (
{tareas.length === 0 && ( )}
{tareasQuery.isLoading ? (

Cargando...

) : tareas.length === 0 ? ( No hay tareas configuradas. Usa "Generar recomendaciones" para crear las 4 tareas default (estados de cuenta, conciliación, contabilización, revisión fiscal preliminar). ) : (
{tareas.map(t => { const p = t.periodoActual; const fl = p ? new Date(p.fechaLimite) : null; const today = new Date(); today.setHours(0, 0, 0, 0); const atrasada = !!fl && !p?.completada && fl < today; const recurrenciaLabel = RECURRENCIAS.find(r => r.value === t.recurrencia)?.label; const cuandoLabel = (t.recurrencia === 'semanal' || t.recurrencia === 'quincenal') ? DIAS_SEMANA.find(d => d.value === t.diaSemana)?.label : `día ${t.diaMes}`; return (
{t.nombre} {t.soloSupervisorCompleta && ( Supervisor )} {atrasada && ( Atrasada )}
{t.descripcion && (

{t.descripcion}

)}

{recurrenciaLabel} · {cuandoLabel} {fl && ` · vence ${fl.toLocaleDateString('es-MX', { day: 'numeric', month: 'short' })}`}

); })}
)} {editingId ? 'Editar tarea' : 'Nueva tarea'}
setForm(f => ({ ...f, nombre: e.target.value }))} />
setForm(f => ({ ...f, descripcion: e.target.value }))} />
{isWeekly ? ( ) : ( setForm(f => ({ ...f, diaMes: parseInt(e.target.value, 10) || 1 }))} /> )}
); }