import { useEffect, useState } from 'react'; import { useConfig } from '../hooks/useConfig'; import { DataProvider } from '../context/DataContext'; import { useDataContext } from '../hooks/useDataContext'; import { usePaginatedList } from '../hooks/usePaginatedList'; import CustomContainer from '../components/CustomContainer'; import ContentWrapper from '../components/ContentWrapper'; import LoadingIcon from '../components/LoadingIcon'; import SearchToolbar from '../components/SearchToolbar'; import PaginatedCardGrid from '../components/PaginatedCardGrid'; import PDFModal from '../components/PDFModal'; import IngresoCard from '../components/Ingresos/IngresoCard'; import IngresosFilter from '../components/Ingresos/IngresosFilter'; import { IngresosPDF } from '../components/Ingresos/IngresosPDF'; import { CONSTANTS } from '../util/constants'; import { errorParser } from '../util/parsers/errorParser'; import '../css/Ingresos.css'; import CustomModal from '../components/CustomModal'; import { Button } from 'react-bootstrap'; const PAGE_SIZE = 10; const Ingresos = () => { const { config, configLoading } = useConfig(); if (configLoading) return

; const reqConfig = { baseUrl: config.apiConfig.baseUrl + config.apiConfig.endpoints.incomes.allWithNames, rawUrl: config.apiConfig.baseUrl + config.apiConfig.endpoints.incomes.all, membersUrl: config.apiConfig.baseUrl + config.apiConfig.endpoints.members.all, params: { _sort: 'createdAt', _order: 'desc' } }; return ( ); }; const IngresosContent = ({ reqConfig }) => { const { data, dataLoading, dataError, getData, postData, putData, deleteData } = useDataContext(); const [showPDFModal, setShowPDFModal] = useState(false); const [creatingIngreso, setCreatingIngreso] = useState(false); const [tempIngreso, setTempIngreso] = useState(null); const [error, setError] = useState(null); const [deleteTargetId, setDeleteTargetId] = useState(null); const [members, setMembers] = useState([]); useEffect(() => { const fetchMembers = async () => { try { const membersData = await getData(reqConfig.membersUrl, { params: { _sort: 'name', _order: 'asc' } }); setMembers(membersData.data); } catch (err) { setError(errorParser(err)); } }; fetchMembers(); }, [reqConfig.membersUrl, getData]); const { filtered, searchTerm, setSearchTerm, filters, setFilters } = usePaginatedList({ data, pageSize: PAGE_SIZE, initialFilters: { todos: true, banco: true, caja: true, semestral: true, anual: true }, filterFn: (ingreso, filters) => { if (filters.todos) return true; const { banco, caja, semestral, anual } = filters; const typeMatch = (banco && ingreso.type === CONSTANTS.PAYMENT_TYPE_BANK) || (caja && ingreso.type === CONSTANTS.PAYMENT_TYPE_CASH); const freqMatch = (semestral && ingreso.frequency === CONSTANTS.PAYMENT_FREQUENCY_BIYEARLY) || (anual && ingreso.frequency === CONSTANTS.PAYMENT_FREQUENCY_YEARLY); const typeFilters = [banco, caja].filter(Boolean).length; const freqFilters = [semestral, anual].filter(Boolean).length; if (typeFilters > 0 && freqFilters > 0) return typeMatch && freqMatch; if (typeFilters > 0) return typeMatch; if (freqFilters > 0) return freqMatch; return false; }, searchFn: (ingreso, term) => { const normalized = term.toLowerCase(); return ingreso.concept?.toLowerCase().includes(normalized) || String(ingreso.memberNumber).includes(normalized) || ingreso.displayName?.toLowerCase().includes(normalized); } }); const handleCreate = () => { setCreatingIngreso(true); setTempIngreso({ incomeId: null, memberNumber: 0, concept: '', amount: 0.0, frequency: CONSTANTS.PAYMENT_FREQUENCY_YEARLY, type: CONSTANTS.PAYMENT_TYPE_BANK }); document.querySelector('.cards-grid')?.scrollTo({ top: 0, behavior: 'smooth' }); }; const handleCancelCreate = () => { setCreatingIngreso(false); setTempIngreso(null); setError(null); }; const handleCreateSubmit = async (nuevo) => { try { await postData(reqConfig.rawUrl, nuevo); setError(null); setCreatingIngreso(false); setTempIngreso(null); } catch (err) { setTempIngreso({ ...nuevo }); setError(errorParser(err)); } }; const handleEditSubmit = async (editado, id) => { try { await putData(`${reqConfig.rawUrl}/${id}`, editado); setError(null); } catch (err) { setError(errorParser(err)); } }; const handleDelete = async (id) => { setDeleteTargetId(id); }; if (dataLoading) return

; if (dataError) return

{dataError}

; return (

Lista de Ingresos


} onCreate={handleCreate} onPDF={() => setShowPDFModal(true)} /> ( setError(null)} members={members} /> )} renderCard={(income) => ( handleEditSubmit(data, id)} onDelete={() => handleDelete(income.incomeId)} error={error} onClearError={() => setError(null)} /> )} /> setShowPDFModal(false)} title="Vista previa del PDF"> setDeleteTargetId(null)} >

¿Estás seguro de que quieres eliminar el ingreso?

); }; export default Ingresos;