back to desktop pc

This commit is contained in:
2026-01-30 11:35:10 +01:00
parent 3f4571af5e
commit 665ac85701
4 changed files with 222 additions and 216 deletions

View File

@@ -6,12 +6,12 @@ import PropTypes from 'prop-types';
import { generateSecurePassword } from '../../util/passwordGenerator'; import { generateSecurePassword } from '../../util/passwordGenerator';
const PreUserForm = ({ onSubmit, userType, plotNumber, errors = {} }) => { const NewUserForm = ({ onSubmit, userType, plotNumber, errors = {} }) => {
const { getData } = useDataContext(); const { getData } = useDataContext();
const fetchedOnce = useRef(false); const fetchedOnce = useRef(false);
const [form, setForm] = useState({ const [form, setForm] = useState({
userName: '', username: '',
password: generateSecurePassword(8), password: generateSecurePassword(8),
displayName: '', displayName: '',
dni: '', dni: '',
@@ -53,10 +53,10 @@ const PreUserForm = ({ onSubmit, userType, plotNumber, errors = {} }) => {
const nuevoUsername = trimmedName const nuevoUsername = trimmedName
? trimmedName.split(' ')[0].toLowerCase() : ""; ? trimmedName.split(' ')[0].toLowerCase() : "";
if (form.userName !== nuevoUsername) { if (form.username !== nuevoUsername) {
setForm(prev => ({ ...prev, userName: nuevoUsername })); setForm(prev => ({ ...prev, username: nuevoUsername }));
} }
}, [form.memberNumber, form.displayName, form.userName]); }, [form.memberNumber, form.displayName, form.username]);
const handleChange = (e) => { const handleChange = (e) => {
const { name, value, type } = e.target; 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 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: 'DNI', name: 'dni', type: 'text', required: true, maxLength: 9 },
{ label: 'Teléfono', name: 'phone', type: 'tel', required: true }, { label: 'Teléfono', name: 'phone', type: 'tel', required: true },
{ label: 'Correo electrónico', name: 'email', type: 'email', 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, userType: PropTypes.number.isRequired,
plotNumber: PropTypes.number.isRequired, plotNumber: PropTypes.number.isRequired,
onSubmit: PropTypes.func.isRequired, onSubmit: PropTypes.func.isRequired,
errors: PropTypes.object errors: PropTypes.object
}; };
export default PreUserForm; export default NewUserForm;

View File

@@ -15,117 +15,100 @@ const MotionCard = _motion.create(Card);
const parseDate = (date) => { const parseDate = (date) => {
if (!date) return 'NO'; if (!date) return 'NO';
const d = new Date(date); 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 getTipoSolicitud = (tipo) =>
const getEstadoSolicitud = (estado) => ['Pendiente', 'Aceptada', 'Rechazada'][estado] ?? 'Desconocido'; ['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 getPFP = (tipo) => {
const base = '/images/icons/'; const base = '/images/icons/';
const map = { const map = {
0: 'list.svg',
1: 'farmer.svg', 1: 'farmer.svg',
2: 'green_house.svg', 2: 'green_house.svg',
0: 'list.svg', 3: 'join.svg'
3: 'join.svg',
4: 'subvencion4.svg',
5: 'programmer.svg'
}; };
return base + (map[tipo] || 'farmer.svg'); return base + (map[tipo] || 'farmer.svg');
}; };
const renderDescripcionSolicitud = (data, onProfile) => { const renderDescripcionSolicitud = (data, onProfile) => {
console.log(data); const m = data.metadata;
switch (data.type) { switch (data.type) {
case 0: case 0:
if (data.requestedByName) { return data.status === 1
return `${data.requestedByName} quiere darse de alta.`; ? 'Se ha aceptado esta solicitud de alta.'
} else if (data.status !== 1 && data.preDisplayName) { : `${m?.displayName ?? 'Alguien'} quiere darse de alta.`;
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.`;
}
case 1: case 1:
return onProfile return onProfile
? "Has solicitado darte de baja." ? 'Has solicitado darte de baja.'
: data.requestedByName : `${m?.displayName ?? 'Alguien'} quiere darse de baja.`;
? `${data.requestedByName} quiere darse de baja.`
: data.status !== 1
? `Alguien quiere darse de baja.`
: `Se ha aceptado esta solicitud de baja.`;
case 2: case 2:
if (onProfile) { if (onProfile) {
switch (data.status) { return [
case 0: return "Has solicitado añadir un colaborador."; 'Has solicitado añadir un colaborador.',
case 1: return "Tu solicitud de colaborador ha sido aceptada."; 'Tu solicitud de colaborador ha sido aceptada.',
case 2: return "Tu solicitud de colaborador ha sido rechazada."; 'Tu solicitud de colaborador ha sido rechazada.'
default: return "Solicitud de colaborador desconocida."; ][data.status] ?? 'Solicitud de colaborador.';
}
} 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 data.status === 0
? `${m?.displayName ?? 'Alguien'} quiere añadir un colaborador.`
: `La solicitud de colaborador ha sido ${
data.status === 1 ? 'aceptada' : 'rechazada'
}.`;
case 3: case 3:
return onProfile return `${m?.displayName ?? 'Alguien'} quiere quitar su colaborador.`;
? "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.`;
case 4: case 4:
return onProfile return `${m?.displayName ?? 'Alguien'} quiere una parcela en el invernadero.`;
? "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.`;
case 5: case 5:
return onProfile return `${m?.displayName ?? 'Alguien'} quiere dejar su parcela del invernadero.`;
? "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.`;
default: default:
return "Tipo de solicitud desconocido."; return 'Tipo de solicitud desconocido.';
} }
}; };
const SolicitudCard = ({ data, onAccept, onReject, onDelete, editable = true, onProfile = false }) => { const SolicitudCard = ({
const handleDelete = () => typeof onDelete === "function" && onDelete(data.requestId); data,
onAccept,
onReject,
onDelete,
editable = true,
onProfile = false
}) => {
const m = data.metadata;
const handleDelete = () =>
typeof onDelete === 'function' && onDelete(data.requestId);
return ( return (
<MotionCard className="solicitud-card shadow-sm rounded-4 h-100"> <MotionCard className="solicitud-card shadow-sm rounded-4 h-100">
<Card.Header className="rounded-top-4 d-flex justify-content-between align-items-center"> <Card.Header className="rounded-top-4 d-flex justify-content-between align-items-center">
<div className="d-flex align-items-center"> <div className="d-flex align-items-center">
<img src={getPFP(data.preType)} width="36" className="rounded me-3" alt="PFP" /> <img
src={getPFP(m?.type)}
width="36"
className="rounded me-3"
alt="PFP"
/>
<div> <div>
<Card.Title className="mb-0"> <Card.Title className="mb-0">
Solicitud #{data.idx} - {getTipoSolicitud(data.type)} Solicitud #{data.requestId?.slice(0, 8)} {getTipoSolicitud(data.type)}
</Card.Title> </Card.Title>
<small className='state-small'>Estado: <strong>{getEstadoSolicitud(data.status)}</strong></small> <small className="state-small">
Estado: <strong>{getEstadoSolicitud(data.status)}</strong>
</small>
</div> </div>
</div> </div>
@@ -133,10 +116,18 @@ const SolicitudCard = ({ data, onAccept, onReject, onDelete, editable = true, on
<AnimatedDropdown <AnimatedDropdown
className="end-0" className="end-0"
buttonStyle="card-button" buttonStyle="card-button"
icon={<FontAwesomeIcon icon={faEllipsisVertical} className="fa-xl" />}> icon={<FontAwesomeIcon icon={faEllipsisVertical} className="fa-xl" />}
>
{({ closeDropdown }) => ( {({ closeDropdown }) => (
<div className="dropdown-item d-flex align-items-center text-danger" onClick={() => { handleDelete(); closeDropdown(); }}> <div
<FontAwesomeIcon icon={faTrash} className="me-2" />Eliminar className="dropdown-item d-flex align-items-center text-danger"
onClick={() => {
handleDelete();
closeDropdown();
}}
>
<FontAwesomeIcon icon={faTrash} className="me-2" />
Eliminar
</div> </div>
)} )}
</AnimatedDropdown> </AnimatedDropdown>
@@ -157,27 +148,73 @@ const SolicitudCard = ({ data, onAccept, onReject, onDelete, editable = true, on
</ListGroup.Item> </ListGroup.Item>
</ListGroup> </ListGroup>
{data.preDisplayName && ( {m && (
<> <>
<Card.Subtitle className="card-subtitle mt-3 mb-2">Datos del futuro socio</Card.Subtitle> <Card.Subtitle className="card-subtitle mt-3 mb-2">
Datos asociados a la solicitud
</Card.Subtitle>
<ListGroup variant="flush" className="border rounded-3"> <ListGroup variant="flush" className="border rounded-3">
<ListGroup.Item><FontAwesomeIcon icon={faUser} className="me-2" />Nombre: <strong>{data.preDisplayName}</strong></ListGroup.Item> <ListGroup.Item>
<ListGroup.Item><FontAwesomeIcon icon={faIdCard} className="me-2" />DNI: <strong>{data.preDni}</strong></ListGroup.Item> <FontAwesomeIcon icon={faUser} className="me-2" />
<ListGroup.Item><FontAwesomeIcon icon={faPhone} className="me-2" />Teléfono: <strong>{data.prePhone}</strong></ListGroup.Item> Nombre: <strong>{m.displayName}</strong>
<ListGroup.Item><FontAwesomeIcon icon={faEnvelope} className="me-2" />Email: <strong>{data.preEmail}</strong></ListGroup.Item> </ListGroup.Item>
<ListGroup.Item><FontAwesomeIcon icon={faHome} className="me-2" />Dirección: <strong>{data.preAddress ?? 'NO'}</strong></ListGroup.Item>
<ListGroup.Item><FontAwesomeIcon icon={faMapMarkerAlt} className="me-2" />Ciudad: <strong>{data.preCity ?? 'NO'} ({data.preZipCode ?? 'NO'})</strong></ListGroup.Item> <ListGroup.Item>
<ListGroup.Item><FontAwesomeIcon icon={faHashtag} className="me-2" /> socio: <strong>{data.preMemberNumber ?? 'NO'}</strong> | huerto: <strong>{data.prePlotNumber ?? 'NO'}</strong></ListGroup.Item> <FontAwesomeIcon icon={faIdCard} className="me-2" />
<ListGroup.Item><FontAwesomeIcon icon={faSeedling} className="me-2" />Tipo: <strong>{['Lista de Espera', 'Hortelano', 'Hortelano + Invernadero', 'Colaborador'][data.preType]}</strong></ListGroup.Item> DNI: <strong>{m.dni}</strong>
<ListGroup.Item><FontAwesomeIcon icon={faUserShield} className="me-2" />Rol: <strong>{['Usuario', 'Admin', 'Desarrollador'][data.preRole]}</strong></ListGroup.Item> </ListGroup.Item>
<ListGroup.Item>
<FontAwesomeIcon icon={faPhone} className="me-2" />
Teléfono: <strong>{m.phone ?? 'NO'}</strong>
</ListGroup.Item>
<ListGroup.Item>
<FontAwesomeIcon icon={faEnvelope} className="me-2" />
Email: <strong>{m.email}</strong>
</ListGroup.Item>
<ListGroup.Item>
<FontAwesomeIcon icon={faUserShield} className="me-2" />
Usuario: <strong>{m.username}</strong>
</ListGroup.Item>
<ListGroup.Item>
<FontAwesomeIcon icon={faHome} className="me-2" />
Dirección: <strong>{m.address ?? 'NO'}</strong>
</ListGroup.Item>
<ListGroup.Item>
<FontAwesomeIcon icon={faMapMarkerAlt} className="me-2" />
Ciudad:{' '}
<strong>
{m.city ?? 'NO'} ({m.zipCode ?? 'NO'})
</strong>
</ListGroup.Item>
<ListGroup.Item>
<FontAwesomeIcon icon={faHashtag} className="me-2" />
socio: <strong>{m.memberNumber ?? 'NO'}</strong> | huerto:{' '}
<strong>{m.plotNumber ?? 'NO'}</strong>
</ListGroup.Item>
<ListGroup.Item>
<FontAwesomeIcon icon={faSeedling} className="me-2" />
Tipo: <strong>{['Lista de espera', 'Hortelano', 'Hortelano + Invernadero', 'Colaborador'][m.type]}</strong>
</ListGroup.Item>
</ListGroup> </ListGroup>
</> </>
)} )}
{editable && data.status === 0 && ( {editable && data.status === 0 && (
<div className="d-flex justify-content-end gap-2 mt-3"> <div className="d-flex justify-content-end gap-2 mt-3">
<Button variant="danger" size="sm" onClick={() => onReject?.(data)}>Rechazar</Button> <Button variant="danger" size="sm" onClick={() => onReject?.(data)}>
<Button variant="success" size="sm" onClick={() => onAccept?.(data)}>Aceptar</Button> Rechazar
</Button>
<Button variant="success" size="sm" onClick={() => onAccept?.(data)}>
Aceptar
</Button>
</div> </div>
)} )}
</Card.Body> </Card.Body>

View File

@@ -10,7 +10,7 @@ import { DateParser } from '../util/parsers/dateParser';
import CustomContainer from '../components/CustomContainer'; import CustomContainer from '../components/CustomContainer';
import ContentWrapper from '../components/ContentWrapper'; import ContentWrapper from '../components/ContentWrapper';
import LoadingIcon from '../components/LoadingIcon'; import LoadingIcon from '../components/LoadingIcon';
import PreUserForm from '../components/Solicitudes/PreUserForm'; import NewUserForm from '../components/Solicitudes/NewUserForm';
import CustomModal from '../components/CustomModal'; import CustomModal from '../components/CustomModal';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faPencil } from '@fortawesome/free-solid-svg-icons'; import { faPencil } from '@fortawesome/free-solid-svg-icons';
@@ -40,7 +40,7 @@ const ListaEsperaContent = ({ reqConfig }) => {
const { data, dataLoading, dataError, postData, postDataValidated } = useDataContext(); const { data, dataLoading, dataError, postData, postDataValidated } = useDataContext();
const [showWelcomeModal, setShowWelcomeModal] = useState(false); const [showWelcomeModal, setShowWelcomeModal] = useState(false);
const [showPreUserFormModal, setShowPreUserFormModal] = useState(false); const [showNewUserFormModal, setShowNewUserFormModal] = useState(false);
const [showConfirmationModal, setShowConfirmationModal] = useState(false); const [showConfirmationModal, setShowConfirmationModal] = useState(false);
const [validationErrors, setValidationErrors] = useState({}); const [validationErrors, setValidationErrors] = useState({});
@@ -82,7 +82,7 @@ const ListaEsperaContent = ({ reqConfig }) => {
requestId requestId
}); });
setShowPreUserFormModal(false); setShowNewUserFormModal(false);
setShowConfirmationModal(true); setShowConfirmationModal(true);
} catch (err) { } catch (err) {
setValidationErrors({ general: "Error inesperado al enviar la solicitud" }); setValidationErrors({ general: "Error inesperado al enviar la solicitud" });
@@ -92,7 +92,7 @@ const ListaEsperaContent = ({ reqConfig }) => {
const handleOpenFormModal = () => { const handleOpenFormModal = () => {
setValidationErrors({}); setValidationErrors({});
setShowWelcomeModal(false); setShowWelcomeModal(false);
setShowPreUserFormModal(true); setShowNewUserFormModal(true);
}; };
if (dataLoading) return <p className="text-center my-5"><LoadingIcon /></p>; if (dataLoading) return <p className="text-center my-5"><LoadingIcon /></p>;
@@ -136,13 +136,13 @@ const ListaEsperaContent = ({ reqConfig }) => {
<CustomModal <CustomModal
title="Solicitud de Huerto" title="Solicitud de Huerto"
show={showPreUserFormModal} show={showNewUserFormModal}
onClose={() => { onClose={() => {
setShowPreUserFormModal(false); setShowNewUserFormModal(false);
setValidationErrors({}); setValidationErrors({});
}} }}
> >
<PreUserForm <NewUserForm
userType={0} userType={0}
plotNumber={0} plotNumber={0}
onSubmit={handleRegisterSubmit} onSubmit={handleRegisterSubmit}

View File

@@ -25,7 +25,7 @@ import { useState } from 'react';
import IngresoCard from '../components/Ingresos/IngresoCard'; import IngresoCard from '../components/Ingresos/IngresoCard';
import SolicitudCard from '../components/Solicitudes/SolicitudCard'; import SolicitudCard from '../components/Solicitudes/SolicitudCard';
import CustomModal from '../components/CustomModal'; import CustomModal from '../components/CustomModal';
import PreUserForm from '../components/Solicitudes/PreUserForm'; import NewUserForm from '../components/Solicitudes/NewUserForm';
import NotificationModal from '../components/NotificationModal'; import NotificationModal from '../components/NotificationModal';
import { Button, Col, Row } from 'react-bootstrap'; import { Button, Col, Row } from 'react-bootstrap';
import AnimatedDropdown from '../components/AnimatedDropdown'; import AnimatedDropdown from '../components/AnimatedDropdown';
@@ -69,9 +69,6 @@ const Perfil = () => {
baseUrl: `${config.apiConfig.baseUrl}${config.apiConfig.endpoints.users.me}`, baseUrl: `${config.apiConfig.baseUrl}${config.apiConfig.endpoints.users.me}`,
myIncomesUrl: buildUrl(config.apiConfig.baseUrl, config.apiConfig.endpoints.incomes.mine), myIncomesUrl: buildUrl(config.apiConfig.baseUrl, config.apiConfig.endpoints.incomes.mine),
requestUrl: buildUrl(config.apiConfig.baseUrl, config.apiConfig.endpoints.requests.all), 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), myRequestsUrl: buildUrl(config.apiConfig.baseUrl, config.apiConfig.endpoints.requests.mine),
changePasswordUrl: buildUrl(config.apiConfig.coreUrl, config.apiConfig.endpoints.auth.changePassword), changePasswordUrl: buildUrl(config.apiConfig.coreUrl, config.apiConfig.endpoints.auth.changePassword),
loginValidateUrl: buildUrl(config.apiConfig.coreUrl, config.apiConfig.endpoints.auth.loginValidate), loginValidateUrl: buildUrl(config.apiConfig.coreUrl, config.apiConfig.endpoints.auth.loginValidate),
@@ -89,8 +86,10 @@ const PerfilContent = ({ config }) => {
const { logout } = useAuth(); const { logout } = useAuth();
const identity = JSON.parse(localStorage.getItem("identity")); const identity = JSON.parse(localStorage.getItem("identity"));
const myRequests = data?.requests ?? []; const myRequests = data?.requests ?? [];
const incomes = data?.payments ?? []; const incomes = data?.payments ?? [];
const hasCollaborator = data?.hasCollaborator ?? false; const hasCollaborator = data?.hasCollaborator ?? false;
const hasCollaboratorRequest = data?.hasCollaboratorRequest ?? false; const hasCollaboratorRequest = data?.hasCollaboratorRequest ?? false;
const hasGreenHouse = data?.hasGreenhouse ?? false; const hasGreenHouse = data?.hasGreenhouse ?? false;
@@ -101,6 +100,44 @@ const PerfilContent = ({ config }) => {
const [feedbackModal, setFeedbackModal] = useState(null); const [feedbackModal, setFeedbackModal] = useState(null);
const closeFeedback = () => setFeedbackModal(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 [validationErrors, setValidationErrors] = useState({});
const [newPasswordData, setNewPasswordData] = useState({ const [newPasswordData, setNewPasswordData] = useState({
@@ -113,75 +150,6 @@ const PerfilContent = ({ config }) => {
const [showNew, setShowNew] = useState(false); const [showNew, setShowNew] = useState(false);
const [showConfirm, setShowConfirm] = 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) => { const handleChange = (e) => {
setNewPasswordData({ setNewPasswordData({
...newPasswordData, ...newPasswordData,
@@ -263,27 +231,42 @@ const PerfilContent = ({ config }) => {
{({ closeDropdown }) => ( {({ closeDropdown }) => (
<> <>
{!hasGreenHouse && !hasGreenHouseRequest && ( {!hasGreenHouse && !hasGreenHouseRequest && (
<div className="dropdown-item d-flex align-items-center" onClick={() => { handleRequestGreenHouse(); closeDropdown(); }}> <div className="dropdown-item d-flex align-items-center" onClick={() => {
sendSimpleRequest(CONSTANTS.REQUEST_TYPE_ADD_GREENHOUSE);
closeDropdown();
}}>
<FontAwesomeIcon icon={faSeedling} className="me-2" />Solicitar invernadero <FontAwesomeIcon icon={faSeedling} className="me-2" />Solicitar invernadero
</div> </div>
)} )}
{!hasCollaborator && !hasCollaboratorRequest && ( {!hasCollaborator && !hasCollaboratorRequest && (
<div className="dropdown-item d-flex align-items-center" onClick={() => { setShowAddCollaboratorModal(true); closeDropdown(); }}> <div className="dropdown-item d-flex align-items-center" onClick={() => {
setShowAddCollaboratorModal(true);
closeDropdown();
}}>
<FontAwesomeIcon icon={faUserPlus} className="me-2" />Añadir un colaborador <FontAwesomeIcon icon={faUserPlus} className="me-2" />Añadir un colaborador
</div> </div>
)} )}
<hr className="dropdown-divider" /> <hr className="dropdown-divider" />
{hasGreenHouse && !hasGreenHouseRequest && ( {hasGreenHouse && !hasGreenHouseRequest && (
<div className="dropdown-item d-flex align-items-center text-danger" onClick={() => { handleRemoveGreenHouse(); closeDropdown(); }}> <div className="dropdown-item d-flex align-items-center text-danger" onClick={() => {
sendSimpleRequest(CONSTANTS.REQUEST_TYPE_REMOVE_GREENHOUSE);
closeDropdown();
}}>
<FontAwesomeIcon icon={faArrowRightFromBracket} className="me-2" />Dejar invernadero <FontAwesomeIcon icon={faArrowRightFromBracket} className="me-2" />Dejar invernadero
</div> </div>
)} )}
{hasCollaborator && !hasCollaboratorRequest && ( {hasCollaborator && !hasCollaboratorRequest && (
<div className="dropdown-item d-flex align-items-center text-danger" onClick={() => { setShowRemoveCollaboratorModal(true); closeDropdown(); }}> <div className="dropdown-item d-flex align-items-center text-danger" onClick={() => {
setShowRemoveCollaboratorModal(true);
closeDropdown();
}}>
<FontAwesomeIcon icon={faUserSlash} className="me-2" />Quitar colaborador <FontAwesomeIcon icon={faUserSlash} className="me-2" />Quitar colaborador
</div> </div>
)} )}
<div className="dropdown-item d-flex align-items-center text-danger" onClick={() => { handleRequestUnregister(); closeDropdown(); }}> <div className="dropdown-item d-flex align-items-center text-danger" onClick={() => {
sendSimpleRequest(CONSTANTS.REQUEST_TYPE_UNREGISTER);
closeDropdown();
}}>
<FontAwesomeIcon icon={faUserSlash} className="me-2" />Darse de baja <FontAwesomeIcon icon={faUserSlash} className="me-2" />Darse de baja
</div> </div>
</> </>
@@ -431,48 +414,34 @@ const PerfilContent = ({ config }) => {
setValidationErrors({}); setValidationErrors({});
}} }}
> >
<PreUserForm <NewUserForm
userType={3} userType={3}
plotNumber={identity.metadata.plotNumber} plotNumber={identity.metadata.plotNumber}
errors={validationErrors} errors={validationErrors}
onSubmit={async (formData) => { onSubmit={async (formData) => {
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); setShowAddCollaboratorModal(false);
if (errors) { setFeedbackModal({
setValidationErrors(errors); title: 'Solicitud enviada',
return; message: 'El colaborador ha sido solicitado correctamente.',
} variant: 'success',
onClick: closeFeedback
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
});
}
}} }}
/> />
</CustomModal> </CustomModal>