'use client'; import { useState, useEffect, useCallback } from 'react'; import { useQueryClient } from '@tanstack/react-query'; import { Button, Card, CardContent, CardHeader, CardTitle, Input, Label, Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, cn, } from '@horux/shared-ui'; import { useContribuyenteStore } from '@/stores/contribuyente-store'; import { apiClient } from '@/lib/api/client'; import { Header } from '@/components/layouts/header'; import { TareasTab } from '@/components/obligaciones/tareas-tab'; import { Plus, Trash2, RotateCcw, Sparkles, ChevronDown, Building2 } from 'lucide-react'; interface Obligacion { id: string; catalogoId: string | null; nombre: string; fundamento: string | null; frecuencia: string | null; fechaLimite: string | null; categoria: string | null; activa: boolean; esRecomendada: boolean; esCustom: boolean; } interface CatalogoItem { id: string; nombre: string; fundamento: string; frecuencia: string; fechaLimite: string; categoria: string; aplica: string; } export default function ObligacionesPage() { const queryClient = useQueryClient(); const { selectedContribuyenteId, selectedContribuyenteRfc, selectedContribuyenteNombre } = useContribuyenteStore(); const [obligaciones, setObligaciones] = useState([]); const [catalogo, setCatalogo] = useState([]); const [loading, setLoading] = useState(false); const [showAdd, setShowAdd] = useState(false); const [showRemoved, setShowRemoved] = useState(false); const [addMode, setAddMode] = useState<'catalogo' | 'custom'>('catalogo'); const [customForm, setCustomForm] = useState({ nombre: '', fundamento: '', frecuencia: '', fechaLimite: '', categoria: '', }); const [selectedCatalogoId, setSelectedCatalogoId] = useState(''); const [activeTab, setActiveTab] = useState<'obligaciones' | 'tareas'>('obligaciones'); const fetchObligaciones = useCallback(async () => { if (!selectedContribuyenteId) return; setLoading(true); try { const { data } = await apiClient.get( `/contribuyentes/${selectedContribuyenteId}/obligaciones` ); setObligaciones(data.data); } catch { setObligaciones([]); } finally { setLoading(false); } }, [selectedContribuyenteId]); useEffect(() => { fetchObligaciones(); }, [fetchObligaciones]); useEffect(() => { apiClient .get('/contribuyentes/catalogo-obligaciones') .then(({ data }) => setCatalogo(data.data)) .catch(() => {}); }, []); const handleInit = async () => { if (!selectedContribuyenteId || !selectedContribuyenteRfc) return; try { await apiClient.post( `/contribuyentes/${selectedContribuyenteId}/obligaciones/init`, { rfc: selectedContribuyenteRfc, regimenes: [], tieneNomina: false, } ); await fetchObligaciones(); invalidateRelated(); } catch (err: unknown) { const e = err as { response?: { data?: { message?: string } } }; alert(e.response?.data?.message || 'Error al generar recomendaciones'); } }; const handleAdd = async () => { if (!selectedContribuyenteId) return; try { if (addMode === 'catalogo' && selectedCatalogoId) { const item = catalogo.find((c) => c.id === selectedCatalogoId); if (!item) return; await apiClient.post(`/contribuyentes/${selectedContribuyenteId}/obligaciones`, { catalogoId: item.id, nombre: item.nombre, fundamento: item.fundamento, frecuencia: item.frecuencia, fechaLimite: item.fechaLimite, categoria: item.categoria, }); } else if (addMode === 'custom' && customForm.nombre) { await apiClient.post( `/contribuyentes/${selectedContribuyenteId}/obligaciones`, customForm ); } setShowAdd(false); setSelectedCatalogoId(''); setCustomForm({ nombre: '', fundamento: '', frecuencia: '', fechaLimite: '', categoria: '' }); await fetchObligaciones(); } catch (err: unknown) { const e = err as { response?: { data?: { message?: string } } }; alert(e.response?.data?.message || 'Error al agregar obligación'); } }; const invalidateRelated = () => { queryClient.invalidateQueries({ queryKey: ['alertas-manuales'] }); queryClient.invalidateQueries({ queryKey: ['alertas-automaticas'] }); queryClient.invalidateQueries({ queryKey: ['alertas'] }); queryClient.invalidateQueries({ queryKey: ['eventos'] }); }; const handleRemove = async (id: string) => { await apiClient.delete( `/contribuyentes/${selectedContribuyenteId}/obligaciones/${id}` ); await fetchObligaciones(); invalidateRelated(); }; const handleRestore = async (id: string) => { await apiClient.post( `/contribuyentes/${selectedContribuyenteId}/obligaciones/${id}/restore` ); await fetchObligaciones(); invalidateRelated(); }; if (!selectedContribuyenteId) { return (

Selecciona un contribuyente

Usa el selector de RFCs en el header para elegir un contribuyente.

); } const activas = obligaciones.filter((o) => o.activa); const removidas = obligaciones.filter((o) => !o.activa); const categorias = [...new Set(activas.map((o) => o.categoria || 'Sin categoría'))]; const frecuenciaBadge = (f: string | null) => { const colors: Record = { mensual: 'bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300', bimestral: 'bg-purple-100 text-purple-700 dark:bg-purple-900 dark:text-purple-300', trimestral: 'bg-orange-100 text-orange-700 dark:bg-orange-900 dark:text-orange-300', anual: 'bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300', eventual: 'bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-300', }; return f ? ( {f} ) : null; }; return ( <>
{/* Subtítulo */}

{selectedContribuyenteNombre} — {selectedContribuyenteRfc}

{/* Tabs */}
{activeTab === 'tareas' ? ( ) : ( <>
{activas.length === 0 && ( )}
{/* Active obligations */} {loading ? (

Cargando...

) : activas.length === 0 ? (

Sin obligaciones configuradas

Importa las obligaciones desde la Constancia de Situación Fiscal (CSF) o agrega manualmente.

) : (
{categorias.map((cat) => (

{cat}

{activas .filter((o) => (o.categoria || 'Sin categoría') === cat) .map((ob) => (

{ob.nombre}

{frecuenciaBadge(ob.frecuencia)} {ob.esRecomendada && ( ★ Recomendada )} {ob.esCustom && ( ✎ Custom )}
{ob.fundamento && (

{ob.fundamento}

)} {ob.fechaLimite && (

📅 {ob.fechaLimite}

)}
))}
))}
)} {/* Removed obligations */} {removidas.length > 0 && (
{showRemoved && (
{removidas.map((ob) => (

{ob.nombre}

{ob.categoria}

))}
)}
)} {/* Add dialog */} Agregar obligación fiscal
{addMode === 'catalogo' ? (
{catalogo.length === 0 ? (

Cargando catálogo...

) : ( catalogo.map((item) => { const yaAgregada = obligaciones.some( (o) => o.catalogoId === item.id && o.activa ); return ( ); }) )}
) : (
setCustomForm((p) => ({ ...p, nombre: e.target.value })) } placeholder="Nombre de la obligación" />
setCustomForm((p) => ({ ...p, fundamento: e.target.value })) } placeholder="Art. X LISR" />
setCustomForm((p) => ({ ...p, frecuencia: e.target.value })) } placeholder="mensual, anual..." />
setCustomForm((p) => ({ ...p, fechaLimite: e.target.value })) } placeholder="Día 17 del mes..." />
setCustomForm((p) => ({ ...p, categoria: e.target.value })) } placeholder="Federal mensual, Anual..." />
)}
)}
); }