aboutsummaryrefslogtreecommitdiff
path: root/packages/challenger-ui/src/pages/AnswerChallenge.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/challenger-ui/src/pages/AnswerChallenge.tsx')
-rw-r--r--packages/challenger-ui/src/pages/AnswerChallenge.tsx111
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&#39;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&#39;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&#39;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>