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"; export type Kind = "positive" | "negative" | "neutral";
interface Props { interface Props {
title: VNode; title: VNode;
text: AmountLike; text: VNode | string;
kind: Kind; kind: Kind;
big?: boolean; big?: boolean;
} }

View File

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

View File

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

View File

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

View File

@ -49,22 +49,6 @@ interface Props {
onAddProvider: () => void; 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 { export function BackupPage({ onAddProvider }: Props): VNode {
const { i18n } = useTranslationContext(); const { i18n } = useTranslationContext();
const status = useAsyncAsHook(wxApi.getBackupInfo); const status = useAsyncAsHook(wxApi.getBackupInfo);

View File

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

View File

@ -369,7 +369,19 @@ export function TransactionView({
/> />
<Part <Part
title={<i18n.Translate>Purchase</i18n.Translate>} 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" kind="neutral"
/> />
<Part <Part
@ -542,7 +554,19 @@ export function TransactionView({
/> />
<Part <Part
title={<i18n.Translate>Purchase</i18n.Translate>} 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" kind="neutral"
/> />
<Part <Part