diff options
author | Sebastian <sebasjm@gmail.com> | 2021-08-19 00:34:47 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2021-08-19 00:35:21 -0300 |
commit | 97a05ff659af274dcfcd9c76bf19100bbd51ce0e (patch) | |
tree | 9cce837ec9a5ec06279dc48eac75e1993ede983f /packages/taler-wallet-webextension | |
parent | b015f76e7268cb5caff14a0ed88cb5e8fa53dc2e (diff) |
new wallet history and view refactoring
Diffstat (limited to 'packages/taler-wallet-webextension')
30 files changed, 867 insertions, 158 deletions
diff --git a/packages/taler-wallet-webextension/.storybook/preview.js b/packages/taler-wallet-webextension/.storybook/preview.js index 02a4e43d4..1b6f62400 100644 --- a/packages/taler-wallet-webextension/.storybook/preview.js +++ b/packages/taler-wallet-webextension/.storybook/preview.js @@ -15,7 +15,8 @@ */ import { Fragment } from "preact" -import { NavBar } from '../src/popup/popup' +import { NavBar } from '../src/NavigationBar' +import { LogoHeader } from '../src/components/LogoHeader' import { TranslationProvider } from '../src/context/translation' export const parameters = { @@ -43,7 +44,7 @@ export const globalTypes = { export const decorators = [ (Story, { kind }) => { if (kind.startsWith('popup')) { - + function Body() { const isTestingHeader = (/.*\/header\/?.*/.test(kind)); if (isTestingHeader) { @@ -51,16 +52,16 @@ export const decorators = [ return <div style={{ width: 400, height: 320 }}> <Story /> </div> - } else { - const path = !isTestingHeader ? /popup(\/.*).*/.exec(kind)[1] : '' - // add a fake header so it looks similar - return <Fragment> - <NavBar path={path} devMode={path === '/dev'} /> - <div style={{ width: 400, height: 290 }}> - <Story /> - </div> - </Fragment> } + + const path = /popup(\/.*).*/.exec(kind)[1]; + // add a fake header so it looks similar + return <Fragment> + <NavBar path={path} devMode={path === '/dev'} /> + <div style={{ width: 400, height: 290 }}> + <Story /> + </div> + </Fragment> } return <div class="popup-container"> @@ -95,11 +96,71 @@ export const decorators = [ </div> </div> } - if (kind.startsWith('wallet')) { - return <div class="wallet-container"> + if (kind.startsWith('cta')) { + return <div> + <style>{` + html { + font-family: sans-serif; /* 1 */ + } + body { + margin: 0; + }`} + </style> + <style>{` + html { + } + h1 { + font-size: 2em; + } + input { + font: inherit; + } + body { + margin: 0; + font-size: 100%; + padding: 0; + background-color: #f8faf7; + font-family: Arial, Helvetica, sans-serif; + }`} + </style> <link key="1" rel="stylesheet" type="text/css" href="/style/pure.css" /> <link key="2" rel="stylesheet" type="text/css" href="/style/wallet.css" /> <Story /> + </div> + } + if (kind.startsWith('wallet')) { + const path = /wallet(\/.*).*/.exec(kind)[1]; + return <div class="wallet-container"> + <style>{` + html { + font-family: sans-serif; /* 1 */ + } + body { + margin: 0; + }`} + </style> + <style>{` + html { + } + h1 { + font-size: 2em; + } + input { + font: inherit; + } + body { + margin: 0; + font-size: 100%; + padding: 0; + background-color: #f8faf7; + font-family: Arial, Helvetica, sans-serif; + }`} + </style> + <LogoHeader /> + <NavBar path={path} devMode={path === '/dev'} /> + {/* <link key="1" rel="stylesheet" type="text/css" href="/style/pure.css" /> + <link key="2" rel="stylesheet" type="text/css" href="/style/wallet.css" /> */} + <Story /> </div> } return <div> diff --git a/packages/taler-wallet-webextension/package.json b/packages/taler-wallet-webextension/package.json index a5908af25..e41c6cb86 100644 --- a/packages/taler-wallet-webextension/package.json +++ b/packages/taler-wallet-webextension/package.json @@ -12,7 +12,7 @@ "test": "jest ./tests", "compile": "tsc && rollup -c", "build-storybook": "build-storybook", - "storybook": "start-storybook -s static -p 6006", + "storybook": "start-storybook -s . -p 6006", "watch": "tsc --watch & rollup -w -c" }, "dependencies": { diff --git a/packages/taler-wallet-webextension/rollup.config.js b/packages/taler-wallet-webextension/rollup.config.js index 7e7ec0032..5a3f0db5f 100644 --- a/packages/taler-wallet-webextension/rollup.config.js +++ b/packages/taler-wallet-webextension/rollup.config.js @@ -1,14 +1,13 @@ // rollup.config.js +import linaria from '@linaria/rollup'; +import alias from '@rollup/plugin-alias'; import commonjs from "@rollup/plugin-commonjs"; -import nodeResolve from "@rollup/plugin-node-resolve"; +import image from '@rollup/plugin-image'; import json from "@rollup/plugin-json"; -import builtins from "builtin-modules"; +import nodeResolve from "@rollup/plugin-node-resolve"; import replace from "@rollup/plugin-replace"; -import ignore from "rollup-plugin-ignore" -import image from '@rollup/plugin-image'; -import linaria from '@linaria/rollup'; import css from 'rollup-plugin-css-only'; -import alias from '@rollup/plugin-alias'; +import ignore from "rollup-plugin-ignore"; const makePlugins = () => [ alias({ diff --git a/packages/taler-wallet-webextension/src/popup/popup.tsx b/packages/taler-wallet-webextension/src/NavigationBar.tsx index 4aee48fb7..e07032d0a 100644 --- a/packages/taler-wallet-webextension/src/popup/popup.tsx +++ b/packages/taler-wallet-webextension/src/NavigationBar.tsx @@ -27,10 +27,11 @@ import { i18n } from "@gnu-taler/taler-util"; import { ComponentChildren, JSX } from "preact"; import Match from "preact-router/match"; -import { useDevContext } from "../context/devContext"; -import { PopupNavigation } from '../components/styled' +import { useDevContext } from "./context/devContext"; +import { PopupNavigation } from './components/styled' export enum Pages { + welcome = '/welcome', balance = '/balance', settings = '/settings', dev = '/dev', @@ -39,6 +40,15 @@ export enum Pages { transaction = '/transaction/:tid', provider_detail = '/provider/:pid', provider_add = '/provider/add', + + reset_required = '/reset-required', + payback = '/payback', + return_coins = '/return-coins', + + pay = '/pay', + refund = '/refund', + tips = '/tips', + withdraw = '/withdraw', } interface TabProps { @@ -59,18 +69,23 @@ function Tab(props: TabProps): JSX.Element { ); } -export function NavBar({devMode, path}:{path:string, devMode:boolean}) { +export function NavBar({ devMode, path }: { path: string, devMode: boolean }) { return <PopupNavigation devMode={devMode}> - <Tab target="/balance" current={path}>{i18n.str`Balance`}</Tab> - <Tab target="/history" current={path}>{i18n.str`History`}</Tab> - <Tab target="/backup" current={path}>{i18n.str`Backup`}</Tab> - <Tab target="/settings" current={path}>{i18n.str`Settings`}</Tab> - {devMode && <Tab target="/dev" current={path}>{i18n.str`Dev`}</Tab>} + <div> + <Tab target="/balance" current={path}>{i18n.str`Balance`}</Tab> + <Tab target="/history" current={path}>{i18n.str`History`}</Tab> + <Tab target="/backup" current={path}>{i18n.str`Backup`}</Tab> + <Tab target="/settings" current={path}>{i18n.str`Settings`}</Tab> + {devMode && <Tab target="/dev" current={path}>{i18n.str`Dev`}</Tab>} + </div> </PopupNavigation> } export function WalletNavBar() { const { devMode } = useDevContext() - return <Match>{({ path }: any) => <NavBar devMode={devMode} path={path} />}</Match> + return <Match>{({ path }: any) => { + console.log("path", path) + return <NavBar devMode={devMode} path={path} /> + }}</Match> } diff --git a/packages/taler-wallet-webextension/src/components/LogoHeader.tsx b/packages/taler-wallet-webextension/src/components/LogoHeader.tsx new file mode 100644 index 000000000..0217289eb --- /dev/null +++ b/packages/taler-wallet-webextension/src/components/LogoHeader.tsx @@ -0,0 +1,13 @@ +export function LogoHeader() { + return <div style={{ + display: 'flex', + justifyContent: 'space-around', + margin: '2em', + }}> + <img style={{ + width: 150, + height: 70, + }} src="/static/img/logo-2021.svg" width="150" /> + </div> + +}
\ No newline at end of file diff --git a/packages/taler-wallet-webextension/src/components/styled/index.tsx b/packages/taler-wallet-webextension/src/components/styled/index.tsx index 7f709db46..6067fa446 100644 --- a/packages/taler-wallet-webextension/src/components/styled/index.tsx +++ b/packages/taler-wallet-webextension/src/components/styled/index.tsx @@ -11,7 +11,7 @@ export const PaymentStatus = styled.div<{ color: string }>` background-color: ${p => p.color}; ` -export const WalletPage = styled.section` +export const WalletAction = styled.section` border: solid 5px black; border-radius: 10px; margin-left: auto; @@ -28,8 +28,73 @@ export const WalletPage = styled.section` } ` +export const DateSeparator = styled.div` + color: gray; + margin: .2em; + margin-top: 1em; +` +export const WalletBox = styled.div<{ noPadding?: boolean }>` + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + & > * { + width: 400px; + } + & > section { + padding-left: ${({ noPadding }) => noPadding ? '0px' : '8px'}; + padding-right: ${({ noPadding }) => noPadding ? '0px' : '8px'}; + // this margin will send the section up when used with a header + margin-bottom: auto; + overflow: auto; + + table td { + padding: 5px 10px; + } + table tr { + border-bottom: 1px solid black; + border-top: 1px solid black; + } + } + + & > header { + flex-direction: row; + justify-content: space-between; + display: flex; + padding: 8px; + margin-bottom: 5px; + + & > div { + align-self: center; + } + + & > h3 { + margin: 0px; + } + + & > .title { + /* margin: 1em; */ + font-size: large; + color: #3c4e92; + } + } + + & > footer { + padding-top: 8px; + padding-bottom: 8px; + flex-direction: row; + justify-content: space-between; + display: flex; + & button { + margin-right: 8px; + margin-left: 8px; + } + } +` + export const PopupBox = styled.div<{ noPadding?: boolean }>` height: 290px; + width: 400px; display: flex; flex-direction: column; justify-content: space-between; @@ -194,10 +259,32 @@ export const RowBorderGray = styled(Row)` export const RowLightBorderGray = styled(Row2)` border: 1px solid lightgray; - /* border-radius: 0.5em; */ + border-top: 0px; + + ${DateSeparator} + & { + border: 1px solid lightgray; + background-color: red; + } ` -export const HistoryRow = styled(RowLightBorderGray)` +export const HistoryRow = styled.a` + text-decoration: none; + + display: flex; + justify-content: space-between; + padding: 0.5em; + + border: 1px solid lightgray; + border-top: 0px; + + ${DateSeparator} + & { + border: 1px solid lightgray; + } + + :hover { + background-color: lightgray; + } + & > ${Column}:last-of-type { margin-left: auto; align-self: center; @@ -284,11 +371,17 @@ export const ErrorBox = styled.div` } } ` -export const PopupNavigation = styled.div<{devMode?:boolean}>` +export const PopupNavigation = styled.div<{ devMode?: boolean }>` background-color:#0042b2; height: 35px; - - & > a { + justify-content: space-around; + display: flex; + + & > div { + width: 400px; + } + + & > div > a { color: #f8faf7; display: inline-block; width: calc(400px / ${({ devMode }) => !devMode ? 4 : 5}); @@ -298,7 +391,7 @@ export const PopupNavigation = styled.div<{devMode?:boolean}>` line-height: 35px; } - & > a.active { + & > div > a.active { background-color: #f8faf7; color: #0042b2; font-weight: bold; diff --git a/packages/taler-wallet-webextension/src/wallet/Pay.stories.tsx b/packages/taler-wallet-webextension/src/cta/Pay.stories.tsx index 0297d6264..38e3d0f35 100644 --- a/packages/taler-wallet-webextension/src/wallet/Pay.stories.tsx +++ b/packages/taler-wallet-webextension/src/cta/Pay.stories.tsx @@ -20,23 +20,16 @@ */ import { ContractTerms, PreparePayResultType } from '@gnu-taler/taler-util'; -import { FunctionalComponent, h } from 'preact'; +import { createExample } from '../test-utils'; import { PaymentRequestView as TestedComponent } from './Pay'; - export default { - title: 'wallet/pay', + title: 'cta/pay', component: TestedComponent, argTypes: { }, }; -function createExample<Props>(Component: FunctionalComponent<Props>, props: Partial<Props>) { - const r = (args: any) => <Component {...args} /> - r.args = props - return r -} - export const InsufficientBalance = createExample(TestedComponent, { payStatus: { status: PreparePayResultType.InsufficientBalance, diff --git a/packages/taler-wallet-webextension/src/wallet/Pay.tsx b/packages/taler-wallet-webextension/src/cta/Pay.tsx index a5849bb28..a5849bb28 100644 --- a/packages/taler-wallet-webextension/src/wallet/Pay.tsx +++ b/packages/taler-wallet-webextension/src/cta/Pay.tsx diff --git a/packages/taler-wallet-webextension/src/wallet/Refund.stories.tsx b/packages/taler-wallet-webextension/src/cta/Refund.stories.tsx index 044141f0c..88e714cb7 100644 --- a/packages/taler-wallet-webextension/src/wallet/Refund.stories.tsx +++ b/packages/taler-wallet-webextension/src/cta/Refund.stories.tsx @@ -19,24 +19,18 @@ * @author Sebastian Javier Marchano (sebasjm) */ -import { ContractTerms, OrderShortInfo, PreparePayResultType } from '@gnu-taler/taler-util'; -import { FunctionalComponent, h } from 'preact'; +import { OrderShortInfo } from '@gnu-taler/taler-util'; +import { createExample } from '../test-utils'; import { View as TestedComponent } from './Refund'; export default { - title: 'wallet/refund', + title: 'cta/refund', component: TestedComponent, argTypes: { }, }; -function createExample<Props>(Component: FunctionalComponent<Props>, props: Partial<Props>) { - const r = (args: any) => <Component {...args} /> - r.args = props - return r -} - export const Complete = createExample(TestedComponent, { applyResult: { amountEffectivePaid: 'USD:10', diff --git a/packages/taler-wallet-webextension/src/wallet/Refund.tsx b/packages/taler-wallet-webextension/src/cta/Refund.tsx index bb26d933b..bb26d933b 100644 --- a/packages/taler-wallet-webextension/src/wallet/Refund.tsx +++ b/packages/taler-wallet-webextension/src/cta/Refund.tsx diff --git a/packages/taler-wallet-webextension/src/wallet/Tip.stories.tsx b/packages/taler-wallet-webextension/src/cta/Tip.stories.tsx index ffd976144..389b183f0 100644 --- a/packages/taler-wallet-webextension/src/wallet/Tip.stories.tsx +++ b/packages/taler-wallet-webextension/src/cta/Tip.stories.tsx @@ -19,24 +19,17 @@ * @author Sebastian Javier Marchano (sebasjm) */ -import { ContractTerms, PreparePayResultType } from '@gnu-taler/taler-util'; -import { FunctionalComponent, h } from 'preact'; +import { createExample } from '../test-utils'; import { View as TestedComponent } from './Tip'; export default { - title: 'wallet/tip', + title: 'cta/tip', component: TestedComponent, argTypes: { }, }; -function createExample<Props>(Component: FunctionalComponent<Props>, props: Partial<Props>) { - const r = (args: any) => <Component {...args} /> - r.args = props - return r -} - export const Accepted = createExample(TestedComponent, { prepareTipResult: { accepted: true, diff --git a/packages/taler-wallet-webextension/src/wallet/Tip.tsx b/packages/taler-wallet-webextension/src/cta/Tip.tsx index 69886668b..69886668b 100644 --- a/packages/taler-wallet-webextension/src/wallet/Tip.tsx +++ b/packages/taler-wallet-webextension/src/cta/Tip.tsx diff --git a/packages/taler-wallet-webextension/src/wallet/Withdraw.stories.tsx b/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx index fef36b820..747f855fa 100644 --- a/packages/taler-wallet-webextension/src/wallet/Withdraw.stories.tsx +++ b/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx @@ -19,32 +19,27 @@ * @author Sebastian Javier Marchano (sebasjm) */ -import { h } from 'preact'; -import { View, ViewProps } from './Withdraw'; +import { createExample } from '../test-utils'; +import { View as TestedComponent } from './Withdraw'; export default { - title: 'wallet/withdraw', - component: View, + title: 'cta/withdraw', + component: TestedComponent, argTypes: { }, }; -export const WithoutDetails = (a: any) => <View {...a} />; -WithoutDetails.args = { -} as ViewProps - -export const CompleteWithExchange = (a: any) => <View {...a} />; -CompleteWithExchange.args = { +export const CompleteWithExchange = createExample(TestedComponent, { details: { amount: 'USD:2', + possibleExchanges: [], }, selectedExchange: 'Some exchange' -} as ViewProps - -export const CompleteWithoutExchange = (a: any) => <View {...a} />; -CompleteWithoutExchange.args = { +}) +export const CompleteWithoutExchange = createExample(TestedComponent, { details: { amount: 'USD:2', + possibleExchanges: [], }, -} as ViewProps +}) diff --git a/packages/taler-wallet-webextension/src/wallet/Withdraw.tsx b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx index 442ee7dae..b5182b070 100644 --- a/packages/taler-wallet-webextension/src/wallet/Withdraw.tsx +++ b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx @@ -32,14 +32,13 @@ import { } from "../wxApi"; import { WithdrawUriInfoResponse } from "@gnu-taler/taler-util"; import { JSX } from "preact/jsx-runtime"; -import { WalletPage } from '../components/styled'; +import { WalletAction } from '../components/styled'; interface Props { talerWithdrawUri?: string; } export interface ViewProps { - talerWithdrawUri?: string; details: WithdrawUriInfoResponse; selectedExchange?: string; accept: () => Promise<void>; @@ -50,7 +49,7 @@ export interface ViewProps { export function View({ details, selectedExchange, accept, setCancelled, setSelecting }: ViewProps) { return ( - <WalletPage> + <WalletAction> <div style="border-bottom: 3px dashed #aa3939; margin-bottom: 2em;"> <h1 style="font-family: monospace; font-size: 250%;"> <span style="color: #aa3939;">❰</span>Taler Wallet<span style="color: #aa3939;">❱</span> @@ -101,26 +100,19 @@ export function View({ details, selectedExchange, accept, setCancelled, setSelec </div> </div> </div> - </WalletPage> + </WalletAction> ) } export function WithdrawPage({ talerWithdrawUri, ...rest }: Props): JSX.Element { const [details, setDetails] = useState<WithdrawUriInfoResponse | undefined>(undefined); - const [selectedExchange, setSelectedExchange] = useState< - string | undefined - >(undefined); + const [selectedExchange, setSelectedExchange] = useState<string | undefined>(undefined); const [cancelled, setCancelled] = useState(false); const [selecting, setSelecting] = useState(false); - const [errMsg, setErrMsg] = useState<string | undefined>(""); + const [error, setError] = useState<boolean>(false); const [updateCounter, setUpdateCounter] = useState(1); const [state, setState] = useState(1) - // setTimeout(() => { - // console.log('tick...') - // setState(s => s + 1) - // }, 1000); - useEffect(() => { return onUpdateNotification(() => { console.log('updating...') @@ -132,20 +124,19 @@ export function WithdrawPage({ talerWithdrawUri, ...rest }: Props): JSX.Element console.log('on effect yes', talerWithdrawUri) if (!talerWithdrawUri) return const fetchData = async (): Promise<void> => { - console.log('que pasa') try { const res = await getWithdrawalDetailsForUri({ talerWithdrawUri }); - console.log('res', res) setDetails(res); if (res.defaultExchangeBaseUrl) { setSelectedExchange(res.defaultExchangeBaseUrl); } } catch (e) { - console.error(e) + console.error('error',JSON.stringify(e,undefined,2)) + setError(true) } }; fetchData(); - }, [selectedExchange, errMsg, selecting, talerWithdrawUri, updateCounter, state]); + }, [selectedExchange, selecting, talerWithdrawUri, updateCounter, state]); if (!talerWithdrawUri) { return <span><i18n.Translate>missing withdraw uri</i18n.Translate></span>; @@ -169,6 +160,9 @@ export function WithdrawPage({ talerWithdrawUri, ...rest }: Props): JSX.Element if (cancelled) { return <span><i18n.Translate>Withdraw operation has been cancelled.</i18n.Translate></span>; } + if (error) { + return <span><i18n.Translate>This URI is not valid anymore.</i18n.Translate></span>; + } return <View accept={accept} setCancelled={setCancelled} setSelecting={setSelecting} diff --git a/packages/taler-wallet-webextension/src/wallet/payback.tsx b/packages/taler-wallet-webextension/src/cta/payback.tsx index 4233b1f96..4233b1f96 100644 --- a/packages/taler-wallet-webextension/src/wallet/payback.tsx +++ b/packages/taler-wallet-webextension/src/cta/payback.tsx diff --git a/packages/taler-wallet-webextension/src/wallet/reset-required.tsx b/packages/taler-wallet-webextension/src/cta/reset-required.tsx index 87751561c..87751561c 100644 --- a/packages/taler-wallet-webextension/src/wallet/reset-required.tsx +++ b/packages/taler-wallet-webextension/src/cta/reset-required.tsx diff --git a/packages/taler-wallet-webextension/src/wallet/return-coins.tsx b/packages/taler-wallet-webextension/src/cta/return-coins.tsx index 2273d1454..2273d1454 100644 --- a/packages/taler-wallet-webextension/src/wallet/return-coins.tsx +++ b/packages/taler-wallet-webextension/src/cta/return-coins.tsx diff --git a/packages/taler-wallet-webextension/src/popup/BackupPage.tsx b/packages/taler-wallet-webextension/src/popup/BackupPage.tsx index 940d1f2a4..72139e1f8 100644 --- a/packages/taler-wallet-webextension/src/popup/BackupPage.tsx +++ b/packages/taler-wallet-webextension/src/popup/BackupPage.tsx @@ -25,7 +25,7 @@ import { SmallText, SmallTextLight } from "../components/styled"; import { useBackupStatus } from "../hooks/useBackupStatus"; -import { Pages } from "./popup"; +import { Pages } from "../NavigationBar"; interface Props { onAddProvider: () => void; diff --git a/packages/taler-wallet-webextension/src/popup/History.tsx b/packages/taler-wallet-webextension/src/popup/History.tsx index b6b65314e..7c9eae54b 100644 --- a/packages/taler-wallet-webextension/src/popup/History.tsx +++ b/packages/taler-wallet-webextension/src/popup/History.tsx @@ -14,11 +14,19 @@ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -import { AmountJson, Amounts, AmountString, Balance, Timestamp, Transaction, TransactionsResponse, TransactionType } from "@gnu-taler/taler-util"; +import { AmountString, Balance, Timestamp, Transaction, TransactionsResponse, TransactionType } from "@gnu-taler/taler-util"; +import { formatDistance } from "date-fns"; import { JSX } from "preact"; import { useEffect, useState } from "preact/hooks"; +import imageBank from '../../static/img/ri-bank-line.svg'; +import imageHandHeart from '../../static/img/ri-hand-heart-line.svg'; +import imageRefresh from '../../static/img/ri-refresh-line.svg'; +import imageRefund from '../../static/img/ri-refund-2-line.svg'; +import imageShoppingCart from '../../static/img/ri-shopping-cart-line.svg'; +import { Column, ExtraLargeText, HistoryRow, PopupBox, SmallTextLight } from "../components/styled"; +import { useBalances } from "../hooks/useBalances"; import * as wxApi from "../wxApi"; -import { Pages } from "./popup"; +import { Pages } from "../NavigationBar"; export function HistoryPage(props: any): JSX.Element { @@ -45,7 +53,7 @@ export function HistoryPage(props: any): JSX.Element { function amountToString(c: AmountString) { const idx = c.indexOf(':') - return `${c.substring(idx+1)} ${c.substring(0,idx)}` + return `${c.substring(idx + 1)} ${c.substring(0, idx)}` } @@ -68,20 +76,14 @@ export function HistoryView({ list, balances }: { list: Transaction[], balances: ))} </section> <footer style={{ justifyContent: 'space-around' }}> - <a style={{ color: 'darkgreen', textDecoration:'none' }} href={Pages.transaction.replace(':tid', 'asd')}>VIEW MORE TRANSACTIONS</a> + <a target="_blank" + rel="noopener noreferrer" + style={{ color: 'darkgreen', textDecoration: 'none' }} + href={chrome.extension ? chrome.extension.getURL(`/static/wallet.html#/history`) : '#'}>VIEW MORE TRANSACTIONS</a> </footer> </PopupBox> } -import imageBank from '../../static/img/ri-bank-line.svg'; -import imageShoppingCart from '../../static/img/ri-shopping-cart-line.svg'; -import imageRefund from '../../static/img/ri-refund-2-line.svg'; -import imageHandHeart from '../../static/img/ri-hand-heart-line.svg'; -import imageRefresh from '../../static/img/ri-refresh-line.svg'; -import { Column, ExtraLargeText, HistoryRow, PopupBox, Row, RowBorderGray, SmallTextLight } from "../components/styled"; -import { useBalances } from "../hooks/useBalances"; -import { formatDistance } from "date-fns"; - function TransactionItem(props: { tx: Transaction }): JSX.Element { const tx = props.tx; switch (tx.type) { @@ -171,18 +173,16 @@ function TransactionLayout(props: TransactionLayoutProps): JSX.Element { const now = new Date(); const dateStr = formatDistance(date, now, { addSuffix: true }) return ( - <HistoryRow> + <HistoryRow href={Pages.transaction.replace(':tid', props.id)}> <img src={props.iconPath} /> <Column> <ExtraLargeText> - <a href={Pages.transaction.replace(':tid', props.id)}><span>{props.title}</span></a> + <span>{props.title}</span> {props.pending ? ( <span style={{ color: "darkblue" }}> (Pending)</span> ) : null} </ExtraLargeText> <SmallTextLight>{dateStr}</SmallTextLight> - - {/* <div>{props.subtitle}</div> */} </Column> <TransactionAmount pending={props.pending} diff --git a/packages/taler-wallet-webextension/src/popup/Popup.stories.tsx b/packages/taler-wallet-webextension/src/popup/Popup.stories.tsx index ec3634d9b..ce5b11c32 100644 --- a/packages/taler-wallet-webextension/src/popup/Popup.stories.tsx +++ b/packages/taler-wallet-webextension/src/popup/Popup.stories.tsx @@ -20,7 +20,7 @@ */ import { Fragment, FunctionalComponent } from 'preact'; -import { NavBar as TestedComponent } from './popup'; +import { NavBar as TestedComponent } from '../NavigationBar'; export default { title: 'popup/header', diff --git a/packages/taler-wallet-webextension/src/popup/Transaction.tsx b/packages/taler-wallet-webextension/src/popup/Transaction.tsx index fd7389c04..8177b74ad 100644 --- a/packages/taler-wallet-webextension/src/popup/Transaction.tsx +++ b/packages/taler-wallet-webextension/src/popup/Transaction.tsx @@ -20,7 +20,7 @@ import { Fragment, JSX, VNode } from "preact"; import { route } from 'preact-router'; import { useEffect, useState } from "preact/hooks"; import * as wxApi from "../wxApi"; -import { Pages } from "./popup"; +import { Pages } from "../NavigationBar"; import emptyImg from "../../static/img/empty.png" import { Button, ButtonDestructive, ButtonPrimary, ListOfProducts, PopupBox, Row, RowBorderGray, SmallTextLight } from "../components/styled"; import { ErrorMessage } from "../components/ErrorMessage"; diff --git a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx index faa5149ac..4a9fe9abc 100644 --- a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx +++ b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx @@ -34,7 +34,7 @@ import { DeveloperPage as DeveloperPage } from "./popup/Debug"; import { HistoryPage } from "./popup/History"; import { Pages, WalletNavBar -} from "./popup/popup"; +} from "./NavigationBar"; import { ProviderAddPage } from "./popup/ProviderAddPage"; import { ProviderDetailPage } from "./popup/ProviderDetailPage"; import { SettingsPage } from "./popup/Settings"; @@ -129,4 +129,4 @@ function Redirect({ to }: { to: string }): null { route(to, true) }) return null -}
\ No newline at end of file +} diff --git a/packages/taler-wallet-webextension/src/test-utils.ts b/packages/taler-wallet-webextension/src/test-utils.ts new file mode 100644 index 000000000..16262b3c2 --- /dev/null +++ b/packages/taler-wallet-webextension/src/test-utils.ts @@ -0,0 +1,8 @@ +import { FunctionalComponent, h as render } from 'preact'; + +export function createExample<Props>(Component: FunctionalComponent<Props>, props: Partial<Props>) { + const r = (args: any) => render(Component, args) + r.args = props + return r +} + diff --git a/packages/taler-wallet-webextension/src/wallet/History.stories.tsx b/packages/taler-wallet-webextension/src/wallet/History.stories.tsx new file mode 100644 index 000000000..f50fd3b68 --- /dev/null +++ b/packages/taler-wallet-webextension/src/wallet/History.stories.tsx @@ -0,0 +1,294 @@ +/* + This file is part of GNU Taler + (C) 2021 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { + PaymentStatus, + TransactionCommon, TransactionDeposit, TransactionPayment, + TransactionRefresh, TransactionRefund, TransactionTip, TransactionType, + TransactionWithdrawal, + WithdrawalType +} from '@gnu-taler/taler-util'; +import { FunctionalComponent } from 'preact'; +import { HistoryView as TestedComponent } from './History'; + +export default { + title: 'wallet/history/list', + component: TestedComponent, +}; + +let count = 0 +const commonTransaction = () => ({ + amountRaw: 'USD:10', + amountEffective: 'USD:9', + pending: false, + timestamp: { + t_ms: new Date().getTime() - (count++ * 1000*60*60*7) + }, + transactionId: '12', +} as TransactionCommon) + +const exampleData = { + withdraw: { + ...commonTransaction(), + type: TransactionType.Withdrawal, + exchangeBaseUrl: 'http://exchange.taler', + withdrawalDetails: { + confirmed: false, + exchangePaytoUris: ['payto://x-taler-bank/bank/account'], + type: WithdrawalType.ManualTransfer, + } + } as TransactionWithdrawal, + payment: { + ...commonTransaction(), + amountEffective: 'USD:11', + type: TransactionType.Payment, + info: { + contractTermsHash: 'ASDZXCASD', + merchant: { + name: 'the merchant', + }, + orderId: '2021.167-03NPY6MCYMVGT', + products: [], + summary: 'the summary', + fulfillmentMessage: '', + }, + proposalId: '1EMJJH8EP1NX3XF7733NCYS2DBEJW4Q2KA5KEB37MCQJQ8Q5HMC0', + status: PaymentStatus.Accepted, + } as TransactionPayment, + deposit: { + ...commonTransaction(), + type: TransactionType.Deposit, + depositGroupId: '#groupId', + targetPaytoUri: 'payto://x-taler-bank/bank/account', + } as TransactionDeposit, + refresh: { + ...commonTransaction(), + type: TransactionType.Refresh, + exchangeBaseUrl: 'http://exchange.taler', + } as TransactionRefresh, + tip: { + ...commonTransaction(), + type: TransactionType.Tip, + merchantBaseUrl: 'http://merchant.taler', + } as TransactionTip, + refund: { + ...commonTransaction(), + type: TransactionType.Refund, + refundedTransactionId: 'payment:1EMJJH8EP1NX3XF7733NCYS2DBEJW4Q2KA5KEB37MCQJQ8Q5HMC0', + info: { + contractTermsHash: 'ASDZXCASD', + merchant: { + name: 'the merchant', + }, + orderId: '2021.167-03NPY6MCYMVGT', + products: [], + summary: 'the summary', + fulfillmentMessage: '', + }, + } as TransactionRefund, +} + +function createExample<Props>(Component: FunctionalComponent<Props>, props: Partial<Props>) { + const r = (args: any) => <Component {...args} /> + r.args = props + return r +} + +export const Empty = createExample(TestedComponent, { + list: [], + balances: [{ + available: 'TESTKUDOS:10', + pendingIncoming: 'TESTKUDOS:0', + pendingOutgoing: 'TESTKUDOS:0', + hasPendingTransactions: false, + requiresUserInput: false, + }] +}); + + +export const One = createExample(TestedComponent, { + list: [exampleData.withdraw], + balances: [{ + available: 'USD:10', + pendingIncoming: 'USD:0', + pendingOutgoing: 'USD:0', + hasPendingTransactions: false, + requiresUserInput: false, + }] +}); + +export const Several = createExample(TestedComponent, { + list: [ + exampleData.withdraw, + exampleData.payment, + exampleData.withdraw, + exampleData.payment, + exampleData.refresh, + exampleData.refund, + exampleData.tip, + exampleData.deposit, + ], + balances: [{ + available: 'TESTKUDOS:10', + pendingIncoming: 'TESTKUDOS:0', + pendingOutgoing: 'TESTKUDOS:0', + hasPendingTransactions: false, + requiresUserInput: false, + }] +}); + +export const SeveralWithTwoCurrencies = createExample(TestedComponent, { + list: [ + exampleData.withdraw, + exampleData.payment, + exampleData.withdraw, + exampleData.payment, + exampleData.refresh, + exampleData.refund, + exampleData.tip, + exampleData.deposit, + ], + balances: [{ + available: 'TESTKUDOS:10', + pendingIncoming: 'TESTKUDOS:0', + pendingOutgoing: 'TESTKUDOS:0', + hasPendingTransactions: false, + requiresUserInput: false, + },{ + available: 'USD:10', + pendingIncoming: 'USD:0', + pendingOutgoing: 'USD:0', + hasPendingTransactions: false, + requiresUserInput: false, + }] +}); + +// export const WithdrawPending = createExample(TestedComponent, { +// transaction: { ...exampleData.withdraw, pending: true }, +// }); + + +// export const Payment = createExample(TestedComponent, { +// transaction: exampleData.payment +// }); + +// export const PaymentWithoutFee = createExample(TestedComponent, { +// transaction: { +// ...exampleData.payment, +// amountRaw: 'USD:11', + +// } +// }); + +// export const PaymentPending = createExample(TestedComponent, { +// transaction: { ...exampleData.payment, pending: true }, +// }); + +// export const PaymentWithProducts = createExample(TestedComponent, { +// transaction: { +// ...exampleData.payment, +// info: { +// ...exampleData.payment.info, +// summary: 'this order has 5 products', +// products: [{ +// description: 't-shirt', +// unit: 'shirts', +// quantity: 1, +// }, { +// description: 't-shirt', +// unit: 'shirts', +// quantity: 1, +// }, { +// description: 'e-book', +// }, { +// description: 'beer', +// unit: 'pint', +// quantity: 15, +// }, { +// description: 'beer', +// unit: 'pint', +// quantity: 15, +// }] +// } +// } as TransactionPayment, +// }); + +// export const PaymentWithLongSummary = createExample(TestedComponent, { +// transaction: { +// ...exampleData.payment, +// info: { +// ...exampleData.payment.info, +// summary: 'this is a very long summary that will occupy severals lines, this is a very long summary that will occupy severals lines, this is a very long summary that will occupy severals lines, this is a very long summary that will occupy severals lines, ', +// products: [{ +// description: 'an xl sized t-shirt with some drawings on it, color pink', +// unit: 'shirts', +// quantity: 1, +// }, { +// description: 'beer', +// unit: 'pint', +// quantity: 15, +// }] +// } +// } as TransactionPayment, +// }); + + +// export const Deposit = createExample(TestedComponent, { +// transaction: exampleData.deposit +// }); + +// export const DepositPending = createExample(TestedComponent, { +// transaction: { ...exampleData.deposit, pending: true } +// }); + +// export const Refresh = createExample(TestedComponent, { +// transaction: exampleData.refresh +// }); + +// export const Tip = createExample(TestedComponent, { +// transaction: exampleData.tip +// }); + +// export const TipPending = createExample(TestedComponent, { +// transaction: { ...exampleData.tip, pending: true } +// }); + +// export const Refund = createExample(TestedComponent, { +// transaction: exampleData.refund +// }); + +// export const RefundPending = createExample(TestedComponent, { +// transaction: { ...exampleData.refund, pending: true } +// }); + +// export const RefundWithProducts = createExample(TestedComponent, { +// transaction: { +// ...exampleData.refund, +// info: { +// ...exampleData.refund.info, +// products: [{ +// description: 't-shirt', +// }, { +// description: 'beer', +// }] +// } +// } as TransactionRefund, +// }); diff --git a/packages/taler-wallet-webextension/src/wallet/History.tsx b/packages/taler-wallet-webextension/src/wallet/History.tsx new file mode 100644 index 000000000..6ef5047ae --- /dev/null +++ b/packages/taler-wallet-webextension/src/wallet/History.tsx @@ -0,0 +1,248 @@ +/* + This file is part of TALER + (C) 2016 GNUnet e.V. + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +import { AmountString, Balance, Timestamp, Transaction, TransactionsResponse, TransactionType } from "@gnu-taler/taler-util"; +import { format } from "date-fns"; +import { Fragment, JSX } from "preact"; +import { useEffect, useState } from "preact/hooks"; +import imageBank from '../../static/img/ri-bank-line.svg'; +import imageHandHeart from '../../static/img/ri-hand-heart-line.svg'; +import imageRefresh from '../../static/img/ri-refresh-line.svg'; +import imageRefund from '../../static/img/ri-refund-2-line.svg'; +import imageShoppingCart from '../../static/img/ri-shopping-cart-line.svg'; +import { Column, ExtraLargeText, HistoryRow, WalletBox, DateSeparator, SmallTextLight } from "../components/styled"; +import { useBalances } from "../hooks/useBalances"; +import * as wxApi from "../wxApi"; +import { Pages } from "../NavigationBar"; + + +export function HistoryPage(props: any): JSX.Element { + const [transactions, setTransactions] = useState< + TransactionsResponse | undefined + >(undefined); + const balance = useBalances() + const balanceWithoutError = balance?.error ? [] : (balance?.response.balances || []) + + useEffect(() => { + const fetchData = async (): Promise<void> => { + const res = await wxApi.getTransactions(); + setTransactions(res); + }; + fetchData(); + }, []); + + if (!transactions) { + return <div>Loading ...</div>; + } + + return <HistoryView balances={balanceWithoutError} list={[...transactions.transactions].reverse()} />; +} + +function amountToString(c: AmountString) { + const idx = c.indexOf(':') + return `${c.substring(idx + 1)} ${c.substring(0, idx)}` +} + + + +export function HistoryView({ list, balances }: { list: Transaction[], balances: Balance[] }) { + const byDate = list.reduce(function (rv, x) { + const theDate = x.timestamp.t_ms === "never" ? "never" : format(x.timestamp.t_ms, 'dd MMMM yyyy'); + (rv[theDate] = rv[theDate] || []).push(x); + return rv; + }, {} as { [x: string]: Transaction[] }); + + return <WalletBox noPadding> + {balances.length > 0 && <header> + {balances.length === 1 && <div class="title"> + Balance: <span>{amountToString(balances[0].available)}</span> + </div>} + {balances.length > 1 && <div class="title"> + Balance: <ul style={{ margin: 0 }}> + {balances.map(b => <li>{b.available}</li>)} + </ul> + </div>} + </header>} + <section> + {Object.keys(byDate).map(d => { + return <Fragment> + <DateSeparator>{d}</DateSeparator> + {byDate[d].map((tx, i) => ( + <TransactionItem key={i} tx={tx} /> + ))} + </Fragment> + })} + </section> + </WalletBox> +} + +function TransactionItem(props: { tx: Transaction }): JSX.Element { + const tx = props.tx; + switch (tx.type) { + case TransactionType.Withdrawal: + return ( + <TransactionLayout + id={tx.transactionId} + amount={tx.amountEffective} + debitCreditIndicator={"credit"} + title="Withdrawal" + subtitle={`via ${tx.exchangeBaseUrl}`} + timestamp={tx.timestamp} + iconPath={imageBank} + pending={tx.pending} + ></TransactionLayout> + ); + case TransactionType.Payment: + return ( + <TransactionLayout + id={tx.transactionId} + amount={tx.amountEffective} + debitCreditIndicator={"debit"} + title="Payment" + subtitle={tx.info.summary} + timestamp={tx.timestamp} + iconPath={imageShoppingCart} + pending={tx.pending} + ></TransactionLayout> + ); + case TransactionType.Refund: + return ( + <TransactionLayout + id={tx.transactionId} + amount={tx.amountEffective} + debitCreditIndicator={"credit"} + title="Refund" + subtitle={tx.info.summary} + timestamp={tx.timestamp} + iconPath={imageRefund} + pending={tx.pending} + ></TransactionLayout> + ); + case TransactionType.Tip: + return ( + <TransactionLayout + id={tx.transactionId} + amount={tx.amountEffective} + debitCreditIndicator={"credit"} + title="Tip" + subtitle={`from ${new URL(tx.merchantBaseUrl).hostname}`} + timestamp={tx.timestamp} + iconPath={imageHandHeart} + pending={tx.pending} + ></TransactionLayout> + ); + case TransactionType.Refresh: + return ( + <TransactionLayout + id={tx.transactionId} + amount={tx.amountEffective} + debitCreditIndicator={"credit"} + title="Refresh" + subtitle={`via exchange ${tx.exchangeBaseUrl}`} + timestamp={tx.timestamp} + iconPath={imageRefresh} + pending={tx.pending} + ></TransactionLayout> + ); + case TransactionType.Deposit: + return ( + <TransactionLayout + id={tx.transactionId} + amount={tx.amountEffective} + debitCreditIndicator={"debit"} + title="Refresh" + subtitle={`to ${tx.targetPaytoUri}`} + timestamp={tx.timestamp} + iconPath={imageRefresh} + pending={tx.pending} + ></TransactionLayout> + ); + } +} + +function TransactionLayout(props: TransactionLayoutProps): JSX.Element { + const date = new Date(props.timestamp.t_ms); + const dateStr = format(date, 'HH:mm:ss') + return ( + // <a href={Pages.transaction.replace(':tid', props.id)}> + <HistoryRow href={Pages.transaction.replace(':tid', props.id)}> + <img src={props.iconPath} /> + <Column> + <ExtraLargeText> + <span>{props.title}</span> + {props.pending ? ( + <span style={{ color: "darkblue" }}> (Pending)</span> + ) : null} + </ExtraLargeText> + <SmallTextLight>{dateStr}</SmallTextLight> + </Column> + <TransactionAmount + pending={props.pending} + amount={props.amount} + debitCreditIndicator={props.debitCreditIndicator} + /> + </HistoryRow> + // </a> + ); +} + +interface TransactionLayoutProps { + debitCreditIndicator: "debit" | "credit" | "unknown"; + amount: AmountString | "unknown"; + timestamp: Timestamp; + title: string; + id: string; + subtitle: string; + iconPath: string; + pending: boolean; +} + +interface TransactionAmountProps { + debitCreditIndicator: "debit" | "credit" | "unknown"; + amount: AmountString | "unknown"; + pending: boolean; +} + +function TransactionAmount(props: TransactionAmountProps): JSX.Element { + const [currency, amount] = props.amount.split(":"); + let sign: string; + switch (props.debitCreditIndicator) { + case "credit": + sign = "+"; + break; + case "debit": + sign = "-"; + break; + case "unknown": + sign = ""; + } + return ( + <Column style={{ + color: + props.pending ? "gray" : + (sign === '+' ? 'darkgreen' : + (sign === '-' ? 'darkred' : + undefined)) + }}> + <ExtraLargeText> + {sign} + {amount} + </ExtraLargeText> + <div>{currency}</div> + </Column> + ); +} + diff --git a/packages/taler-wallet-webextension/src/wallet/Welcome.stories.tsx b/packages/taler-wallet-webextension/src/wallet/Welcome.stories.tsx index 4fa87a137..6579450b3 100644 --- a/packages/taler-wallet-webextension/src/wallet/Welcome.stories.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Welcome.stories.tsx @@ -19,7 +19,7 @@ * @author Sebastian Javier Marchano (sebasjm) */ -import { FunctionalComponent, h } from 'preact'; +import { createExample } from '../test-utils'; import { View as TestedComponent } from './Welcome'; @@ -28,12 +28,6 @@ export default { component: TestedComponent, }; -function createExample<Props>(Component: FunctionalComponent<Props>, props: Partial<Props>) { - const r = (args: any) => <Component {...args} /> - r.args = props - return r -} - export const Normal = createExample(TestedComponent, { permissionsEnabled: true, diagnostics: { diff --git a/packages/taler-wallet-webextension/src/wallet/Welcome.tsx b/packages/taler-wallet-webextension/src/wallet/Welcome.tsx index 4c33e1c72..0738e14b6 100644 --- a/packages/taler-wallet-webextension/src/wallet/Welcome.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Welcome.tsx @@ -24,7 +24,7 @@ import { JSX } from "preact/jsx-runtime"; import { Checkbox } from "../components/Checkbox"; import { useExtendedPermissions } from "../hooks/useExtendedPermissions"; import { Diagnostics } from "../components/Diagnostics"; -import { WalletPage } from "../components/styled"; +import { WalletBox } from "../components/styled"; import { useDiagnostics } from "../hooks/useDiagnostics"; import { WalletDiagnostics } from "@gnu-taler/taler-util"; @@ -44,12 +44,7 @@ export interface ViewProps { timedOut: boolean, } export function View({ permissionsEnabled, togglePermissions, diagnostics, timedOut }: ViewProps): JSX.Element { - return (<WalletPage> - <div style="border-bottom: 3px dashed #aa3939; margin-bottom: 2em;"> - <h1 style="font-family: monospace; font-size: 250%;"> - <span style="color: #aa3939;">❰</span>Taler Wallet<span style="color: #aa3939;">❱</span> - </h1> - </div> + return (<WalletBox> <h1>Browser Extension Installed!</h1> <div> <p>Thank you for installing the wallet.</p> @@ -68,6 +63,6 @@ export function View({ permissionsEnabled, togglePermissions, diagnostics, timed Learn how to top up your wallet balance » </a> </div> - </WalletPage> + </WalletBox> ); } diff --git a/packages/taler-wallet-webextension/src/walletEntryPoint.tsx b/packages/taler-wallet-webextension/src/walletEntryPoint.tsx index f487e54fc..f8191a0fb 100644 --- a/packages/taler-wallet-webextension/src/walletEntryPoint.tsx +++ b/packages/taler-wallet-webextension/src/walletEntryPoint.tsx @@ -20,17 +20,24 @@ * @author Florian Dold <dold@taler.net> */ -import { render } from "preact"; +import { Fragment, render } from "preact"; import { setupI18n } from "@gnu-taler/taler-util"; import { strings } from "./i18n/strings"; import { createHashHistory } from 'history'; -import { WithdrawPage } from "./wallet/Withdraw"; import { WelcomePage } from "./wallet/Welcome"; -import { PayPage } from "./wallet/Pay"; -import { RefundPage } from "./wallet/Refund"; -import { TipPage } from './wallet/Tip'; +import { HistoryPage } from "./wallet/History"; +import { WithdrawPage } from "./cta/Withdraw"; +import { PayPage } from "./cta/Pay"; +import { RefundPage } from "./cta/Refund"; +import { TipPage } from './cta/Tip'; import Router, { route, Route } from "preact-router"; +import { DevContextProvider } from "./context/devContext"; +import { LogoHeader } from "./components/LogoHeader"; +import { useEffect } from "preact/hooks"; +import { + Pages, WalletNavBar +} from "./NavigationBar"; function main(): void { try { @@ -53,32 +60,43 @@ if (document.readyState === "loading") { main(); } - -enum Pages { - welcome = '/welcome', - pay = '/pay', - payback = '/payback', - refund = '/refund', - reset_required = '/reset-required', - return_coins = '/return-coins', - tips = '/tips', - withdraw = '/withdraw', +function withLogoAndNavBar(Component: any) { + return () => <Fragment> + <LogoHeader /> + <WalletNavBar /> + <Component /> + </Fragment> } function Application() { - const h = createHashHistory(); - return <Router history={h} > + return <div> + <DevContextProvider> + <Router history={createHashHistory()} > + + <Route path={Pages.welcome} component={withLogoAndNavBar(WelcomePage)} /> - <Route path={Pages.welcome} component={WelcomePage} /> - <Route path={Pages.pay} component={PayPage} /> - <Route path={Pages.refund} component={RefundPage} /> + <Route path={Pages.history} component={withLogoAndNavBar(HistoryPage)} /> + <Route path={Pages.transaction} component={withLogoAndNavBar(HistoryPage)} /> - <Route path={Pages.tips} component={TipPage} /> - <Route path={Pages.withdraw} component={WithdrawPage} /> + <Route path={Pages.reset_required} component={() => <div>no yet implemented</div>} /> + <Route path={Pages.payback} component={() => <div>no yet implemented</div>} /> + <Route path={Pages.return_coins} component={() => <div>no yet implemented</div>} /> - <Route path={Pages.reset_required} component={() => <div>no yet implemented</div>} /> - <Route path={Pages.payback} component={() => <div>no yet implemented</div>} /> - <Route path={Pages.return_coins} component={() => <div>no yet implemented</div>} /> + {/** call to action */} + <Route path={Pages.pay} component={PayPage} /> + <Route path={Pages.refund} component={RefundPage} /> + <Route path={Pages.tips} component={TipPage} /> + <Route path={Pages.withdraw} component={WithdrawPage} /> + + <Route default component={Redirect} to={Pages.history} /> + </Router> + </DevContextProvider> + </div> +} - </Router> +function Redirect({ to }: { to: string }): null { + useEffect(() => { + route(to, true) + }) + return null } diff --git a/packages/taler-wallet-webextension/static/img/logo-2021.svg b/packages/taler-wallet-webextension/static/img/logo-2021.svg new file mode 100644 index 000000000..e72611eba --- /dev/null +++ b/packages/taler-wallet-webextension/static/img/logo-2021.svg @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" width="670" height="300" viewBox="0 0 201 90"><g fill="#0042b3" fill-rule="evenodd" stroke-width=".3"><path d="M86.7 1.1c15.6 0 29 9.4 36 23.2h-5.9A35.1 35.1 0 0086.7 6.5C67 6.5 51 23.6 51 44.7c0 10.4 3.8 19.7 10 26.6a31.4 31.4 0 01-4.2 3A45.2 45.2 0 0146 44.7c0-24 18.2-43.6 40.7-43.6zm35.8 64.3a40.4 40.4 0 01-39 22.8c3-1.5 6-3.5 8.6-5.7a35.6 35.6 0 0024.6-17.1z"/><path d="M64.2 1.1l3.1.1c-3 1.6-5.9 3.5-8.5 5.8a37.5 37.5 0 00-30.2 37.7c0 14.3 7.3 26.7 18 33.3a29.6 29.6 0 01-8.5.2c-9-8-14.6-20-14.6-33.5 0-24 18.2-43.6 40.7-43.6zm5.4 81.4a35.6 35.6 0 0024.6-17.1h5.9a40.4 40.4 0 01-39 22.8c3-1.5 5.9-3.5 8.5-5.7zm24.8-58.2a37 37 0 00-12.6-12.8 29.6 29.6 0 018.5-.2c4 3.6 7.4 8 9.9 13z"/><path d="M41.8 1.1c1 0 2 0 3.1.2-3 1.5-5.9 3.4-8.5 5.6A37.5 37.5 0 006.1 44.7c0 21.1 16 38.3 35.7 38.3 12.6 0 23.6-7 30-17.6h5.8a40.4 40.4 0 01-35.8 23C19.3 88.4 1 68.8 1 44.7c0-24 18.2-43.6 40.7-43.6zm30.1 23.2a38.1 38.1 0 00-4.5-6.1c1.3-1.2 2.7-2.2 4.3-3 2.3 2.7 4.4 5.8 6 9.1z"/></g><path d="M76.1 34.4h9.2v-5H61.9v5H71v26h5.1zM92.6 52.9h13.7l3 7.4h5.3l-12.7-31.2h-4.7L84.5 60.3h5.2zm11.8-4.9h-9.9l5-12.4zM123.8 29.4h-4.6v31h20.6v-5h-16zM166.5 29.4H145v31h21.6v-5H150v-8.3h14.5v-4.9h-14.5v-8h16.4zM191.2 39.5c0 1.6-.5 2.8-1.6 3.8s-2.6 1.4-4.4 1.4h-7.4V34.3h7.4c1.9 0 3.4.4 4.4 1.3 1 .9 1.6 2.2 1.6 3.9zm6 20.8l-7.7-11.7c1-.3 1.9-.7 2.7-1.3a8.8 8.8 0 003.6-4.6c.4-1 .5-2.2.5-3.5 0-1.5-.2-2.9-.7-4.1a8.4 8.4 0 00-2.1-3.1c-1-.8-2-1.5-3.4-2-1.3-.4-2.8-.6-4.5-.6h-12.9v31h5V49.4h6.5l7 10.8z"/></svg>
\ No newline at end of file diff --git a/packages/taler-wallet-webextension/static/style/wallet.css b/packages/taler-wallet-webextension/static/style/wallet.css index 32a96dbc4..859789149 100644 --- a/packages/taler-wallet-webextension/static/style/wallet.css +++ b/packages/taler-wallet-webextension/static/style/wallet.css @@ -2,6 +2,7 @@ body { font-size: 100%; overflow-y: scroll; margin-top: 2em; + font-family: Arial, Helvetica, sans-serif; } .wallet-container { |