feat(users): OTP delivery method picker on user creation + post-login agreement
build-run / Run Lint, Build and Deploy (push) Canceled after 0s
Publish Image in Docker Hub / build (push) Canceled after 0s
Playwright E2E Tests / Run Playwright Tests (push) Canceled after 0s
Tests / testRigor (push) Canceled after 0s

Create User dialog now has a mandatory Email/Mobile OTP delivery method
picker (styled as a pill toggle) alongside the existing fields.

Adds a new post-login agreement acceptance dialog: right after the existing
2FA flow (TwoFactorAuthenticationComponent) succeeds, or immediately after
login for users without 2FA, the user must accept the bank's current
agreement/disclaimer at least once before reaching the app.

Also adds a "Manage User Agreement" admin screen (System section) to publish
versioned agreement text without a code deploy.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-24 16:20:46 +05:30
co-authored by Claude Sonnet 5
parent d0536dbb11
commit d334dd1669
18 changed files with 1356 additions and 16 deletions
@@ -126,6 +126,12 @@ $purple: #7c3aed;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px 14px;
// A field placed right after the grid (e.g. OTP Delivery Method, which spans full width
// and isn't part of the 2-column layout) needs its own breathing room above it.
+ .ufd-field {
margin-top: 12px;
}
}
.ufd-field {
@@ -268,6 +274,57 @@ $purple: #7c3aed;
}
}
.ufd-otp-methods {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.ufd-otp-method {
display: inline-flex;
align-items: center;
gap: 7px;
height: 36px;
padding: 0 14px;
border: 1px solid #cbd5e1;
background: #fff;
border-radius: 999px;
color: #475569;
font-size: 12.5px;
font-weight: 600;
cursor: pointer;
transition: all 0.12s;
fa-icon {
font-size: 12px;
}
// stylelint-disable-next-line selector-no-qualifying-type
input[type='radio'] {
// Visually hidden but still focusable/clickable for accessibility - the pill itself
// carries the selected state via .is-selected, matching .ufd-role's pattern.
position: absolute;
opacity: 0;
width: 0;
height: 0;
}
&:hover {
border-color: #94a3b8;
color: $navy;
}
&.is-selected {
background: rgb(30 136 229 / 12%);
border-color: $blue;
color: $blue-d;
fa-icon {
color: $blue;
}
}
}
.ufd-hint {
display: flex;
align-items: center;