diff options
Diffstat (limited to 'packages/challenger-ui/src/pages/AnswerChallenge.tsx')
-rw-r--r-- | packages/challenger-ui/src/pages/AnswerChallenge.tsx | 111 |
1 files changed, 86 insertions, 25 deletions
diff --git a/packages/challenger-ui/src/pages/AnswerChallenge.tsx b/packages/challenger-ui/src/pages/AnswerChallenge.tsx index b5b3b74b0..2740e1bdb 100644 --- a/packages/challenger-ui/src/pages/AnswerChallenge.tsx +++ b/packages/challenger-ui/src/pages/AnswerChallenge.tsx @@ -17,6 +17,7 @@ import { AbsoluteTime, ChallengerApi, HttpStatusCode, + TalerProtocolTimestamp, assertUnreachable, } from "@gnu-taler/taler-util"; import { @@ -53,8 +54,7 @@ export function AnswerChallenge({ const { state, accepted, completed } = useSessionState(); const [notification, withErrorHandler] = useLocalNotificationHandler(); const [pin, setPin] = useState<string | undefined>(); - const [lastTryError, setLastTryError] = - useState<ChallengerApi.InvalidPinResponse>(); + const errors = undefinedIfEmpty({ pin: !pin ? i18n.str`Can't be empty` : undefined, }); @@ -68,7 +68,9 @@ export function AnswerChallenge({ : state.lastStatus.last_address["email"]; const onSendAgain = - !state || lastEmail === undefined + lastEmail === undefined || + state?.lastStatus == undefined || + state?.lastStatus.changes_left === 0 ? undefined : withErrorHandler( async () => { @@ -80,9 +82,11 @@ export function AnswerChallenge({ completed(new URL(ok.body.redirect_url)); } else { accepted({ - attemptsLeft: ok.body.attempts_left, + changeTargetLeft: ok.body.attempts_left, + checkPinLeft: state.lastStatus?.auth_attempts_left ?? 0, + sendCodeLeft: state.lastStatus?.pin_transmissions_left ?? 0, nextSend: AbsoluteTime.fromProtocolTimestamp( - ok.body.next_tx_time, + ok.body.retransmission_time, ), transmitted: ok.body.transmitted, }); @@ -92,23 +96,23 @@ export function AnswerChallenge({ (fail) => { switch (fail.case) { case HttpStatusCode.BadRequest: - return i18n.str``; - case HttpStatusCode.Forbidden: - return i18n.str``; + return i18n.str`The request was not accepted, try reloading the app.`; case HttpStatusCode.NotFound: - return i18n.str``; + return i18n.str`Challenge not found.`; case HttpStatusCode.NotAcceptable: - return i18n.str``; + return i18n.str`Server templates are missing due to misconfiguration.`; case HttpStatusCode.TooManyRequests: - return i18n.str``; + return i18n.str`There have been too many attempts to request challenge transmissions.`; case HttpStatusCode.InternalServerError: - return i18n.str``; + return i18n.str`Server is not able to respond due to internal problems.`; } }, ); const onCheck = - errors !== undefined || (lastTryError && lastTryError.exhausted) + errors !== undefined || + state?.lastStatus == undefined || + state?.lastStatus.auth_attempts_left === 0 ? undefined : withErrorHandler( async () => { @@ -118,25 +122,34 @@ export function AnswerChallenge({ if (ok.body.type === "completed") { completed(new URL(ok.body.redirect_url)); } else { - setLastTryError(ok.body); + accepted({ + changeTargetLeft: ok.body.addresses_left, + checkPinLeft: ok.body.auth_attempts_left, + sendCodeLeft: ok.body.pin_transmissions_left, + nextSend: AbsoluteTime.fromProtocolTimestamp( + state?.lastStatus?.retransmission_time ?? + TalerProtocolTimestamp.now(), + ), + transmitted: state?.lastTry?.transmitted ?? false, + }); } onComplete(); }, (fail) => { switch (fail.case) { case HttpStatusCode.BadRequest: - return i18n.str`Invalid request`; + return i18n.str`The request was not accepted, try reloading the app.`; case HttpStatusCode.Forbidden: { - return i18n.str`Too many attemps where made`; + return i18n.str`Invalid pin.`; } case HttpStatusCode.NotFound: - return i18n.str``; + return i18n.str`Challenge not found.`; case HttpStatusCode.NotAcceptable: - return i18n.str``; + return i18n.str`Server templates are missing due to misconfiguration.`; case HttpStatusCode.TooManyRequests: - return i18n.str``; + return i18n.str`There have been too many attempts to request challenge transmissions.`; case HttpStatusCode.InternalServerError: - return i18n.str``; + return i18n.str`Server is not able to respond due to internal problems.`; default: assertUnreachable(fail); } @@ -177,11 +190,11 @@ export function AnswerChallenge({ </Attention> )} </p> - {!lastTryError ? undefined : ( + {!state.lastStatus ? undefined : ( <p class="mt-2 text-lg leading-8 text-gray-600"> <i18n.Translate> You can try another PIN but just{" "} - {lastTryError.auth_attempts_left} times more. + {state.lastStatus.auth_attempts_left} times more. </i18n.Translate> </p> )} @@ -225,8 +238,21 @@ export function AnswerChallenge({ <p class="mt-3 text-sm leading-6 text-gray-400"> <i18n.Translate> - You have {state.lastTry.attemptsLeft} attempts left. + We send the code {state.lastTry.checkPinLeft} more times. </i18n.Translate> + {state.lastTry.checkPinLeft < 1 ? ( + <i18n.Translate> + You can't check the PIN anymore. + </i18n.Translate> + ) : state.lastTry.checkPinLeft === 1 ? ( + <i18n.Translate> + You can check the PIN one last time. + </i18n.Translate> + ) : ( + <i18n.Translate> + You can check the PIN {state.lastTry.checkPinLeft} more times. + </i18n.Translate> + )} </p> </div> @@ -243,12 +269,31 @@ export function AnswerChallenge({ <div class="mt-10 flex justify-between"> <div> <a + data-disabled={!state.lastStatus || state.lastStatus.changes_left < 1} href={routeAsk.url({ nonce })} - class="relative disabled:bg-gray-100 disabled:text-gray-500 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0" + class="relative data-[disabled=true]:bg-gray-300 data-[disabled=true]:text-white data-[disabled=true]:cursor-default inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0" > <i18n.Translate>Change email</i18n.Translate> </a> - </div> + {state.lastStatus === undefined ? undefined : + <p class="mt-2 text-sm leading-6 text-gray-400"> + {state.lastStatus.changes_left < 1 ? ( + <i18n.Translate> + You can't change the email anymore. + </i18n.Translate> + ) : state.lastStatus.changes_left === 1 ? ( + <i18n.Translate> + You can change the email one last time. + </i18n.Translate> + ) : ( + <i18n.Translate> + You can change the email {state.lastStatus.changes_left}{" "} + more times. + </i18n.Translate> + )} + </p> + } + </div> <div> <Button type="submit" @@ -258,6 +303,22 @@ export function AnswerChallenge({ > <i18n.Translate>Send code again</i18n.Translate> </Button> + <p class="mt-2 text-sm leading-6 text-gray-400"> + {state.lastTry.sendCodeLeft < 1 ? ( + <i18n.Translate> + We can't send you the code anymore. + </i18n.Translate> + ) : state.lastTry.sendCodeLeft === 1 ? ( + <i18n.Translate> + We can send the code one last time. + </i18n.Translate> + ) : ( + <i18n.Translate> + We can send the code {state.lastTry.sendCodeLeft} more + times. + </i18n.Translate> + )} + </p> </div> </div> </form> |