commit cb0386ea00063a1569cba2d79ffc2d7bd0e8a44e
parent 896eccc3240d20bffbf8cde4eaaf2eb28fa27b50
Author: Sebastian <sebasjm@gmail.com>
Date: Mon, 15 Jul 2024 16:02:28 -0300
show transfer details on fast form
Diffstat:
6 files changed, 196 insertions(+), 19 deletions(-)
diff --git a/packages/bank-ui/src/Routing.tsx b/packages/bank-ui/src/Routing.tsx
@@ -148,9 +148,7 @@ function PublicRounting({
}
switch (location.name) {
- case undefined: {
- return <Fragment />;
- }
+ case undefined:
case "login": {
return (
<Fragment>
@@ -281,9 +279,6 @@ function PrivateRouting({
}, [location]);
switch (location.name) {
- case undefined: {
- return <Fragment />;
- }
case "operationDetails": {
return (
<WithdrawalOperationPage
@@ -472,6 +467,7 @@ function PrivateRouting({
/>
);
}
+ case undefined:
case "home": {
if (isAdmin) {
return (
diff --git a/packages/bank-ui/src/pages/OperationState/index.ts b/packages/bank-ui/src/pages/OperationState/index.ts
@@ -17,6 +17,7 @@
import {
AbsoluteTime,
AmountJson,
+ PaytoUri,
TalerCoreBankErrorsByMethod,
TalerError,
WithdrawUriResult,
@@ -118,6 +119,12 @@ export namespace State {
TalerCoreBankErrorsByMethod<"confirmWithdrawalById"> | undefined
>);
error: undefined;
+ details: {
+ account: PaytoUri;
+ reserve: string;
+ username: string;
+ amount?: AmountJson;
+ };
id: string;
}
export interface Aborted {
diff --git a/packages/bank-ui/src/pages/OperationState/state.ts b/packages/bank-ui/src/pages/OperationState/state.ts
@@ -140,13 +140,19 @@ export function useComponentState({
return (): utils.RecursiveState<State> => {
const result = useWithdrawalDetails(withdrawalOperationId);
- const shouldCreateNewOperation = result && !(result instanceof TalerError);
+
+ const shouldCreateNewOperation =
+ result &&
+ (result instanceof TalerError ||
+ result.type === "fail" ||
+ result.body.status === "aborted" ||
+ result.body.status === "confirmed");
useEffect(() => {
if (shouldCreateNewOperation) {
doSilentStart();
}
- }, []);
+ }, [shouldCreateNewOperation]);
if (!result) {
return {
status: "loading",
@@ -236,6 +242,12 @@ export function useComponentState({
status: "need-confirmation",
error: undefined,
routeHere,
+ details: {
+ account,
+ reserve: data.selected_reserve_pub,
+ username: data.username,
+ amount: !data.amount ? undefined : Amounts.parse(data.amount),
+ },
onAuthorizationRequired,
account: data.username,
id: withdrawalOperationId,
diff --git a/packages/bank-ui/src/pages/OperationState/views.tsx b/packages/bank-ui/src/pages/OperationState/views.tsx
@@ -16,6 +16,7 @@
import {
AbsoluteTime,
+ Amounts,
HttpStatusCode,
TalerErrorCode,
TranslatedString,
@@ -26,6 +27,7 @@ import {
Attention,
LocalNotificationBanner,
notifyInfo,
+ useBankCoreApiContext,
useLocalNotification,
useTalerWalletIntegrationAPI,
useTranslationContext,
@@ -37,7 +39,7 @@ 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";
+import { RenderAmount, doAutoFocus } from "../PaytoWireTransferForm.js";
export function InvalidPaytoView({ payto }: State.InvalidPayto) {
return <div>Payto from server is not valid "{payto}"</div>;
@@ -54,6 +56,7 @@ export function NeedConfirmationView({
onConfirm: doConfirm,
routeHere,
account,
+ details,
id,
onAuthorizationRequired,
}: State.NeedConfirmation) {
@@ -61,6 +64,11 @@ export function NeedConfirmationView({
const [settings] = usePreferences();
const [notification, notify, errorHandler] = useLocalNotification();
const [, updateBankState] = useBankState();
+ const { config } = useBankCoreApiContext();
+ const wireFee =
+ config.wire_transfer_fees === undefined
+ ? Amounts.zeroOfCurrency(config.currency)
+ : Amounts.parseOrThrow(config.wire_transfer_fees);
async function onCancel() {
errorHandler(async () => {
@@ -182,6 +190,164 @@ export function NeedConfirmationView({
e.preventDefault();
}}
>
+ <div class="px-4 mt-4">
+ <div class="w-full">
+ <dl class="">
+ {((): VNode => {
+ if (!details.account.isKnown) {
+ return (
+ <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
+ <dt class="text-sm font-medium leading-6 text-gray-900">
+ <i18n.Translate>
+ Payment provider's account
+ </i18n.Translate>
+ </dt>
+ <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
+ {details.account.targetPath}
+ </dd>
+ </div>
+ );
+ }
+ switch (details.account.targetType) {
+ case "iban": {
+ const name = details.account.params["receiver-name"];
+ return (
+ <Fragment>
+ <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
+ <dt class="text-sm font-medium leading-6 text-gray-900">
+ <i18n.Translate>
+ Payment provider's account number
+ </i18n.Translate>
+ </dt>
+ <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
+ {details.account.iban}
+ </dd>
+ </div>
+ {name && (
+ <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
+ <dt class="text-sm font-medium leading-6 text-gray-900">
+ <i18n.Translate>
+ Payment provider's name
+ </i18n.Translate>
+ </dt>
+ <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
+ {name}
+ </dd>
+ </div>
+ )}
+ </Fragment>
+ );
+ }
+ case "x-taler-bank": {
+ const name = details.account.params["receiver-name"];
+ return (
+ <Fragment>
+ <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
+ <dt class="text-sm font-medium leading-6 text-gray-900">
+ <i18n.Translate>
+ Payment provider's account bank hostname
+ </i18n.Translate>
+ </dt>
+ <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
+ {details.account.host}
+ </dd>
+ </div>
+ <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
+ <dt class="text-sm font-medium leading-6 text-gray-900">
+ <i18n.Translate>
+ Payment provider's account id
+ </i18n.Translate>
+ </dt>
+ <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
+ {details.account.account}
+ </dd>
+ </div>
+ {name && (
+ <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
+ <dt class="text-sm font-medium leading-6 text-gray-900">
+ <i18n.Translate>
+ Payment provider's name
+ </i18n.Translate>
+ </dt>
+ <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
+ {name}
+ </dd>
+ </div>
+ )}
+ </Fragment>
+ );
+ }
+ case "bitcoin": {
+ const name = details.account.params["receiver-name"];
+ return (
+ <Fragment>
+ <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
+ <dt class="text-sm font-medium leading-6 text-gray-900">
+ <i18n.Translate>
+ Payment provider's account address
+ </i18n.Translate>
+ </dt>
+ <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
+ {details.account.address}
+ </dd>
+ </div>
+ {name && (
+ <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
+ <dt class="text-sm font-medium leading-6 text-gray-900">
+ <i18n.Translate>
+ Payment provider's name
+ </i18n.Translate>
+ </dt>
+ <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
+ {name}
+ </dd>
+ </div>
+ )}
+ </Fragment>
+ );
+ }
+ default: {
+ assertUnreachable(details.account);
+ }
+ }
+ })()}
+ <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
+ <dt class="text-sm font-medium leading-6 text-gray-900">
+ <i18n.Translate>Amount</i18n.Translate>
+ </dt>
+ <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
+ {details.amount !== undefined ? (
+ <RenderAmount
+ value={details.amount}
+ spec={config.currency_specification}
+ />
+ ) : (
+ <i18n.Translate>
+ No amount specified yet.
+ </i18n.Translate>
+ )}
+ </dd>
+ </div>
+ {Amounts.isZero(wireFee) ? undefined : (
+ <Fragment>
+ <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
+ <dt class="text-sm font-medium leading-6 text-gray-900">
+ <i18n.Translate>Cost</i18n.Translate>
+ </dt>
+ <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
+ <RenderAmount
+ value={wireFee}
+ negative
+ withColor
+ spec={config.currency_specification}
+ />
+ </dd>
+ </div>
+ </Fragment>
+ )}
+ </dl>
+ </div>
+ </div>
<div class="flex items-center justify-between gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8">
<button
type="button"
diff --git a/packages/bank-ui/src/pages/PaymentOptions.tsx b/packages/bank-ui/src/pages/PaymentOptions.tsx
@@ -41,29 +41,25 @@ function ShowOperationPendingTag({
const pending =
!loading &&
!error &&
- (result.body.status === "pending" || result.body.status === "selected") &&
+ result.body.status === "selected" &&
+ // (result.body.status === "pending" || result.body.status === "selected") &&
credentials.status === "loggedIn" &&
credentials.username === result.body.username;
- useEffect(() => {
- if (!loading && !pending && onOperationAlreadyCompleted) {
- onOperationAlreadyCompleted();
- }
- }, [loading, pending]);
if (error || !pending) {
return <Fragment />;
}
return (
- <span class="flex items-center gap-x-1.5 w-fit rounded-md bg-green-100 px-2 py-1 text-xs font-medium text-green-700 whitespace-pre">
+ <span class="flex items-center gap-x-1.5 w-fit rounded-md bg-yellow-100 px-2 py-1 text-xs font-medium text-yellow-700 whitespace-pre">
<svg
- class="h-1.5 w-1.5 fill-green-500"
+ class="h-1.5 w-1.5 fill-yellow-500"
viewBox="0 0 6 6"
aria-hidden="true"
>
<circle cx="3" cy="3" r="3" />
</svg>
- <i18n.Translate>Operation ready</i18n.Translate>
+ <i18n.Translate>Pending operation</i18n.Translate>
</span>
);
}
diff --git a/packages/bank-ui/src/pages/WalletWithdrawForm.tsx b/packages/bank-ui/src/pages/WalletWithdrawForm.tsx
@@ -355,7 +355,7 @@ export function WalletWithdrawForm({
<div class="grid grid-cols-1 gap-x-8 gap-y-8 pt-6 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg">
<div class="px-4 sm:px-0">
<h2 class="text-base font-semibold leading-7 text-gray-900">
- <i18n.Translate>Prepare your Taler wallet</i18n.Translate>
+ <i18n.Translate>Use your Taler wallet</i18n.Translate>
</h2>
<p class="mt-1 text-sm text-gray-500">
<i18n.Translate>