From e22bdd52f7dc878738d1b1306a15ae0f573c30a2 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 24 Aug 2021 15:16:11 -0300 Subject: [PATCH] transaction details new ui --- packages/taler-util/src/amounts.ts | 9 +- .../.storybook/preview.js | 2 - .../src/components/styled/index.tsx | 48 ++++++- .../src/popup/ProviderDetailPage.tsx | 4 +- .../src/wallet/ProviderDetailPage.tsx | 4 +- .../src/wallet/Transaction.stories.tsx | 8 +- .../src/wallet/Transaction.tsx | 117 +++++++++++------- 7 files changed, 135 insertions(+), 57 deletions(-) diff --git a/packages/taler-util/src/amounts.ts b/packages/taler-util/src/amounts.ts index e472de503..f0434be0e 100644 --- a/packages/taler-util/src/amounts.ts +++ b/packages/taler-util/src/amounts.ts @@ -402,6 +402,12 @@ export class Amounts { */ static stringify(a: AmountLike): string { a = Amounts.jsonifyAmount(a); + const s = this.stringifyValue(a) + + return `${a.currency}:${s}`; + } + + static stringifyValue(a: AmountJson): string { const av = a.value + Math.floor(a.fraction / amountFractionalBase); const af = a.fraction % amountFractionalBase; let s = av.toString(); @@ -417,7 +423,6 @@ export class Amounts { n = (n * 10) % amountFractionalBase; } } - - return `${a.currency}:${s}`; + return s } } diff --git a/packages/taler-wallet-webextension/.storybook/preview.js b/packages/taler-wallet-webextension/.storybook/preview.js index 920e6b1ca..488663469 100644 --- a/packages/taler-wallet-webextension/.storybook/preview.js +++ b/packages/taler-wallet-webextension/.storybook/preview.js @@ -158,8 +158,6 @@ export const decorators = [ - - } diff --git a/packages/taler-wallet-webextension/src/components/styled/index.tsx b/packages/taler-wallet-webextension/src/components/styled/index.tsx index 66595d84c..8f795ce83 100644 --- a/packages/taler-wallet-webextension/src/components/styled/index.tsx +++ b/packages/taler-wallet-webextension/src/components/styled/index.tsx @@ -85,6 +85,7 @@ export const WalletBox = styled.div<{ noPadding?: boolean }>` flex-direction: row; justify-content: space-between; display: flex; + background-color: #f7f7f7; & button { margin-right: 8px; margin-left: 8px; @@ -199,6 +200,33 @@ export const Button = styled.button` } `; +export const FontIcon = styled.div` + font-family: monospace; + font-size: x-large; + text-align: center; + font-weight: bold; + /* vertical-align: text-top; */ +` +export const ButtonBox = styled(Button)` + padding: .5em; + width: 2em; + height: 2em; + + & > ${FontIcon} { + width: 1em; + height: 1em; + display: inline; + line-height: 0px; + } + background-color: transparent; + + border: 1px solid; + border-radius: 4px; + border-color: black; + color: black; +` + + const ButtonVariant = styled(Button)` color: white; border-radius: 4px; @@ -208,18 +236,35 @@ const ButtonVariant = styled(Button)` export const ButtonPrimary = styled(ButtonVariant)` background-color: rgb(66, 184, 221); ` +export const ButtonBoxPrimary = styled(ButtonBox)` + color: rgb(66, 184, 221); + border-color: rgb(66, 184, 221); +` export const ButtonSuccess = styled(ButtonVariant)` background-color: rgb(28, 184, 65); ` +export const ButtonBoxSuccess = styled(ButtonBox)` + color: rgb(28, 184, 65); + border-color: rgb(28, 184, 65); +` export const ButtonWarning = styled(ButtonVariant)` background-color: rgb(223, 117, 20); ` +export const ButtonBoxWarning = styled(ButtonBox)` + color: rgb(223, 117, 20); + border-color: rgb(223, 117, 20); +` export const ButtonDestructive = styled(ButtonVariant)` background-color: rgb(202, 60, 60); ` +export const ButtonBoxDestructive = styled(ButtonBox)` + color: rgb(202, 60, 60); + border-color: rgb(202, 60, 60); +` + export const BoldLight = styled.div` color: gray; @@ -336,6 +381,7 @@ export const CenteredTextBold = styled(CenteredText)` font-weight: bold; color: ${((props: any): any => String(props.color) as any) as any}; ` + export const Input = styled.div<{ invalid?: boolean }>` & label { display: block; @@ -359,7 +405,7 @@ export const ErrorBox = styled.div` /* margin: 0.5em; */ padding-left: 1em; padding-right: 1em; - width: 100%; + /* width: 100%; */ color: #721c24; background: #f8d7da; diff --git a/packages/taler-wallet-webextension/src/popup/ProviderDetailPage.tsx b/packages/taler-wallet-webextension/src/popup/ProviderDetailPage.tsx index bfc32a8f3..83d94ac0f 100644 --- a/packages/taler-wallet-webextension/src/popup/ProviderDetailPage.tsx +++ b/packages/taler-wallet-webextension/src/popup/ProviderDetailPage.tsx @@ -58,9 +58,7 @@ export function ProviderView({ info, onDelete, onSync, onBack, onExtend }: ViewP const isPaid = info.paymentStatus.type === ProviderPaymentType.Paid || info.paymentStatus.type === ProviderPaymentType.TermsChanged return ( - {info.backupProblem || info.lastError ?
- -
: undefined } +

{info.name} {info.syncProviderBaseUrl}

{isPaid ? 'Paid' : 'Unpaid'} diff --git a/packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx b/packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx index fc361f625..871e30b71 100644 --- a/packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx +++ b/packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx @@ -58,9 +58,7 @@ export function ProviderView({ info, onDelete, onSync, onBack, onExtend }: ViewP const isPaid = info.paymentStatus.type === ProviderPaymentType.Paid || info.paymentStatus.type === ProviderPaymentType.TermsChanged return ( - {info.backupProblem || info.lastError ?
- -
: undefined } +

{info.name} {info.syncProviderBaseUrl}

{isPaid ? 'Paid' : 'Unpaid'} diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx b/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx index 0f7ea457d..535509cef 100644 --- a/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx @@ -40,8 +40,8 @@ export default { }; const commonTransaction = { - amountRaw: 'USD:10', - amountEffective: 'USD:9', + amountRaw: 'KUDOS:11', + amountEffective: 'KUDOS:9.2', pending: false, timestamp: { t_ms: new Date().getTime() @@ -62,7 +62,7 @@ const exampleData = { } as TransactionWithdrawal, payment: { ...commonTransaction, - amountEffective: 'USD:11', + amountEffective: 'KUDOS:11', type: TransactionType.Payment, info: { contractTermsHash: 'ASDZXCASD', @@ -147,7 +147,7 @@ export const PaymentError = createExample(TestedComponent, { export const PaymentWithoutFee = createExample(TestedComponent, { transaction: { ...exampleData.payment, - amountRaw: 'USD:11', + amountRaw: 'KUDOS:11', } }); diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx index d00abc16a..ad00b3d1b 100644 --- a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx @@ -14,7 +14,7 @@ TALER; see the file COPYING. If not, see */ -import { AmountJson, Amounts, i18n, Transaction, TransactionType } from "@gnu-taler/taler-util"; +import { AmountJson, AmountLike, Amounts, i18n, Transaction, TransactionType } from "@gnu-taler/taler-util"; import { format } from "date-fns"; import { Fragment, JSX, VNode, h } from "preact"; import { route } from 'preact-router'; @@ -22,7 +22,7 @@ import { useEffect, useState } from "preact/hooks"; import * as wxApi from "../wxApi"; import { Pages } from "../NavigationBar"; import emptyImg from "../../static/img/empty.png" -import { Button, ButtonDestructive, ButtonPrimary, ListOfProducts, PopupBox, Row, RowBorderGray, SmallTextLight, WalletBox } from "../components/styled"; +import { Button, ButtonBox, ButtonBoxDestructive, ButtonDestructive, ButtonPrimary, ExtraLargeText, FontIcon, LargeText, ListOfProducts, PopupBox, Row, RowBorderGray, SmallTextLight, WalletBox } from "../components/styled"; import { ErrorMessage } from "../components/ErrorMessage"; export function TransactionPage({ tid }: { tid: string; }): JSX.Element { @@ -73,43 +73,54 @@ export function TransactionView({ transaction, onDelete, onRetry, onBack }: Wall return null } - function Fee({ value }: { value: AmountJson }) { - if (Amounts.isZero(value)) return null - return (fee {Amounts.stringify(value)}) - } - - function TransactionTemplate({ upperRight, children }: { upperRight: VNode, children: VNode[] }) { + function TransactionTemplate({ children }: { children: VNode[] }) { return -
- - {transaction.timestamp.t_ms === "never" ? "never" : format(transaction.timestamp.t_ms, 'dd/MM/yyyy HH:mm:ss')} - - - {upperRight} - -
- {children} +
+ {children} +
- +
{transaction?.error ? retry : null} - delete + 🗑
} + type Kind = 'positive' | 'negative' | 'neutral'; + function Part({ text, title, kind, big }: { title: string, text: AmountLike, kind: Kind, big?: boolean }) { + const Text = big ? ExtraLargeText : LargeText; + return
+ {title} + + {text} + +
+ } + + function amountToString(text: AmountLike) { + const aj = Amounts.jsonifyAmount(text) + const amount = Amounts.stringifyValue(aj) + return `${amount} ${aj.currency}` + } + if (transaction.type === TransactionType.Withdrawal) { const fee = Amounts.sub( Amounts.parseOrThrow(transaction.amountRaw), Amounts.parseOrThrow(transaction.amountEffective), ).amount - return From {transaction.exchangeBaseUrl}}> -

Withdraw

-

{transaction.amountEffective}

+ return +

Withdrawal

+
{transaction.timestamp.t_ms === 'never' ? 'never': format(transaction.timestamp.t_ms, 'dd MMMM yyyy, HH:mm')}
+
+ + + +
} @@ -123,13 +134,17 @@ export function TransactionView({ transaction, onDelete, onRetry, onBack }: Wall Amounts.parseOrThrow(transaction.amountRaw), ).amount - return To {transaction.info.merchant.name}}> -

Payment

-

{transaction.amountEffective}

- #{transaction.info.orderId} -

- {transaction.info.summary} -

+ return +

Payment

+
{transaction.timestamp.t_ms === 'never' ? 'never': format(transaction.timestamp.t_ms, 'dd MMMM yyyy, HH:mm')}
+
+ + + + + + +
{transaction.info.products && transaction.info.products.length > 0 && @@ -153,9 +168,13 @@ export function TransactionView({ transaction, onDelete, onRetry, onBack }: Wall Amounts.parseOrThrow(transaction.amountRaw), Amounts.parseOrThrow(transaction.amountEffective), ).amount - return To {transaction.targetPaytoUri}}> -

Deposit

-

{transaction.amountEffective}

+ return +

Deposit

+
{transaction.timestamp.t_ms === 'never' ? 'never': format(transaction.timestamp.t_ms, 'dd MMMM yyyy, HH:mm')}
+
+ + +
} @@ -164,9 +183,13 @@ export function TransactionView({ transaction, onDelete, onRetry, onBack }: Wall Amounts.parseOrThrow(transaction.amountRaw), Amounts.parseOrThrow(transaction.amountEffective), ).amount - return From {transaction.exchangeBaseUrl}}> -

Refresh

-

{transaction.amountEffective}

+ return +

Refresh

+
{transaction.timestamp.t_ms === 'never' ? 'never': format(transaction.timestamp.t_ms, 'dd MMMM yyyy, HH:mm')}
+
+ + +
} @@ -175,9 +198,13 @@ export function TransactionView({ transaction, onDelete, onRetry, onBack }: Wall Amounts.parseOrThrow(transaction.amountRaw), Amounts.parseOrThrow(transaction.amountEffective), ).amount - return From {transaction.merchantBaseUrl}}> -

Tip

-

{transaction.amountEffective}

+ return +

Tip

+
{transaction.timestamp.t_ms === 'never' ? 'never': format(transaction.timestamp.t_ms, 'dd MMMM yyyy, HH:mm')}
+
+ + +
} @@ -186,11 +213,17 @@ export function TransactionView({ transaction, onDelete, onRetry, onBack }: Wall Amounts.parseOrThrow(transaction.amountRaw), Amounts.parseOrThrow(transaction.amountEffective), ).amount - return From {transaction.info.merchant.name}}> -

Refund

-

{transaction.amountEffective}

+ return +

Refund

+
{transaction.timestamp.t_ms === 'never' ? 'never': format(transaction.timestamp.t_ms, 'dd MMMM yyyy, HH:mm')}
+
+ + + + + + - #{transaction.info.orderId}

{transaction.info.summary}