Merge branch 'feature/fayda-auth-and-email-notifications' of github.com:Tria-plc/emaui into feature/fayda-auth-and-email-notifications

This commit is contained in:
mihretue
2026-08-27 17:08:20 +03:00
7 changed files with 99 additions and 10 deletions

View File

@@ -76,6 +76,7 @@ export function SignupPage() {
transactionToken: string;
expiresIn: number;
}>();
const [linkTrigger] = useApiMutation<{ phoneNumberVerified?: boolean }>();
const verified = (field: string) => fayda?.verifiedFields.includes(field) ?? false;
const conflicted = (field: string) => fayda?.conflicts.includes(field) ?? false;
@@ -89,8 +90,10 @@ export function SignupPage() {
const faydaMark = (field: string): { description?: React.ReactNode } => {
if (conflicted(field)) {
return {
// component="span" on these badges: the description slot renders
// inside a <p>, where Badge's default <div> is invalid HTML.
description: (
<Badge size="xs" variant="light" color="orange">
<Badge component="span" size="xs" variant="light" color="orange">
{t('fayda.fieldConflict', 'Already used by another account')}
</Badge>
),
@@ -100,6 +103,7 @@ export function SignupPage() {
return {
description: (
<Badge
component="span"
size="xs"
variant="light"
color="teal"
@@ -234,9 +238,28 @@ export function SignupPage() {
const me = await meTrigger({ url: '/auth/me', method: 'GET' }).unwrap();
dispatch(setUser(me));
// Records the Fayda-verified identity on the new account: marks the
// phone verified when it is the one Fayda vouched for, and fills the
// still-empty profile fields. Best-effort — the account already works,
// and the token can be presented again on a retry.
let faydaPhoneVerified = false;
if (fayda?.verificationToken) {
try {
const applied = await linkTrigger({
url: '/profiles/me/fayda',
method: 'POST',
body: { verificationToken: fayda.verificationToken },
}).unwrap();
faydaPhoneVerified = Boolean(applied?.phoneNumberVerified);
} catch {
/* deliberately ignored — signup already succeeded */
}
}
faydaSession.clearResult();
if (data.isPhoneNumberVerified) {
// Fayda already verified this exact number via its own OTP; asking for
// a second OTP on the same number is theatre.
if (data.isPhoneNumberVerified || faydaPhoneVerified) {
navigate(loginRedirectPath);
} else {
navigate('/otp-verify', {

View File

@@ -24,6 +24,9 @@ export interface FaydaPrefill {
/** Shown for context only — the signup form has no field for these. */
gender?: string;
address?: string;
birthdate?: string;
nationality?: string;
faydaNumber?: string;
}
/** Shape of `POST /auth/register-with-fayda` with `action: "verify"`. */
@@ -34,6 +37,11 @@ export interface FaydaResult {
verifiedFields: string[];
/** Prefilled fields already taken by another account. */
conflicts: string[];
/**
* Encrypted proof of the verification, presented to POST /profiles/me/fayda
* after signup so the account and profile record what Fayda vouched for.
*/
verificationToken: string;
}
// Private browsing and locked-down browsers can throw on access, and a failure