destination ui

This commit is contained in:
Sebastian 2022-08-15 21:18:39 -03:00
parent 004b1544f3
commit cdc8e9afdf
No known key found for this signature in database
GPG Key ID: BE4FF68352439FC1
19 changed files with 450 additions and 61 deletions

View File

@ -85,8 +85,8 @@ export const Pages = {
balanceHistory: pageDefinition<{ currency?: string }>( balanceHistory: pageDefinition<{ currency?: string }>(
"/balance/history/:currency?", "/balance/history/:currency?",
), ),
balanceManualWithdraw: pageDefinition<{ currency?: string }>( balanceManualWithdraw: pageDefinition<{ amount?: string }>(
"/balance/manual-withdraw/:currency?", "/balance/manual-withdraw/:amount?",
), ),
balanceDeposit: pageDefinition<{ currency: string }>( balanceDeposit: pageDefinition<{ currency: string }>(
"/balance/deposit/:currency", "/balance/deposit/:currency",
@ -94,12 +94,8 @@ export const Pages = {
balanceTransaction: pageDefinition<{ tid: string }>( balanceTransaction: pageDefinition<{ tid: string }>(
"/balance/transaction/:tid", "/balance/transaction/:tid",
), ),
sendCash: pageDefinition<{ currency?: string }>( sendCash: pageDefinition<{ amount?: string }>("/destination/send/:amount"),
"/destination/send/:currency?", receiveCash: pageDefinition<{ amount?: string }>("/destination/get/:amount?"),
),
receiveCash: pageDefinition<{ currency?: string }>(
"/destination/get/:currency?",
),
dev: "/dev", dev: "/dev",
backup: "/backup", backup: "/backup",

View File

@ -842,10 +842,12 @@ interface SvgIconProps {
title: string; title: string;
color: string; color: string;
onClick?: any; onClick?: any;
transform?: string;
} }
export const SvgIcon = styled.div<SvgIconProps>` export const SvgIcon = styled.div<SvgIconProps>`
& > svg { & > svg {
fill: ${({ color }) => color}; fill: ${({ color }) => color};
transform: ${({ transform }) => (transform ? transform : "")};
} }
width: 24px; width: 24px;
height: 24px; height: 24px;

View File

@ -27,7 +27,7 @@ import { LoadingUriView, BaseView } from "./views.js";
export interface Props { export interface Props {
talerPayUri?: string; talerPayUri?: string;
goToWalletManualWithdraw: (currency?: string) => Promise<void>; goToWalletManualWithdraw: (amount?: string) => Promise<void>;
cancel: () => Promise<void>; cancel: () => Promise<void>;
} }
@ -55,7 +55,7 @@ export namespace State {
amount: AmountJson; amount: AmountJson;
uri: string; uri: string;
error: undefined; error: undefined;
goToWalletManualWithdraw: (currency?: string) => Promise<void>; goToWalletManualWithdraw: (amount?: string) => Promise<void>;
cancel: () => Promise<void>; cancel: () => Promise<void>;
} }
export interface NoBalanceForCurrency extends BaseInfo { export interface NoBalanceForCurrency extends BaseInfo {

View File

@ -393,7 +393,9 @@ function ButtonsSection({
<Button <Button
variant="contained" variant="contained"
color="success" color="success"
onClick={() => goToWalletManualWithdraw(state.amount.currency)} onClick={() =>
goToWalletManualWithdraw(Amounts.stringify(state.amount))
}
> >
<i18n.Translate>Get digital cash</i18n.Translate> <i18n.Translate>Get digital cash</i18n.Translate>
</Button> </Button>

View File

@ -129,7 +129,6 @@ export function SuccessView(state: State.Success): VNode {
title="Edit" title="Edit"
dangerouslySetInnerHTML={{ __html: editIcon }} dangerouslySetInnerHTML={{ __html: editIcon }}
color="black" color="black"
onClick={() => console.log("ok")}
/> />
</div> </div>
} }

View File

@ -34,11 +34,9 @@ export function useDiagnostics(): [WalletDiagnostics | undefined, boolean] {
}, 1000); }, 1000);
const doFetch = async (): Promise<void> => { const doFetch = async (): Promise<void> => {
const d = await wxApi.getDiagnostics(); const d = await wxApi.getDiagnostics();
console.log("got diagnostics", d);
gotDiagnostics = true; gotDiagnostics = true;
setDiagnostics(d); setDiagnostics(d);
}; };
console.log("fetching diagnostics");
doFetch(); doFetch();
}, []); }, []);
return [diagnostics, timedOut]; return [diagnostics, timedOut];

View File

@ -33,6 +33,10 @@ export default {
const Stack = styled.div` const Stack = styled.div`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
& > button {
margin: 14px;
}
background-color: white;
`; `;
export const BasicExample = (): VNode => ( export const BasicExample = (): VNode => (

View File

@ -43,6 +43,9 @@ export interface Props {
placeholder?: string; placeholder?: string;
required?: boolean; required?: boolean;
startAdornment?: VNode;
endAdornment?: VNode;
//FIXME: change to "grabFocus" //FIXME: change to "grabFocus"
// focused?: boolean; // focused?: boolean;
rows?: number; rows?: number;
@ -75,7 +78,6 @@ export function TextField({
}: Props): VNode { }: Props): VNode {
// htmlFor={id} id={inputLabelId} // htmlFor={id} id={inputLabelId}
const Input = select ? selectVariant[variant] : inputVariant[variant]; const Input = select ? selectVariant[variant] : inputVariant[variant];
// console.log("variant", Input);
return ( return (
<FormControl {...props}> <FormControl {...props}>
{label && <InputLabel>{label}</InputLabel>} {label && <InputLabel>{label}</InputLabel>}

View File

@ -53,6 +53,8 @@ export function InputBaseRoot({
multiline, multiline,
focused, focused,
fullWidth, fullWidth,
startAdornment,
endAdornment,
children, children,
}: any): VNode { }: any): VNode {
const fcs = useFormControl({}); const fcs = useFormControl({});
@ -61,6 +63,8 @@ export function InputBaseRoot({
data-disabled={disabled} data-disabled={disabled}
data-focused={focused} data-focused={focused}
data-multiline={multiline} data-multiline={multiline}
data-hasStart={!!startAdornment}
data-hasEnd={!!endAdornment}
data-error={error} data-error={error}
class={[ class={[
_class, _class,
@ -156,22 +160,28 @@ export function InputBaseComponent({
multiline, multiline,
type, type,
class: _class, class: _class,
startAdornment,
endAdornment,
...props ...props
}: any): VNode { }: any): VNode {
return ( return (
<input <Fragment>
disabled={disabled} {startAdornment}
type={type} <input
class={[ disabled={disabled}
componentStyle, type={type}
_class, class={[
disabled && componentDisabledStyle, componentStyle,
size === "small" && componentSmallStyle, _class,
// multiline && componentMultilineStyle, disabled && componentDisabledStyle,
type === "search" && searchStyle, size === "small" && componentSmallStyle,
].join(" ")} // multiline && componentMultilineStyle,
{...props} type === "search" && searchStyle,
/> ].join(" ")}
{...props}
/>
{endAdornment}
</Fragment>
); );
} }
@ -388,7 +398,6 @@ export function TextareaAutoSize({
getStyleValue(computedStyle, "border-bottom-width") + getStyleValue(computedStyle, "border-bottom-width") +
getStyleValue(computedStyle, "border-top-width"); getStyleValue(computedStyle, "border-top-width");
// console.log(boxSizing, padding, border);
// The height of the inner content // The height of the inner content
const innerHeight = inputShallow.scrollHeight; const innerHeight = inputShallow.scrollHeight;
@ -412,7 +421,6 @@ export function TextareaAutoSize({
outerHeight + (boxSizing === "border-box" ? padding + border : 0); outerHeight + (boxSizing === "border-box" ? padding + border : 0);
const overflow = Math.abs(outerHeight - innerHeight) <= 1; const overflow = Math.abs(outerHeight - innerHeight) <= 1;
console.log("height", outerHeight, minRows, maxRows);
setState((prevState) => { setState((prevState) => {
// Need a large enough difference to update the height. // Need a large enough difference to update the height.
// This prevents infinite rendering loop. // This prevents infinite rendering loop.

View File

@ -27,7 +27,6 @@ export interface Props {
defaultValue?: string; defaultValue?: string;
disabled?: boolean; disabled?: boolean;
disableUnderline?: boolean; disableUnderline?: boolean;
endAdornment?: VNode;
error?: boolean; error?: boolean;
fullWidth?: boolean; fullWidth?: boolean;
id?: string; id?: string;
@ -42,6 +41,7 @@ export interface Props {
required?: boolean; required?: boolean;
rows?: number; rows?: number;
startAdornment?: VNode; startAdornment?: VNode;
endAdornment?: VNode;
type?: string; type?: string;
value?: string; value?: string;
} }
@ -108,6 +108,9 @@ const filledRootStyle = css`
&[data-multiline] { &[data-multiline] {
padding: 25px 12px 8px; padding: 25px 12px 8px;
} }
/* &[data-hasStart] {
padding-left: 25px;
} */
`; `;
const underlineStyle = css` const underlineStyle = css`

View File

@ -40,7 +40,6 @@ const api: PlatformAPI = {
function waitAndNotify(): void { function waitAndNotify(): void {
total--; total--;
if (total < 1) { if (total < 1) {
console.log("done");
fn(); fn();
} }
} }

View File

@ -63,7 +63,6 @@ function notifyWhenAppIsReady(callback: () => void): void {
function redirectTabToWalletPage(tabId: number, page: string): void { function redirectTabToWalletPage(tabId: number, page: string): void {
const url = chrome.runtime.getURL(`/static/wallet.html#${page}`); const url = chrome.runtime.getURL(`/static/wallet.html#${page}`);
console.log("redirecting tabId: ", tabId, " to: ", url);
chrome.tabs.update(tabId, { url, loadReplace: true } as any); chrome.tabs.update(tabId, { url, loadReplace: true } as any);
} }

View File

@ -75,7 +75,7 @@ export function Application(): VNode {
path={Pages.balance} path={Pages.balance}
component={BalancePage} component={BalancePage}
goToWalletManualWithdraw={() => goToWalletManualWithdraw={() =>
redirectTo(Pages.balanceManualWithdraw({})) redirectTo(Pages.receiveCash({}))
} }
goToWalletDeposit={(currency: string) => goToWalletDeposit={(currency: string) =>
redirectTo(Pages.balanceDeposit({ currency })) redirectTo(Pages.balanceDeposit({ currency }))
@ -133,6 +133,10 @@ export function Application(): VNode {
path={Pages.backupProviderAdd} path={Pages.backupProviderAdd}
component={RedirectToWalletPage} component={RedirectToWalletPage}
/> />
<Route
path={Pages.receiveCash.pattern}
component={RedirectToWalletPage}
/>
<Route path={Pages.qr} component={RedirectToWalletPage} /> <Route path={Pages.qr} component={RedirectToWalletPage} />
<Route path={Pages.settings} component={RedirectToWalletPage} /> <Route path={Pages.settings} component={RedirectToWalletPage} />
<Route <Route

View File

@ -172,7 +172,7 @@ export function BalanceView(state: State.Balances): VNode {
variant="contained" variant="contained"
onClick={state.goToWalletManualWithdraw.onClick} onClick={state.goToWalletManualWithdraw.onClick}
> >
<i18n.Translate>Get</i18n.Translate> <i18n.Translate>Add</i18n.Translate>
</Button> </Button>
{currencyWithNonZeroAmount.length > 0 && ( {currencyWithNonZeroAmount.length > 0 && (
<MultiActionButton <MultiActionButton

View File

@ -57,6 +57,7 @@ import {
DestinationSelectionGetCash, DestinationSelectionGetCash,
DestinationSelectionSendCash, DestinationSelectionSendCash,
} from "./DestinationSelection.js"; } from "./DestinationSelection.js";
import { Amounts } from "@gnu-taler/taler-util";
export function Application(): VNode { export function Application(): VNode {
const [globalNotification, setGlobalNotification] = useState< const [globalNotification, setGlobalNotification] = useState<
@ -130,10 +131,14 @@ export function Application(): VNode {
path={Pages.balanceHistory.pattern} path={Pages.balanceHistory.pattern}
component={HistoryPage} component={HistoryPage}
goToWalletDeposit={(currency: string) => goToWalletDeposit={(currency: string) =>
redirectTo(Pages.sendCash({ currency })) redirectTo(Pages.sendCash({ amount: `${currency}:0` }))
} }
goToWalletManualWithdraw={(currency?: string) => goToWalletManualWithdraw={(currency?: string) =>
redirectTo(Pages.receiveCash({ currency })) redirectTo(
Pages.receiveCash({
amount: !currency ? undefined : `${currency}:0`,
}),
)
} }
/> />
<Route <Route
@ -143,6 +148,9 @@ export function Application(): VNode {
<Route <Route
path={Pages.receiveCash.pattern} path={Pages.receiveCash.pattern}
component={DestinationSelectionGetCash} component={DestinationSelectionGetCash}
goToWalletManualWithdraw={(amount?: string) =>
redirectTo(Pages.balanceManualWithdraw({ amount }))
}
/> />
<Route <Route
path={Pages.balanceTransaction.pattern} path={Pages.balanceTransaction.pattern}
@ -226,8 +234,8 @@ export function Application(): VNode {
<Route <Route
path={Pages.ctaPay} path={Pages.ctaPay}
component={PaymentPage} component={PaymentPage}
goToWalletManualWithdraw={(currency?: string) => goToWalletManualWithdraw={(amount?: string) =>
redirectTo(Pages.balanceManualWithdraw({ currency })) redirectTo(Pages.balanceManualWithdraw({ amount }))
} }
cancel={() => redirectTo(Pages.balance)} cancel={() => redirectTo(Pages.balance)}
/> />

View File

@ -30,8 +30,8 @@ export default {
}; };
export const GetCash = createExample(DestinationSelectionGetCash, { export const GetCash = createExample(DestinationSelectionGetCash, {
currency: "usd", amount: "usd:0",
}); });
export const SendCash = createExample(DestinationSelectionSendCash, { export const SendCash = createExample(DestinationSelectionSendCash, {
currency: "eur", amount: "eur:1",
}); });

View File

@ -14,17 +14,22 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/ */
import { Amounts } from "@gnu-taler/taler-util";
import { styled } from "@linaria/react"; import { styled } from "@linaria/react";
import { Fragment, h, VNode } from "preact"; import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
import {
InputWithLabel,
LightText,
SvgIcon,
} from "../components/styled/index.js";
import { useTranslationContext } from "../context/translation.js";
import { Button } from "../mui/Button.js";
import { Grid } from "../mui/Grid.js";
import { Paper } from "../mui/Paper.js"; import { Paper } from "../mui/Paper.js";
import { TextField } from "../mui/TextField.js";
const QrVideo = styled.video` import arrowIcon from "../svg/chevron-down.svg";
width: 80%; import bankIcon from "../svg/ri-bank-line.svg";
margin-left: auto;
margin-right: auto;
padding: 8px;
background-color: black;
`;
const Container = styled.div` const Container = styled.div`
display: flex; display: flex;
@ -36,25 +41,379 @@ const Container = styled.div`
interface Props { interface Props {
action: "send" | "get"; action: "send" | "get";
currency?: string; amount?: string;
goToWalletManualWithdraw: (amount: string) => void;
} }
export function DestinationSelectionGetCash({ currency }: Props): VNode { type Contact = {
icon: string;
name: string;
description: string;
};
const ContactTable = styled.table`
width: 100%;
& > tr > td {
padding: 8px;
& > div:not([data-disabled]):hover {
background-color: lightblue;
}
color: black;
div[data-disabled] > * {
color: gray;
}
}
& > tr:nth-child(2n) {
background: #ebebeb;
}
`;
const MediaExample = styled.div`
text-size-adjust: 100%;
color: inherit;
font-family: inherit;
font-size: inherit;
line-height: inherit;
text-transform: none;
text-align: left;
box-sizing: border-box;
align-items: center;
display: flex;
padding: 8px 8px;
&[data-disabled]:hover {
cursor: inherit;
}
cursor: pointer;
`;
const MediaLeft = styled.div`
text-size-adjust: 100%;
color: inherit;
font-family: inherit;
font-size: inherit;
line-height: inherit;
text-transform: none;
text-align: left;
box-sizing: border-box;
padding-right: 8px;
display: block;
`;
const MediaBody = styled.div`
text-size-adjust: 100%;
font-family: inherit;
text-transform: none;
text-align: left;
box-sizing: border-box;
flex: 1 1;
font-size: 14px;
font-weight: 500;
line-height: 1.42857;
`;
const MediaRight = styled.div`
text-size-adjust: 100%;
color: inherit;
font-family: inherit;
font-size: inherit;
line-height: inherit;
text-transform: none;
text-align: left;
box-sizing: border-box;
padding-left: 8px;
`;
const CircleDiv = styled.div`
box-sizing: border-box;
align-items: center;
background-position: 50%;
background-repeat: no-repeat;
background-size: cover;
border-radius: 50%;
display: flex;
justify-content: center;
margin-left: auto;
margin-right: auto;
overflow: hidden;
text-align: center;
text-decoration: none;
text-transform: uppercase;
transition: background-color 0.15s ease, border-color 0.15s ease,
color 0.15s ease;
font-size: 16px;
background-color: #86a7bd1a;
height: 40px;
line-height: 40px;
width: 40px;
border: none;
`;
function RowExample({
info,
disabled,
}: {
info: Contact;
disabled?: boolean;
}): VNode {
return (
<MediaExample data-disabled={disabled}>
<MediaLeft>
<CircleDiv>
<SvgIcon
title={info.name}
dangerouslySetInnerHTML={{ __html: info.icon }}
color="currentColor"
/>
</CircleDiv>
</MediaLeft>
<MediaBody>
<span>{info.name}</span>
<LightText>{info.description}</LightText>
</MediaBody>
<MediaRight>
<SvgIcon
title="Select this contact"
dangerouslySetInnerHTML={{ __html: arrowIcon }}
color="currentColor"
transform="rotate(-90deg)"
/>
</MediaRight>
</MediaExample>
);
}
export function DestinationSelectionGetCash({
amount: initialAmount,
goToWalletManualWithdraw,
}: Props): VNode {
const parsedInitialAmount = !initialAmount
? undefined
: Amounts.parse(initialAmount);
const parsedInitialAmountValue = !parsedInitialAmount
? ""
: Amounts.stringifyValue(parsedInitialAmount);
const currency = parsedInitialAmount?.currency;
const [amount, setAmount] = useState(parsedInitialAmountValue);
const { i18n } = useTranslationContext();
const previous1: Contact[] = [];
const previous2: Contact[] = [
{
name: "International Bank",
icon: bankIcon,
description: "account ending with 3454",
},
{
name: "Max",
icon: bankIcon,
description: "account ending with 3454",
},
{
name: "Alex",
icon: bankIcon,
description: "account ending with 3454",
},
];
if (!currency) {
return <div>currency not provided</div>;
}
const currencyAndAmount = `${currency}:${amount}`;
const parsedAmount = Amounts.parse(currencyAndAmount);
// const dirty = parsedInitialAmountValue !== amount;
const invalid = !parsedAmount || Amounts.isZero(parsedAmount);
return ( return (
<Container> <Container>
<p>Request {currency} from:</p> <h1>
<Paper style={{ padding: 8 }}>Bank account</Paper> <i18n.Translate>Specify the amount and the origin</i18n.Translate>
<Paper style={{ padding: 8 }}>Another person</Paper> </h1>
<TextField
label="Amount"
type="number"
variant="filled"
error={invalid}
required
startAdornment={
<div style={{ padding: "25px 12px 8px 12px" }}>{currency}</div>
}
value={amount}
onChange={(e) => {
setAmount(e);
}}
/>
<Grid container spacing={1} columns={1}>
{previous2.length > 0 ? (
<Fragment>
<p>Previous origins:</p>
<Grid item xs={1}>
<Paper style={{ padding: 8 }}>
<ContactTable>
{previous2.map((info, i) => (
<tr key={i}>
<td>
<RowExample info={info} disabled={invalid} />
</td>
</tr>
))}
</ContactTable>
</Paper>
</Grid>
</Fragment>
) : undefined}
<Grid item>
<p>Create new origin for the money</p>
</Grid>
<Grid item container columns={3} spacing={1}>
<Grid item xs={1}>
<Paper style={{ padding: 8 }}>
<p>From my bank account</p>
<Button
disabled={invalid}
onClick={async () =>
goToWalletManualWithdraw(currencyAndAmount)
}
>
Withdraw
</Button>
</Paper>
</Grid>
<Grid item xs={1}>
<Paper style={{ padding: 8 }}>
<p>From someone else</p>
<Button disabled>Request</Button>
</Paper>
</Grid>
<Grid item xs={1}>
<Paper style={{ padding: 8 }}>
<p>From a business or charity</p>
<Button disabled>Invoice</Button>
</Paper>
</Grid>
</Grid>
<Grid item columns={1} spacing={1} xs={1}>
<Paper style={{ padding: 8 }}>
<p>From a exchange reserve or purse</p>
<Button disabled>Create</Button>
</Paper>
</Grid>
</Grid>
</Container> </Container>
); );
} }
export function DestinationSelectionSendCash({ currency }: Props): VNode { export function DestinationSelectionSendCash({
amount: initialAmount,
}: Props): VNode {
const parsedInitialAmount = !initialAmount
? undefined
: Amounts.parse(initialAmount);
const parsedInitialAmountValue = !parsedInitialAmount
? ""
: Amounts.stringifyValue(parsedInitialAmount);
const currency = parsedInitialAmount?.currency;
const [amount, setAmount] = useState(parsedInitialAmountValue);
const { i18n } = useTranslationContext();
const previous1: Contact[] = [];
const previous2: Contact[] = [
{
name: "International Bank",
icon: bankIcon,
description: "account ending with 3454",
},
{
name: "Max",
icon: bankIcon,
description: "account ending with 3454",
},
{
name: "Alex",
icon: bankIcon,
description: "account ending with 3454",
},
];
if (!currency) {
return <div>currency not provided</div>;
}
const currencyAndAmount = `${currency}:${amount}`;
const parsedAmount = Amounts.parse(currencyAndAmount);
const invalid = !parsedAmount || Amounts.isZero(parsedAmount);
return ( return (
<Container> <Container>
<p>Sending {currency} to:</p> <h1>
<Paper style={{ padding: 8 }}>Bank account</Paper> <i18n.Translate>Specify the amount and the destination</i18n.Translate>
<Paper style={{ padding: 8 }}>Another person</Paper> </h1>
<TextField
label="Amount"
type="number"
variant="filled"
required
error={invalid}
startAdornment={
<div style={{ padding: "25px 12px 8px 12px" }}>{currency}</div>
}
value={amount}
onChange={(e) => {
setAmount(e);
}}
/>
<Grid container spacing={1} columns={1}>
{previous2.length > 0 ? (
<Fragment>
<p>Previous destinations:</p>
<Grid item xs={1}>
<Paper style={{ padding: 8 }}>
<ContactTable>
{previous2.map((info, i) => (
<tr key={i}>
<td>
<RowExample info={info} disabled={invalid} />
</td>
</tr>
))}
</ContactTable>
</Paper>
</Grid>
</Fragment>
) : undefined}
<Grid item>
<p>Create a destination for the money</p>
</Grid>
<Grid item container columns={3} spacing={1}>
<Grid item xs={1}>
<Paper style={{ padding: 8 }}>
<p>To my bank account</p>
<Button disabled={invalid}>Deposit</Button>
</Paper>
</Grid>
<Grid item xs={1}>
<Paper style={{ padding: 8 }}>
<p>To someone else</p>
<Button disabled>Send</Button>
</Paper>
</Grid>
<Grid item xs={1}>
<Paper style={{ padding: 8 }}>
<p>To a business or charity</p>
<Button disabled>Pay</Button>
</Paper>
</Grid>
</Grid>
<Grid item columns={1} spacing={1} xs={1}>
<Paper style={{ padding: 8 }}>
<p>To an exchange reserve or purse</p>
<Button disabled>Create</Button>
</Paper>
</Grid>
</Grid>
</Container> </Container>
); );
} }

View File

@ -210,7 +210,7 @@ export function HistoryView({
// style={{ marginLeft: 0, marginTop: 8 }} // style={{ marginLeft: 0, marginTop: 8 }}
onClick={() => goToWalletManualWithdraw(selectedCurrency)} onClick={() => goToWalletManualWithdraw(selectedCurrency)}
> >
<i18n.Translate>Get</i18n.Translate> <i18n.Translate>Add</i18n.Translate>
</Button> </Button>
{currencyAmount && Amounts.isNonZero(currencyAmount) && ( {currencyAmount && Amounts.isNonZero(currencyAmount) && (
<Button <Button

View File

@ -33,11 +33,11 @@ import { CreateManualWithdraw } from "./CreateManualWithdraw.js";
import { ReserveCreated } from "./ReserveCreated.js"; import { ReserveCreated } from "./ReserveCreated.js";
interface Props { interface Props {
currency?: string; amount?: string;
onCancel: () => Promise<void>; onCancel: () => Promise<void>;
} }
export function ManualWithdrawPage({ currency, onCancel }: Props): VNode { export function ManualWithdrawPage({ amount, onCancel }: Props): VNode {
const [success, setSuccess] = useState< const [success, setSuccess] = useState<
| { | {
response: AcceptManualWithdrawalResult; response: AcceptManualWithdrawalResult;
@ -117,12 +117,18 @@ export function ManualWithdrawPage({ currency, onCancel }: Props): VNode {
{} as Record<string, string>, {} as Record<string, string>,
); );
const parsedAmount = !amount ? undefined : Amounts.parse(amount);
const currency = parsedAmount?.currency;
const amountValue = !parsedAmount
? undefined
: Amounts.stringifyValue(parsedAmount);
return ( return (
<CreateManualWithdraw <CreateManualWithdraw
error={error} error={error}
exchangeUrlWithCurrency={exchangeList} exchangeUrlWithCurrency={exchangeList}
onCreate={doCreate} onCreate={doCreate}
initialCurrency={currency} initialCurrency={currency}
initialAmount={amountValue}
/> />
); );
} }