/*
This file is part of GNU Taler
(C) 2022-2024 Taler Systems S.A.
GNU Taler is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see
*/
import {
AbsoluteTime,
HttpStatusCode,
TalerErrorCode,
TranslatedString,
assertUnreachable,
stringifyWithdrawUri,
} from "@gnu-taler/taler-util";
import {
Attention,
LocalNotificationBanner,
notifyInfo,
useLocalNotification,
useTalerWalletIntegrationAPI,
useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useEffect } from "preact/hooks";
import { QR } from "../../components/QR.js";
import { useBankState } from "../../hooks/bank-state.js";
import { usePreferences } from "../../hooks/preferences.js";
import { ShouldBeSameUser } from "../WithdrawalConfirmationQuestion.js";
import { State } from "./index.js";
import { doAutoFocus } from "../PaytoWireTransferForm.js";
export function InvalidPaytoView({ payto }: State.InvalidPayto) {
return
Payto from server is not valid "{payto}"
;
}
export function InvalidWithdrawalView({ uri }: State.InvalidWithdrawal) {
return
Withdrawal uri from server is not valid "{uri}"
;
}
export function InvalidReserveView({ reserve }: State.InvalidReserve) {
return
Reserve from server is not valid "{reserve}"
;
}
export function NeedConfirmationView({
onAbort: doAbort,
onConfirm: doConfirm,
routeHere,
account,
id,
onAuthorizationRequired,
}: State.NeedConfirmation) {
const { i18n } = useTranslationContext();
const [settings] = usePreferences();
const [notification, notify, errorHandler] = useLocalNotification();
const [, updateBankState] = useBankState();
async function onCancel() {
errorHandler(async () => {
if (!doAbort) return;
const resp = await doAbort();
if (!resp) return;
switch (resp.case) {
case HttpStatusCode.Conflict:
return notify({
type: "error",
title: i18n.str`The reserve operation has been confirmed previously and can't be aborted`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
when: AbsoluteTime.now(),
});
case HttpStatusCode.BadRequest:
return notify({
type: "error",
title: i18n.str`The operation id is invalid.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
when: AbsoluteTime.now(),
});
case HttpStatusCode.NotFound:
return notify({
type: "error",
title: i18n.str`The operation was not found.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
when: AbsoluteTime.now(),
});
default:
assertUnreachable(resp);
}
});
}
async function onConfirm() {
errorHandler(async () => {
if (!doConfirm) return;
const resp = await doConfirm();
if (!resp) {
if (!settings.showWithdrawalSuccess) {
notifyInfo(i18n.str`Wire transfer completed!`);
}
return;
}
switch (resp.case) {
case TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT:
return notify({
type: "error",
title: i18n.str`The withdrawal has been aborted previously and can't be confirmed`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
when: AbsoluteTime.now(),
});
case TalerErrorCode.BANK_CONFIRM_INCOMPLETE:
return notify({
type: "error",
title: i18n.str`The withdrawal operation can't be confirmed before a wallet accepted the transaction.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
when: AbsoluteTime.now(),
});
case HttpStatusCode.BadRequest:
return notify({
type: "error",
title: i18n.str`The operation id is invalid.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
when: AbsoluteTime.now(),
});
case HttpStatusCode.NotFound:
return notify({
type: "error",
title: i18n.str`The operation was not found.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
when: AbsoluteTime.now(),
});
case TalerErrorCode.BANK_UNALLOWED_DEBIT:
return notify({
type: "error",
title: i18n.str`Your balance is not enough.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
when: AbsoluteTime.now(),
});
case HttpStatusCode.Accepted: {
updateBankState("currentChallenge", {
operation: "confirm-withdrawal",
id: String(resp.body.challenge_id),
sent: AbsoluteTime.never(),
location: routeHere.url({ wopid: id }),
request: id,
});
return onAuthorizationRequired();
}
default:
assertUnreachable(resp);
}
});
}
return (
);
}
export function ReadyView({
uri,
focus,
onAbort: doAbort,
}: State.Ready): VNode {
const { i18n } = useTranslationContext();
const walletInegrationApi = useTalerWalletIntegrationAPI();
const [notification, notify, errorHandler] = useLocalNotification();
const talerWithdrawUri = stringifyWithdrawUri(uri);
useEffect(() => {
walletInegrationApi.publishTalerAction(uri);
}, []);
async function onAbort() {
errorHandler(async () => {
const hasError = await doAbort();
if (!hasError) return;
switch (hasError.case) {
case HttpStatusCode.Conflict:
return notify({
type: "error",
title: i18n.str`The reserve operation has been confirmed previously and can't be aborted`,
description: hasError.detail.hint as TranslatedString,
debug: hasError.detail,
when: AbsoluteTime.now(),
});
case HttpStatusCode.BadRequest:
return notify({
type: "error",
title: i18n.str`The operation id is invalid.`,
description: hasError.detail.hint as TranslatedString,
debug: hasError.detail,
when: AbsoluteTime.now(),
});
case HttpStatusCode.NotFound:
return notify({
type: "error",
title: i18n.str`The operation was not found.`,
description: hasError.detail.hint as TranslatedString,
debug: hasError.detail,
when: AbsoluteTime.now(),
});
default:
assertUnreachable(hasError);
}
});
}
return (
If you have a Taler wallet installed on this device
Your wallet will display the details of the transaction
including the fees (if applicable). If you do not yet have a
wallet, please follow the instructions
{" "}
on this page
.