Files
huertos-bellavista-web/src/pages/Solicitudes.jsx

148 lines
4.7 KiB
JavaScript

import { useConfig } from '../hooks/useConfig';
import { DataProvider } from '../context/DataContext';
import { useDataContext } from '../hooks/useDataContext';
import { usePaginatedList } from '../hooks/usePaginatedList';
import { useState } from 'react';
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 SolicitudCard from '../components/Solicitudes/SolicitudCard';
import { Button } from 'react-bootstrap';
import CustomModal from '../components/CustomModal';
const PAGE_SIZE = 10;
const Solicitudes = () => {
const { config, configLoading } = useConfig();
if (configLoading || !config) return <p className="text-center my-5"><LoadingIcon /></p>;
const reqConfig = {
baseUrl: config.apiConfig.baseUrl + config.apiConfig.endpoints.requests.allWithPreUsers,
rawUrl: config.apiConfig.baseUrl + config.apiConfig.endpoints.requests.all,
acceptUrl: config.apiConfig.baseUrl + config.apiConfig.endpoints.requests.accept,
rejectUrl: config.apiConfig.baseUrl + config.apiConfig.endpoints.requests.reject,
params: {}
};
return (
<DataProvider config={reqConfig}>
<SolicitudesContent reqConfig={reqConfig} />
</DataProvider>
);
};
const SolicitudesContent = ({ reqConfig }) => {
const { data, dataLoading, dataError, putData, deleteData } = useDataContext();
const [deleteTargetId, setDeleteTargetId] = useState(null);
const {
filtered,
searchTerm,
setSearchTerm
} = usePaginatedList({
data,
pageSize: PAGE_SIZE,
searchFn: (entry, term) => {
const normalized = term.toLowerCase();
return (
entry.preDisplayName?.toLowerCase().includes(normalized) ||
entry.preDni?.toLowerCase().includes(normalized) ||
entry.preEmail?.toLowerCase().includes(normalized) ||
String(entry.prePhone).includes(normalized)
);
},
sortFn: (a, b) => a.status - b.status
});
const handleAccept = async (entry) => {
const url = reqConfig.acceptUrl.replace(":requestId", entry.requestId);
try {
await putData(url, {});
} catch (err) {
console.error("❌ Error al aceptar solicitud:", err.message);
}
};
const handleReject = async (entry) => {
const url = reqConfig.rejectUrl.replace(":requestId", entry.requestId);
try {
await putData(url, {});
} catch (err) {
console.error("❌ Error al rechazar solicitud:", err.message);
}
};
const handleDelete = async (id) => {
setDeleteTargetId(id);
}
if (dataLoading) return <p className="text-center my-5"><LoadingIcon /></p>;
if (dataError) return <p className="text-danger text-center my-5">{dataError}</p>;
return (
<CustomContainer>
<ContentWrapper>
<div className="d-flex flex-column align-items-center m-0 p-0">
<h1 className='section-title me-auto'>Panel de Solicitudes</h1>
<h5 className='me-auto'>Es necesario asignarle manualmente una contraseña al socio en caso de
aceptar su solicitud tanto de alta como de nuevo colaborador.</h5>
</div>
<hr className="section-divider" />
<SearchToolbar
searchTerm={searchTerm}
onSearchChange={setSearchTerm}
hideCreate
hidePDF
/>
<PaginatedCardGrid
items={filtered}
renderCard={(entry) => (
<SolicitudCard
key={entry.requestId}
data={entry}
onAccept={() => handleAccept(entry)}
onReject={() => handleReject(entry)}
onDelete={handleDelete}
/>
)}
/>
<CustomModal
title="Confirmar eliminación"
show={deleteTargetId !== null}
onClose={() => setDeleteTargetId(null)}
>
<p className='p-3'>¿Estás seguro de que quieres eliminar la solicitud manualmente?</p>
<div className="d-flex justify-content-end gap-2 mt-3 p-3">
<Button variant="secondary" onClick={() => setDeleteTargetId(null)}>Cancelar</Button>
<Button
variant="danger"
onClick={async () => {
try {
await deleteData(`${reqConfig.rawUrl}/${deleteTargetId}`);
setSearchTerm("");
setDeleteTargetId(null);
} catch (err) {
console.error(err);
}
}}
>
Confirmar
</Button>
</div>
</CustomModal>
</ContentWrapper>
</CustomContainer>
);
};
export default Solicitudes;