fulfillment url on payment ticket

This commit is contained in:
Sebastian 2022-03-17 15:00:34 -03:00
parent b650750bcc
commit 49948eea98
No known key found for this signature in database
GPG Key ID: BE4FF68352439FC1
8 changed files with 109 additions and 62 deletions

View File

@ -20,7 +20,7 @@ import { h, VNode } from "preact";
export type Kind = "positive" | "negative" | "neutral";
interface Props {
title: VNode;
text: AmountLike;
text: VNode | string;
kind: Kind;
big?: boolean;
}

View File

@ -47,6 +47,8 @@ import { Part } from "../components/Part";
import { QR } from "../components/QR";
import {
ButtonSuccess,
Link,
LinkPrimary,
LinkSuccess,
SmallLightText,
SuccessBox,
@ -406,6 +408,11 @@ export function PaymentRequestView({
)}
</section>
<ButtonsSection />
<section>
<Link upperCased>
<i18n.Translate>Cancel</i18n.Translate>
</Link>
</section>
</WalletAction>
);
}

View File

@ -34,7 +34,7 @@ import { AddNewActionView } from "../wallet/AddNewActionView";
import * as wxApi from "../wxApi";
import { NoBalanceHelp } from "./NoBalanceHelp";
interface Props {
export interface Props {
goToWalletDeposit: (currency: string) => void;
goToWalletHistory: (currency: string) => void;
goToWalletManualWithdraw: () => void;

View File

@ -38,11 +38,8 @@ import { useTalerActionURL } from "./hooks/useTalerActionURL";
import { strings } from "./i18n/strings";
import { Pages, PopupNavBar } from "./NavigationBar";
import { BalancePage } from "./popup/BalancePage";
import { DeveloperPage } from "./popup/DeveloperPage";
import { TalerActionFound } from "./popup/TalerActionFound";
import { BackupPage } from "./wallet/BackupPage";
import { ExchangeAddPage } from "./wallet/ExchangeAddPage";
import { ProviderAddPage } from "./wallet/ProviderAddPage";
import { ProviderDetailPage } from "./wallet/ProviderDetailPage";
function main(): void {

View File

@ -49,22 +49,6 @@ interface Props {
onAddProvider: () => void;
}
// interface BackupStatus {
// deviceName: string;
// providers: ProviderInfo[];
// }
// async function getBackupInfoOrdered(): BackupStatus {
// //create a first list of backup info by currency
// const status = await wxApi.getBackupInfo();
// return { deviceName: status.deviceId, providers };
// }
// async function sync() {
// await wxApi.syncAllProviders();
// }
export function BackupPage({ onAddProvider }: Props): VNode {
const { i18n } = useTranslationContext();
const status = useAsyncAsHook(wxApi.getBackupInfo);

View File

@ -27,7 +27,6 @@ import { SelectList } from "../components/SelectList";
import {
BoldLight,
ButtonPrimary,
ButtonSuccess,
Centered,
Input,
InputWithLabel,
@ -35,25 +34,21 @@ import {
LinkPrimary,
} from "../components/styled";
import { useTranslationContext } from "../context/translation";
import { Pages } from "../NavigationBar";
export interface Props {
error: string | undefined;
initialAmount?: string;
exchangeList: Record<string, string>;
onCreate: (exchangeBaseUrl: string, amount: AmountJson) => Promise<void>;
onAddExchange: () => void;
initialCurrency?: string;
}
export function CreateManualWithdraw({
initialAmount,
exchangeList,
error,
initialCurrency,
onCreate,
onAddExchange,
}: Props): VNode {
const { i18n } = useTranslationContext();
export function useComponentState(
exchangeList: Record<string, string>,
initialAmount: string | undefined,
initialCurrency: string | undefined,
) {
const exchangeSelectList = Object.keys(exchangeList);
const currencySelectList = Object.values(exchangeList);
const exchangeMap = exchangeSelectList.reduce(
@ -74,10 +69,12 @@ export function CreateManualWithdraw({
? exchangeSelectList[foundExchangeForCurrency]
: exchangeSelectList.length > 0
? exchangeSelectList[0]
: "";
: undefined;
const [exchange, setExchange] = useState(initialExchange || "");
const [currency, setCurrency] = useState(exchangeList[initialExchange] ?? "");
const [currency, setCurrency] = useState(
initialExchange ? exchangeList[initialExchange] : "",
);
const [amount, setAmount] = useState(initialAmount || "");
const parsedAmount = Amounts.parse(`${currency}:${amount}`);
@ -97,8 +94,49 @@ export function CreateManualWithdraw({
setExchange("");
}
}
return {
initialExchange,
currency: {
list: currencyMap,
value: currency,
onChange: changeCurrency,
},
exchange: {
list: exchangeMap,
value: exchange,
onChange: changeExchange,
},
amount: {
value: amount,
onInput: (e: string) => setAmount(e),
},
parsedAmount,
};
}
if (!initialExchange) {
interface InputHandler {
value: string;
onInput: (s: string) => void;
}
interface SelectInputHandler {
list: Record<string, string>;
value: string;
onChange: (s: string) => void;
}
export function CreateManualWithdraw({
initialAmount,
exchangeList,
error,
initialCurrency,
onCreate,
}: Props): VNode {
const { i18n } = useTranslationContext();
const state = useComponentState(exchangeList, initialAmount, initialCurrency);
if (!state.initialExchange) {
return (
<section>
<h2>
@ -115,9 +153,12 @@ export function CreateManualWithdraw({
<BoldLight>
<i18n.Translate>No exchange configured</i18n.Translate>
</BoldLight>
<ButtonSuccess onClick={onAddExchange}>
<i18n.Translate>Add exchange</i18n.Translate>
</ButtonSuccess>
<LinkPrimary
href={Pages.settings_exchange_add}
style={{ marginLeft: "auto" }}
>
<i18n.Translate>Add Exchange</i18n.Translate>
</LinkPrimary>
</Centered>
</section>
);
@ -146,37 +187,38 @@ export function CreateManualWithdraw({
<Input>
<SelectList
label={<i18n.Translate>Currency</i18n.Translate>}
list={currencyMap}
name="currency"
value={currency}
onChange={changeCurrency}
{...state.currency}
/>
</Input>
<Input>
<SelectList
label={<i18n.Translate>Exchange</i18n.Translate>}
list={exchangeMap}
name="currency"
value={exchange}
onChange={changeExchange}
name="exchange"
{...state.exchange}
/>
</Input>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<LinkPrimary onClick={onAddExchange} style={{ marginLeft: "auto" }}>
<LinkPrimary
href={Pages.settings_exchange_add}
style={{ marginLeft: "auto" }}
>
<i18n.Translate>Add Exchange</i18n.Translate>
</LinkPrimary>
</div>
{currency && (
<InputWithLabel invalid={!!amount && !parsedAmount}>
{state.currency.value && (
<InputWithLabel
invalid={!!state.amount.value && !state.parsedAmount}
>
<label>
<i18n.Translate>Amount</i18n.Translate>
</label>
<div>
<span>{currency}</span>
<span>{state.currency.value}</span>
<input
type="number"
value={amount}
onInput={(e) => setAmount(e.currentTarget.value)}
value={state.amount.value}
onInput={(e) => state.amount.onInput(e.currentTarget.value)}
/>
</div>
</InputWithLabel>
@ -186,8 +228,8 @@ export function CreateManualWithdraw({
<footer>
<div />
<ButtonPrimary
disabled={!parsedAmount || !exchange}
onClick={() => onCreate(exchange, parsedAmount!)}
disabled={!state.parsedAmount || !state.exchange.value}
onClick={() => onCreate(state.exchange.value, state.parsedAmount!)}
>
<i18n.Translate>Start withdrawal</i18n.Translate>
</ButtonPrimary>

View File

@ -73,12 +73,6 @@ export function ManualWithdrawPage({ currency, onCancel }: Props): VNode {
}
}
const [addingExchange, setAddingExchange] = useState(false);
if (addingExchange) {
return <ExchangeAddPage onBack={() => setAddingExchange(false)} />;
}
if (success) {
return (
<ReserveCreated
@ -117,7 +111,6 @@ export function ManualWithdrawPage({ currency, onCancel }: Props): VNode {
return (
<CreateManualWithdraw
onAddExchange={() => setAddingExchange(true)}
error={error}
exchangeList={exchangeList}
onCreate={doCreate}

View File

@ -369,7 +369,19 @@ export function TransactionView({
/>
<Part
title={<i18n.Translate>Purchase</i18n.Translate>}
text={transaction.info.summary}
text={
transaction.info.fulfillmentUrl ? (
<a
href={transaction.info.fulfillmentUrl}
target="_bank"
rel="noreferrer"
>
{transaction.info.summary}
</a>
) : (
transaction.info.summary
)
}
kind="neutral"
/>
<Part
@ -542,7 +554,19 @@ export function TransactionView({
/>
<Part
title={<i18n.Translate>Purchase</i18n.Translate>}
text={transaction.info.summary}
text={
transaction.info.fulfillmentUrl ? (
<a
href={transaction.info.fulfillmentUrl}
target="_bank"
rel="noreferrer"
>
{transaction.info.summary}
</a>
) : (
transaction.info.summary
)
}
kind="neutral"
/>
<Part