added new continue after wire transfer confirmed

This commit is contained in:
Sebastian 2023-08-04 10:10:30 -03:00
parent 6f4548c892
commit acf110dd78
No known key found for this signature in database
GPG Key ID: 173909D1A5F66069
7 changed files with 122 additions and 45 deletions

View File

@ -21,9 +21,11 @@ export function Loading(): VNode {
<div
class="columns is-centered is-vcentered"
style={{
height: "calc(100% - 3rem)",
position: "absolute",
width: "100%",
height: "200px",
display: "flex",
margin: "auto",
justifyContent: "center",
}}
>
<Spinner />
@ -33,7 +35,7 @@ export function Loading(): VNode {
export function Spinner(): VNode {
return (
<div class="lds-ring">
<div class="lds-ring" style={{margin:"auto"}}>
<div />
<div />
<div />

View File

@ -84,11 +84,11 @@ export function HomePage({
export function WithdrawalOperationPage({
operationId,
onLoadNotOk,
onAbort,
onContinue,
}: {
operationId: string;
onLoadNotOk: () => void;
onAbort: () => void;
onContinue: () => void;
}): VNode {
//FIXME: libeufin sandbox should return show to create the integration api endpoint
//or return withdrawal uri from response
@ -99,12 +99,6 @@ export function WithdrawalOperationPage({
const parsedUri = parseWithdrawUri(uri);
const { i18n } = useTranslationContext();
const [settings, updateSettings] = useSettings();
function clearCurrentWithdrawal(): void {
updateSettings("currentWithdrawalOperationId", undefined);
onAbort();
}
if (!parsedUri) {
notifyError({
title: i18n.str`The Withdrawal URI is not valid: "${uri}"`,
@ -115,10 +109,7 @@ export function WithdrawalOperationPage({
return (
<WithdrawalQRCode
withdrawUri={parsedUri}
onConfirmed={() => {
notifyInfo(i18n.str`Withdrawal confirmed!`);
}}
onAborted={clearCurrentWithdrawal}
onContinue={onContinue}
onLoadNotOk={onLoadNotOk}
/>
);

View File

@ -40,7 +40,7 @@ export function Routing(): VNode {
component={({ wopid }: { wopid: string }) => (
<WithdrawalOperationPage
operationId={wopid}
onAbort={() => {
onContinue={() => {
route("/account");
}}
onLoadNotOk={() => {

View File

@ -33,7 +33,6 @@ import { ShowInputErrorLabel } from "./ShowInputErrorLabel.js";
const logger = new Logger("WithdrawalConfirmationQuestion");
interface Props {
onConfirmed: () => void;
onAborted: () => void;
withdrawUri: WithdrawUriResult;
}
@ -42,7 +41,6 @@ interface Props {
* Not providing a back button, only abort.
*/
export function WithdrawalConfirmationQuestion({
onConfirmed,
onAborted,
withdrawUri,
}: Props): VNode {
@ -119,7 +117,6 @@ export function WithdrawalConfirmationQuestion({
await confirmWithdrawal(
withdrawUri.withdrawalOperationId,
);
onConfirmed();
} catch (error) {
if (error instanceof RequestError) {
notifyError(

View File

@ -24,6 +24,7 @@ import { Fragment, VNode, h } from "preact";
import { Loading } from "../components/Loading.js";
import { useWithdrawalDetails } from "../hooks/access.js";
import { notifyInfo } from "../hooks/notification.js";
import { useSettings } from "../hooks/settings.js";
import { handleNotOkResult } from "./HomePage.js";
import { QrCodeSection } from "./QrCodeSection.js";
import { WithdrawalConfirmationQuestion } from "./WithdrawalConfirmationQuestion.js";
@ -32,8 +33,7 @@ const logger = new Logger("WithdrawalQRCode");
interface Props {
withdrawUri: WithdrawUriResult;
onAborted: () => void;
onConfirmed: () => void;
onContinue: () => void;
onLoadNotOk: () => void;
}
/**
@ -43,10 +43,14 @@ interface Props {
*/
export function WithdrawalQRCode({
withdrawUri,
onConfirmed,
onAborted,
onContinue,
onLoadNotOk,
}: Props): VNode {
const [settings, updateSettings] = useSettings();
function clearCurrentWithdrawal(): void {
updateSettings("currentWithdrawalOperationId", undefined);
onContinue();
}
const { i18n } = useTranslationContext();
const result = useWithdrawalDetails(withdrawUri.withdrawalOperationId);
if (!result.ok) {
@ -64,13 +68,64 @@ export function WithdrawalQRCode({
}
const { data } = result;
logger.trace("withdrawal status", data);
if (data.aborted || data.confirmation_done) {
// signal that this withdrawal is aborted
// will redirect to account info
notifyInfo(i18n.str`Operation completed`);
onAborted();
return <Loading />;
if (data.aborted) {
return <section id="main" class="content">
<h1 class="nav">{i18n.str`Operation aborted`}</h1>
<section>
<p>
<i18n.Translate>
The wire transfer to the GNU Taler Exchange bank's account was aborted, your balance
was not affected.
</i18n.Translate>
</p>
<p>
<i18n.Translate>
You can close this page now or continue to the account page.
</i18n.Translate>
</p>
<a class="pure-button pure-button-primary"
style={{float:"right"}}
onClick={async (e) => {
e.preventDefault();
clearCurrentWithdrawal()
onContinue()
}}>
{i18n.str`Continue`}
</a>
</section>
</section>
}
if (data.confirmation_done) {
return <section id="main" class="content">
<h1 class="nav">{i18n.str`Operation completed`}</h1>
<section id="assets" style={{maxWidth: 400, marginLeft: "auto", marginRight:"auto"}}>
<p>
<i18n.Translate>
The wire transfer to the GNU Taler Exchange bank's account is completed, now the
exchange will send the requested amount into your GNU Taler wallet.
</i18n.Translate>
</p>
<p>
<i18n.Translate>
You can close this page now or continue to the account page.
</i18n.Translate>
</p>
<div style={{textAlign:"center"}}>
<a class="pure-button pure-button-primary"
onClick={async (e) => {
e.preventDefault();
clearCurrentWithdrawal()
onContinue()
}}>
{i18n.str`Continue`}
</a>
</div>
</section>
</section>
}
if (!data.selection_done) {
@ -79,25 +134,21 @@ export function WithdrawalQRCode({
withdrawUri={withdrawUri}
onAborted={() => {
notifyInfo(i18n.str`Operation canceled`);
onAborted();
}}
clearCurrentWithdrawal()
onContinue()
}}
/>
);
}
// Wallet POSTed the withdrawal details! Ask the
// user to authorize the operation (here CAPTCHA).
return (
<WithdrawalConfirmationQuestion
withdrawUri={withdrawUri}
onConfirmed={() => {
notifyInfo(i18n.str`Operation confirmed`);
onConfirmed();
}}
onAborted={() => {
notifyInfo(i18n.str`Operation canceled`);
onAborted();
}}
clearCurrentWithdrawal()
onContinue()
}}
/>
);
}

View File

@ -315,3 +315,39 @@ h1.nav {
margin-bottom: 1em;
}
.lds-ring {
display: inline-block;
position: relative;
width: 80px;
height: 80px;
}
.lds-ring div {
box-sizing: border-box;
display: block;
position: absolute;
width: 64px;
height: 64px;
margin: 8px;
border: 8px solid black;
border-radius: 50%;
animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
border-color: black transparent transparent transparent;
}
.lds-ring div:nth-child(1) {
animation-delay: -0.45s;
}
.lds-ring div:nth-child(2) {
animation-delay: -0.3s;
}
.lds-ring div:nth-child(3) {
animation-delay: -0.15s;
}
@keyframes lds-ring {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}

View File

@ -134,7 +134,7 @@ export function buildRequestErrorMessage(
specialCases.onClientError && specialCases.onClientError(cause.status);
result = {
title: title ? title : i18n.str`The server didn't accept the request`,
description: cause.payload.error.description,
description: cause?.payload?.error?.description,
debug: JSON.stringify(cause),
};
break;
@ -146,7 +146,7 @@ export function buildRequestErrorMessage(
title: title
? title
: i18n.str`The server had problems processing the request`,
description: cause.payload.error.description,
description: cause?.payload?.error?.description,
debug: JSON.stringify(cause),
};
break;
@ -154,7 +154,7 @@ export function buildRequestErrorMessage(
case ErrorType.UNREADABLE: {
result = {
title: i18n.str`Unexpected error`,
description: `Response from ${cause.info?.url} is unreadable, status: ${cause.status}`,
description: `Response from ${cause?.info?.url} is unreadable, status: ${cause?.status}`,
debug: JSON.stringify(cause),
};
break;