feat(f6.2): add per-act representative signing and user smtp
Android CI / RC / Android · lint, tests, debug APK, release compile (push) Failing after 1m25s
DH V2 CI / API · typecheck, tests, build (push) Successful in 34s
DH V2 CI / WEB · typecheck, build (push) Successful in 20s
Production dependency audit / API · production dependencies (push) Successful in 9s
Production dependency audit / WEB · production dependencies (push) Successful in 9s
DH V2 CI / Docker / scripts contract (push) Successful in 1m16s

This commit is contained in:
2026-09-14 15:53:55 -03:00
parent 103ecf2fae
commit 7fe59bccd2
46 changed files with 907 additions and 154 deletions
+4 -3
View File
@@ -57,8 +57,8 @@ export function UserDetailPage() {
setError(''); setSuccess('');
const data = new FormData(event.currentTarget);
const email = String(data.get('email') ?? '').trim();
if (inspectorSelected && !email) {
setError('El email es obligatorio para un Inspector porque allí recibe la documentación de sus inspecciones.');
if (!email) {
setError('El email es obligatorio para todos los usuarios de Hidrocarburos.');
return;
}
setSaving('profile');
@@ -139,6 +139,7 @@ export function UserDetailPage() {
<div className="detail-grid">
<form className="panel form-panel" onSubmit={saveProfile}>
<div className="panel-heading"><div><span className="eyebrow">PERFIL</span><h2>Datos personales y contacto</h2></div><span className={`status-badge ${user.status.toLowerCase()}`}>{user.status === 'ACTIVE' ? 'Activo' : 'Inactivo'}</span></div>
<p className="muted-copy">Correo saliente: <strong>{user.smtpMode === 'CUSTOM' ? 'SMTP propio' : 'SMTP general'}</strong>. Cada usuario administra su modalidad desde Mi perfil.</p>
<div className="form-grid">
<label className="field"><span>Nombre</span><input name="firstName" defaultValue={user.firstName} required disabled={!canUpdate} /></label>
<label className="field"><span>Apellido</span><input name="lastName" defaultValue={user.lastName} required disabled={!canUpdate} /></label>
@@ -147,7 +148,7 @@ export function UserDetailPage() {
<label className="field"><span>Cargo / función</span><input name="jobTitle" defaultValue={user.jobTitle ?? ''} maxLength={160} disabled={!canUpdate} /></label>
<label className="field"><span>Legajo / matrícula</span><input name="employeeNumber" defaultValue={user.employeeNumber ?? ''} maxLength={80} disabled={!canUpdate} /></label>
<label className="field"><span>Usuario</span><input name="username" defaultValue={user.username} required disabled={!canUpdate} /></label>
<label className="field"><span>Email {inspectorSelected && <em>obligatorio para Inspector</em>}</span><input name="email" type="email" defaultValue={user.email ?? ''} required={inspectorSelected} disabled={!canUpdate} /></label>
<label className="field"><span>Email <em>obligatorio</em></span><input name="email" type="email" defaultValue={user.email ?? ''} required disabled={!canUpdate} /></label>
</div>
{inspectorSelected && <div className="temporal-notice"><Icon name="mail" /><p><strong>Destinatario del Inspector:</strong> al finalizar una inspección, la documentación se enviará también a <strong>{user.email || 'este email cuando lo completes'}</strong>.</p></div>}
<div className="metadata-grid"><div><small>Último acceso</small><strong>{formatDate(user.lastLoginAt)}</strong></div><div><small>Último cambio de clave</small><strong>{formatDate(user.passwordChangedAt)}</strong></div><div><small>Intentos fallidos</small><strong>{user.failedLoginAttempts}</strong></div><div><small>Bloqueado hasta</small><strong>{formatDate(user.lockedUntil)}</strong></div></div>