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

View File

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

View File

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

View File

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

View File

@ -24,6 +24,7 @@ import { Fragment, VNode, h } from "preact";
import { Loading } from "../components/Loading.js"; import { Loading } from "../components/Loading.js";
import { useWithdrawalDetails } from "../hooks/access.js"; import { useWithdrawalDetails } from "../hooks/access.js";
import { notifyInfo } from "../hooks/notification.js"; import { notifyInfo } from "../hooks/notification.js";
import { useSettings } from "../hooks/settings.js";
import { handleNotOkResult } from "./HomePage.js"; import { handleNotOkResult } from "./HomePage.js";
import { QrCodeSection } from "./QrCodeSection.js"; import { QrCodeSection } from "./QrCodeSection.js";
import { WithdrawalConfirmationQuestion } from "./WithdrawalConfirmationQuestion.js"; import { WithdrawalConfirmationQuestion } from "./WithdrawalConfirmationQuestion.js";
@ -32,8 +33,7 @@ const logger = new Logger("WithdrawalQRCode");
interface Props { interface Props {
withdrawUri: WithdrawUriResult; withdrawUri: WithdrawUriResult;
onAborted: () => void; onContinue: () => void;
onConfirmed: () => void;
onLoadNotOk: () => void; onLoadNotOk: () => void;
} }
/** /**
@ -43,10 +43,14 @@ interface Props {
*/ */
export function WithdrawalQRCode({ export function WithdrawalQRCode({
withdrawUri, withdrawUri,
onConfirmed, onContinue,
onAborted,
onLoadNotOk, onLoadNotOk,
}: Props): VNode { }: Props): VNode {
const [settings, updateSettings] = useSettings();
function clearCurrentWithdrawal(): void {
updateSettings("currentWithdrawalOperationId", undefined);
onContinue();
}
const { i18n } = useTranslationContext(); const { i18n } = useTranslationContext();
const result = useWithdrawalDetails(withdrawUri.withdrawalOperationId); const result = useWithdrawalDetails(withdrawUri.withdrawalOperationId);
if (!result.ok) { if (!result.ok) {
@ -64,13 +68,64 @@ export function WithdrawalQRCode({
} }
const { data } = result; const { data } = result;
logger.trace("withdrawal status", data); if (data.aborted) {
if (data.aborted || data.confirmation_done) { return <section id="main" class="content">
// signal that this withdrawal is aborted <h1 class="nav">{i18n.str`Operation aborted`}</h1>
// will redirect to account info <section>
notifyInfo(i18n.str`Operation completed`); <p>
onAborted(); <i18n.Translate>
return <Loading />; 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) { if (!data.selection_done) {
@ -79,24 +134,20 @@ export function WithdrawalQRCode({
withdrawUri={withdrawUri} withdrawUri={withdrawUri}
onAborted={() => { onAborted={() => {
notifyInfo(i18n.str`Operation canceled`); notifyInfo(i18n.str`Operation canceled`);
onAborted(); clearCurrentWithdrawal()
onContinue()
}} }}
/> />
); );
} }
// Wallet POSTed the withdrawal details! Ask the
// user to authorize the operation (here CAPTCHA).
return ( return (
<WithdrawalConfirmationQuestion <WithdrawalConfirmationQuestion
withdrawUri={withdrawUri} withdrawUri={withdrawUri}
onConfirmed={() => {
notifyInfo(i18n.str`Operation confirmed`);
onConfirmed();
}}
onAborted={() => { onAborted={() => {
notifyInfo(i18n.str`Operation canceled`); notifyInfo(i18n.str`Operation canceled`);
onAborted(); clearCurrentWithdrawal()
onContinue()
}} }}
/> />
); );

View File

@ -315,3 +315,39 @@ h1.nav {
margin-bottom: 1em; 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); specialCases.onClientError && specialCases.onClientError(cause.status);
result = { result = {
title: title ? title : i18n.str`The server didn't accept the request`, 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), debug: JSON.stringify(cause),
}; };
break; break;
@ -146,7 +146,7 @@ export function buildRequestErrorMessage(
title: title title: title
? title ? title
: i18n.str`The server had problems processing the request`, : i18n.str`The server had problems processing the request`,
description: cause.payload.error.description, description: cause?.payload?.error?.description,
debug: JSON.stringify(cause), debug: JSON.stringify(cause),
}; };
break; break;
@ -154,7 +154,7 @@ export function buildRequestErrorMessage(
case ErrorType.UNREADABLE: { case ErrorType.UNREADABLE: {
result = { result = {
title: i18n.str`Unexpected error`, 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), debug: JSON.stringify(cause),
}; };
break; break;