diff --git a/src/components/Solicitudes/PreUserForm.jsx b/src/components/Solicitudes/NewUserForm.jsx similarity index 92% rename from src/components/Solicitudes/PreUserForm.jsx rename to src/components/Solicitudes/NewUserForm.jsx index f02fd3f..59f21f6 100644 --- a/src/components/Solicitudes/PreUserForm.jsx +++ b/src/components/Solicitudes/NewUserForm.jsx @@ -6,12 +6,12 @@ import PropTypes from 'prop-types'; import { generateSecurePassword } from '../../util/passwordGenerator'; -const PreUserForm = ({ onSubmit, userType, plotNumber, errors = {} }) => { +const NewUserForm = ({ onSubmit, userType, plotNumber, errors = {} }) => { const { getData } = useDataContext(); const fetchedOnce = useRef(false); const [form, setForm] = useState({ - userName: '', + username: '', password: generateSecurePassword(8), displayName: '', dni: '', @@ -53,10 +53,10 @@ const PreUserForm = ({ onSubmit, userType, plotNumber, errors = {} }) => { const nuevoUsername = trimmedName ? trimmedName.split(' ')[0].toLowerCase() : ""; - if (form.userName !== nuevoUsername) { - setForm(prev => ({ ...prev, userName: nuevoUsername })); + if (form.username !== nuevoUsername) { + setForm(prev => ({ ...prev, username: nuevoUsername })); } - }, [form.memberNumber, form.displayName, form.userName]); + }, [form.memberNumber, form.displayName, form.username]); const handleChange = (e) => { const { name, value, type } = e.target; @@ -86,7 +86,7 @@ const PreUserForm = ({ onSubmit, userType, plotNumber, errors = {} }) => { {[ { label: 'Nombre completo', name: 'displayName', type: 'text', required: true }, - { label: 'Nombre de usuario', name: 'userName', type: 'text', required: true }, + { label: 'Nombre de usuario', name: 'username', type: 'text', required: true }, { label: 'DNI', name: 'dni', type: 'text', required: true, maxLength: 9 }, { label: 'Teléfono', name: 'phone', type: 'tel', required: true }, { label: 'Correo electrónico', name: 'email', type: 'email', required: true }, @@ -139,11 +139,11 @@ const PreUserForm = ({ onSubmit, userType, plotNumber, errors = {} }) => { ); }; -PreUserForm.propTypes = { +NewUserForm.propTypes = { userType: PropTypes.number.isRequired, plotNumber: PropTypes.number.isRequired, onSubmit: PropTypes.func.isRequired, errors: PropTypes.object }; -export default PreUserForm; +export default NewUserForm; diff --git a/src/components/Solicitudes/SolicitudCard.jsx b/src/components/Solicitudes/SolicitudCard.jsx index c7dac8e..ac59d98 100644 --- a/src/components/Solicitudes/SolicitudCard.jsx +++ b/src/components/Solicitudes/SolicitudCard.jsx @@ -15,117 +15,100 @@ const MotionCard = _motion.create(Card); const parseDate = (date) => { if (!date) return 'NO'; const d = new Date(date); - return `${d.getDate().toString().padStart(2, '0')}/${(d.getMonth() + 1).toString().padStart(2, '0')}/${d.getFullYear()}`; + return `${d.getDate().toString().padStart(2, '0')}/${(d.getMonth() + 1) + .toString().padStart(2, '0')}/${d.getFullYear()}`; }; -const getTipoSolicitud = (tipo) => ['Alta', 'Baja', 'Añadir Colaborador', 'Quitar Colaborador', 'Añadir parcela invernadero', 'Dejar parcela invernadero'][tipo] ?? 'Desconocido'; -const getEstadoSolicitud = (estado) => ['Pendiente', 'Aceptada', 'Rechazada'][estado] ?? 'Desconocido'; +const getTipoSolicitud = (tipo) => + ['Alta', 'Baja', 'Añadir Colaborador', 'Quitar Colaborador', 'Añadir parcela invernadero', 'Dejar parcela invernadero'][tipo] + ?? 'Desconocido'; + +const getEstadoSolicitud = (estado) => + ['Pendiente', 'Aceptada', 'Rechazada'][estado] ?? 'Desconocido'; const getPFP = (tipo) => { const base = '/images/icons/'; const map = { + 0: 'list.svg', 1: 'farmer.svg', 2: 'green_house.svg', - 0: 'list.svg', - 3: 'join.svg', - 4: 'subvencion4.svg', - 5: 'programmer.svg' + 3: 'join.svg' }; return base + (map[tipo] || 'farmer.svg'); }; const renderDescripcionSolicitud = (data, onProfile) => { - console.log(data); + const m = data.metadata; switch (data.type) { case 0: - if (data.requestedByName) { - return `${data.requestedByName} quiere darse de alta.`; - } else if (data.status !== 1 && data.preDisplayName) { - return `${data.preDisplayName} quiere darse de alta.`; - } else if (data.status !== 1) { - return `Alguien quiere darse de alta.`; - } else { - return `Se ha aceptado esta solicitud de alta.`; - } + return data.status === 1 + ? 'Se ha aceptado esta solicitud de alta.' + : `${m?.displayName ?? 'Alguien'} quiere darse de alta.`; case 1: return onProfile - ? "Has solicitado darte de baja." - : data.requestedByName - ? `${data.requestedByName} quiere darse de baja.` - : data.status !== 1 - ? `Alguien quiere darse de baja.` - : `Se ha aceptado esta solicitud de baja.`; + ? 'Has solicitado darte de baja.' + : `${m?.displayName ?? 'Alguien'} quiere darse de baja.`; case 2: if (onProfile) { - switch (data.status) { - case 0: return "Has solicitado añadir un colaborador."; - case 1: return "Tu solicitud de colaborador ha sido aceptada."; - case 2: return "Tu solicitud de colaborador ha sido rechazada."; - default: return "Solicitud de colaborador desconocida."; - } - } else { - switch (data.status) { - case 0: - return data.requestedByName - ? `${data.requestedByName} quiere añadir a ${data.preDisplayName || "un colaborador"} como colaborador.` - : `Alguien quiere añadir a ${data.preDisplayName || "un colaborador"} como colaborador.`; - case 1: - return `La solicitud de colaborador de ${data.requestedByName || "alguien"} ha sido aceptada.`; - case 2: - return `La solicitud de colaborador de ${data.requestedByName || "alguien"} ha sido rechazada.`; - default: - return "Solicitud de colaborador desconocida."; - } + return [ + 'Has solicitado añadir un colaborador.', + 'Tu solicitud de colaborador ha sido aceptada.', + 'Tu solicitud de colaborador ha sido rechazada.' + ][data.status] ?? 'Solicitud de colaborador.'; } + return data.status === 0 + ? `${m?.displayName ?? 'Alguien'} quiere añadir un colaborador.` + : `La solicitud de colaborador ha sido ${ + data.status === 1 ? 'aceptada' : 'rechazada' + }.`; case 3: - return onProfile - ? "Has solicitado quitar tu colaborador." - : data.requestedByName - ? `${data.requestedByName} quiere quitar su colaborador.` - : data.status !== 1 - ? `Alguien quiere quitar su colaborador.` - : `Se ha aceptado esta solicitud de baja de colaborador.`; + return `${m?.displayName ?? 'Alguien'} quiere quitar su colaborador.`; case 4: - return onProfile - ? "Has solicitado una parcela en el invernadero." - : data.requestedByName - ? `${data.requestedByName} quiere una parcela en el invernadero.` - : data.status !== 1 - ? `Alguien quiere una parcela en el invernadero.` - : `Se ha aceptado esta solicitud de parcela en el invernadero.`; + return `${m?.displayName ?? 'Alguien'} quiere una parcela en el invernadero.`; case 5: - return onProfile - ? "Has solicitado dejar tu parcela del invernadero." - : data.requestedByName - ? `${data.requestedByName} quiere dejar su parcela del invernadero.` - : data.status !== 1 - ? `Alguien quiere dejar su parcela del invernadero.` - : `Se ha aceptado esta solicitud de salida del invernadero.`; + return `${m?.displayName ?? 'Alguien'} quiere dejar su parcela del invernadero.`; default: - return "Tipo de solicitud desconocido."; + return 'Tipo de solicitud desconocido.'; } }; -const SolicitudCard = ({ data, onAccept, onReject, onDelete, editable = true, onProfile = false }) => { - const handleDelete = () => typeof onDelete === "function" && onDelete(data.requestId); +const SolicitudCard = ({ + data, + onAccept, + onReject, + onDelete, + editable = true, + onProfile = false +}) => { + const m = data.metadata; + + const handleDelete = () => + typeof onDelete === 'function' && onDelete(data.requestId); return (
- PFP + PFP
- Solicitud #{data.idx} - {getTipoSolicitud(data.type)} + Solicitud #{data.requestId?.slice(0, 8)} – {getTipoSolicitud(data.type)} - Estado: {getEstadoSolicitud(data.status)} + + Estado: {getEstadoSolicitud(data.status)} +
@@ -133,10 +116,18 @@ const SolicitudCard = ({ data, onAccept, onReject, onDelete, editable = true, on }> + icon={} + > {({ closeDropdown }) => ( -
{ handleDelete(); closeDropdown(); }}> - Eliminar +
{ + handleDelete(); + closeDropdown(); + }} + > + + Eliminar
)} @@ -157,27 +148,73 @@ const SolicitudCard = ({ data, onAccept, onReject, onDelete, editable = true, on - {data.preDisplayName && ( + {m && ( <> - Datos del futuro socio + + Datos asociados a la solicitud + + - Nombre: {data.preDisplayName} - DNI: {data.preDni} - Teléfono: {data.prePhone} - Email: {data.preEmail} - Dirección: {data.preAddress ?? 'NO'} - Ciudad: {data.preCity ?? 'NO'} ({data.preZipCode ?? 'NO'}) - Nº socio: {data.preMemberNumber ?? 'NO'} | Nº huerto: {data.prePlotNumber ?? 'NO'} - Tipo: {['Lista de Espera', 'Hortelano', 'Hortelano + Invernadero', 'Colaborador'][data.preType]} - Rol: {['Usuario', 'Admin', 'Desarrollador'][data.preRole]} + + + Nombre: {m.displayName} + + + + + DNI: {m.dni} + + + + + Teléfono: {m.phone ?? 'NO'} + + + + + Email: {m.email} + + + + + Usuario: {m.username} + + + + + Dirección: {m.address ?? 'NO'} + + + + + Ciudad:{' '} + + {m.city ?? 'NO'} ({m.zipCode ?? 'NO'}) + + + + + + Nº socio: {m.memberNumber ?? 'NO'} | Nº huerto:{' '} + {m.plotNumber ?? 'NO'} + + + + + Tipo: {['Lista de espera', 'Hortelano', 'Hortelano + Invernadero', 'Colaborador'][m.type]} + )} {editable && data.status === 0 && (
- - + +
)} @@ -194,4 +231,4 @@ SolicitudCard.propTypes = { onProfile: PropTypes.bool }; -export default SolicitudCard; \ No newline at end of file +export default SolicitudCard; diff --git a/src/pages/ListaEspera.jsx b/src/pages/ListaEspera.jsx index f1d5d39..633dfaf 100644 --- a/src/pages/ListaEspera.jsx +++ b/src/pages/ListaEspera.jsx @@ -10,7 +10,7 @@ import { DateParser } from '../util/parsers/dateParser'; import CustomContainer from '../components/CustomContainer'; import ContentWrapper from '../components/ContentWrapper'; import LoadingIcon from '../components/LoadingIcon'; -import PreUserForm from '../components/Solicitudes/PreUserForm'; +import NewUserForm from '../components/Solicitudes/NewUserForm'; import CustomModal from '../components/CustomModal'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faPencil } from '@fortawesome/free-solid-svg-icons'; @@ -40,7 +40,7 @@ const ListaEsperaContent = ({ reqConfig }) => { const { data, dataLoading, dataError, postData, postDataValidated } = useDataContext(); const [showWelcomeModal, setShowWelcomeModal] = useState(false); - const [showPreUserFormModal, setShowPreUserFormModal] = useState(false); + const [showNewUserFormModal, setShowNewUserFormModal] = useState(false); const [showConfirmationModal, setShowConfirmationModal] = useState(false); const [validationErrors, setValidationErrors] = useState({}); @@ -82,7 +82,7 @@ const ListaEsperaContent = ({ reqConfig }) => { requestId }); - setShowPreUserFormModal(false); + setShowNewUserFormModal(false); setShowConfirmationModal(true); } catch (err) { setValidationErrors({ general: "Error inesperado al enviar la solicitud" }); @@ -92,7 +92,7 @@ const ListaEsperaContent = ({ reqConfig }) => { const handleOpenFormModal = () => { setValidationErrors({}); setShowWelcomeModal(false); - setShowPreUserFormModal(true); + setShowNewUserFormModal(true); }; if (dataLoading) return

; @@ -136,13 +136,13 @@ const ListaEsperaContent = ({ reqConfig }) => { { - setShowPreUserFormModal(false); + setShowNewUserFormModal(false); setValidationErrors({}); }} > - { baseUrl: `${config.apiConfig.baseUrl}${config.apiConfig.endpoints.users.me}`, myIncomesUrl: buildUrl(config.apiConfig.baseUrl, config.apiConfig.endpoints.incomes.mine), requestUrl: buildUrl(config.apiConfig.baseUrl, config.apiConfig.endpoints.requests.all), - preUsersUrl: buildUrl(config.apiConfig.baseUrl, config.apiConfig.endpoints.preUsers.all), - requestWithPreUserUrl: buildUrl(config.apiConfig.baseUrl, config.apiConfig.endpoints.requests.withPreUser), - preUserValidationUrl: buildUrl(config.apiConfig.baseUrl, config.apiConfig.endpoints.preUsers.validate), myRequestsUrl: buildUrl(config.apiConfig.baseUrl, config.apiConfig.endpoints.requests.mine), changePasswordUrl: buildUrl(config.apiConfig.coreUrl, config.apiConfig.endpoints.auth.changePassword), loginValidateUrl: buildUrl(config.apiConfig.coreUrl, config.apiConfig.endpoints.auth.loginValidate), @@ -89,8 +86,10 @@ const PerfilContent = ({ config }) => { const { logout } = useAuth(); const identity = JSON.parse(localStorage.getItem("identity")); + const myRequests = data?.requests ?? []; const incomes = data?.payments ?? []; + const hasCollaborator = data?.hasCollaborator ?? false; const hasCollaboratorRequest = data?.hasCollaboratorRequest ?? false; const hasGreenHouse = data?.hasGreenhouse ?? false; @@ -101,6 +100,44 @@ const PerfilContent = ({ config }) => { const [feedbackModal, setFeedbackModal] = useState(null); const closeFeedback = () => setFeedbackModal(null); + const baseMetadata = { + displayName: identity.user.displayName, + dni: identity.metadata.dni, + phone: identity.metadata.phone, + email: identity.account.email, + memberNumber: identity.metadata.memberNumber, + plotNumber: identity.metadata.plotNumber, + type: identity.metadata.type, + role: identity.metadata.role + }; + + const sendSimpleRequest = async (type) => { + const requestOf = type == 1 ? "baja" : type == 2 ? "adición de colaborador" : + type == 3 ? "eliminación de colaborador" : type == 4 ? "adición de invernadero" : + type == 5 ? "eliminación de invernadero" : "desconocido"; + try { + await postData(config.requestUrl, { + type, + status: CONSTANTS.REQUEST_PENDING, + userId: identity.user.userId, + metadata: baseMetadata + }); + setFeedbackModal({ + title: 'Solicitud enviada', + message: `Se ha enviado la solicitud de ${requestOf} correctamente.`, + variant: 'success', + onClick: closeFeedback + }); + } catch (err) { + setFeedbackModal({ + title: 'Error', + message: err.message, + variant: 'danger', + onClick: closeFeedback + }); + } + }; + const [validationErrors, setValidationErrors] = useState({}); const [newPasswordData, setNewPasswordData] = useState({ @@ -113,75 +150,6 @@ const PerfilContent = ({ config }) => { const [showNew, setShowNew] = useState(false); const [showConfirm, setShowConfirm] = useState(false); - const handleRequestUnregister = async () => { - try { - await postData(config.requestUrl, { - type: CONSTANTS.REQUEST_TYPE_UNREGISTER, - status: CONSTANTS.REQUEST_PENDING, - requestedBy: identity.user.userId - }); - setFeedbackModal({ - title: 'Solicitud enviada', - message: 'Se ha enviado la solicitud de baja correctamente.', - variant: 'success', - onClick: closeFeedback - }); - } catch (err) { - setFeedbackModal({ - title: 'Error', - message: err.message, - variant: 'danger', - onClick: closeFeedback - }); - } - }; - - const handleRequestGreenHouse = async () => { - try { - await postData(config.requestUrl, { - type: CONSTANTS.REQUEST_TYPE_ADD_GREENHOUSE, - status: CONSTANTS.REQUEST_PENDING, - requestedBy: identity.user.userId - }); - setFeedbackModal({ - title: 'Solicitud enviada', - message: 'Se ha enviado la solicitud de invernadero correctamente.', - variant: 'success', - onClick: closeFeedback - }); - } catch (err) { - setFeedbackModal({ - title: 'Error', - message: err.message, - variant: 'danger', - onClick: closeFeedback - }); - } - }; - - const handleRemoveGreenHouse = async () => { - try { - await postData(config.requestUrl, { - type: CONSTANTS.REQUEST_TYPE_REMOVE_GREENHOUSE, - status: CONSTANTS.REQUEST_PENDING, - requestedBy: identity.user.userId - }); - setFeedbackModal({ - title: 'Solicitud enviada', - message: 'Se ha enviado la solicitud de baja de invernadero correctamente.', - variant: 'success', - onClick: closeFeedback - }); - } catch (err) { - setFeedbackModal({ - title: 'Error', - message: err.message, - variant: 'danger', - onClick: closeFeedback - }); - } - }; - const handleChange = (e) => { setNewPasswordData({ ...newPasswordData, @@ -263,27 +231,42 @@ const PerfilContent = ({ config }) => { {({ closeDropdown }) => ( <> {!hasGreenHouse && !hasGreenHouseRequest && ( -
{ handleRequestGreenHouse(); closeDropdown(); }}> +
{ + sendSimpleRequest(CONSTANTS.REQUEST_TYPE_ADD_GREENHOUSE); + closeDropdown(); + }}> Solicitar invernadero
)} {!hasCollaborator && !hasCollaboratorRequest && ( -
{ setShowAddCollaboratorModal(true); closeDropdown(); }}> +
{ + setShowAddCollaboratorModal(true); + closeDropdown(); + }}> Añadir un colaborador
)}
{hasGreenHouse && !hasGreenHouseRequest && ( -
{ handleRemoveGreenHouse(); closeDropdown(); }}> +
{ + sendSimpleRequest(CONSTANTS.REQUEST_TYPE_REMOVE_GREENHOUSE); + closeDropdown(); + }}> Dejar invernadero
)} {hasCollaborator && !hasCollaboratorRequest && ( -
{ setShowRemoveCollaboratorModal(true); closeDropdown(); }}> +
{ + setShowRemoveCollaboratorModal(true); + closeDropdown(); + }}> Quitar colaborador
)} -
{ handleRequestUnregister(); closeDropdown(); }}> +
{ + sendSimpleRequest(CONSTANTS.REQUEST_TYPE_UNREGISTER); + closeDropdown(); + }}> Darse de baja
@@ -431,48 +414,34 @@ const PerfilContent = ({ config }) => { setValidationErrors({}); }} > - { - setValidationErrors({}); + await postData(config.requestUrl, { + type: CONSTANTS.REQUEST_TYPE_ADD_COLLABORATOR, + status: CONSTANTS.REQUEST_PENDING, + userId: identity.user.userId, + metadata: { + displayName: formData.displayName, + dni: formData.dni, + phone: formData.phone, + email: formData.email, + memberNumber: formData.memberNumber, + plotNumber: formData.plotNumber, + type: formData.type, + role: formData.role + } + }); - const { _, errors } = await postDataValidated(config.preUserValidationUrl, formData); - if (errors) { - setValidationErrors(errors); - return; - } - - try { - await postData(config.requestWithPreUserUrl, { - request: { - type: CONSTANTS.REQUEST_TYPE_ADD_COLLABORATOR, - status: CONSTANTS.REQUEST_PENDING, - requestedBy: identity.user.userId - }, - preUser: { - ...formData - } - }); - - setValidationErrors({}); - setShowAddCollaboratorModal(false); - setFeedbackModal({ - title: "Colaborador añadido", - message: "Tu solicitud de colaborador ha sido enviada correctamente.", - variant: "success", - onClick: closeFeedback - }); - } catch (err) { - setValidationErrors({}); - setFeedbackModal({ - title: "Error", - message: err.message, - variant: "danger", - onClick: closeFeedback - }); - } + setShowAddCollaboratorModal(false); + setFeedbackModal({ + title: 'Solicitud enviada', + message: 'El colaborador ha sido solicitado correctamente.', + variant: 'success', + onClick: closeFeedback + }); }} />