1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
import { Amounts, BackupBackupProviderTerms, i18n } from "@gnu-taler/taler-util";
import { privateDecrypt } from "crypto";
import { add, addYears } from "date-fns";
import { VNode } from "preact";
import { useState } from "preact/hooks";
import * as wxApi from "../wxApi";
import ProviderAddConfirmProviderStories from "./ProviderAddConfirmProvider.stories";
interface Props {
currency: string;
}
export function ProviderAddPage({ currency }: Props): VNode {
const [verifying, setVerifying] = useState<{ url: string, provider: BackupBackupProviderTerms } | undefined>(undefined)
if (!verifying) {
return <SetUrlView
currency={currency}
onCancel={() => {
setVerifying(undefined);
}}
onVerify={(url) => {
return fetch(url).then(r => r.json())
.then((provider) => setVerifying({ url, provider }))
.catch((e) => e.message)
}}
/>
}
return <ConfirmProviderView
provider={verifying.provider}
currency={currency}
url={verifying.url}
onCancel={() => {
setVerifying(undefined);
}}
onConfirm={() => {
wxApi.addBackupProvider(verifying.url).then(_ => history.go(-1))
}}
/>
}
export interface SetUrlViewProps {
currency: string,
onCancel: () => void;
onVerify: (s: string) => Promise<string | undefined>;
}
export function SetUrlView({ currency, onCancel, onVerify }: SetUrlViewProps) {
const [value, setValue] = useState<string>("")
const [error, setError] = useState<string | undefined>(undefined)
return <div style={{ display: 'flex', flexDirection: 'column' }}>
<section style={{ height: 'calc(320px - 34px - 34px - 16px)', overflow: 'auto' }}>
<div>
Add backup provider for storing <b>{currency}</b>
</div>
{error && <div class="errorbox" style={{ marginTop: 10 }} >
<p>{error}</p>
</div>}
<h3>Backup provider URL</h3>
<input style={{ width: 'calc(100% - 8px)' }} value={value} onChange={(e) => setValue(e.currentTarget.value)} />
<p>
Backup providers may charge for their service
</p>
</section>
<footer style={{ marginTop: 'auto', display: 'flex', flexShrink: 0 }}>
<button class="pure-button" onClick={onCancel}><i18n.Translate>cancel</i18n.Translate></button>
<div style={{ width: '100%', flexDirection: 'row', justifyContent: 'flex-end', display: 'flex' }}>
<button class="pure-button button-secondary" style={{ marginLeft: 5 }} onClick={() => onVerify(value).then(r => r ? setError(r) : undefined)}><i18n.Translate>verify service terms</i18n.Translate></button>
</div>
</footer>
</div>
}
export interface ConfirmProviderViewProps {
provider: BackupBackupProviderTerms,
currency: string,
url: string,
onCancel: () => void;
onConfirm: () => void
}
export function ConfirmProviderView({ url, provider, currency, onCancel, onConfirm }: ConfirmProviderViewProps) {
return <div style={{ display: 'flex', flexDirection: 'column' }}>
<section style={{ height: 'calc(320px - 34px - 34px - 16px)', overflow: 'auto' }}>
<div>
Verify provider service terms for storing <b>{currency}</b>
</div>
<h3>{url}</h3>
<p>
{Amounts.isZero(provider.annual_fee) ? 'free of charge' : provider.annual_fee} for a year of backup service
</p>
<p>
{provider.storage_limit_in_megabytes} megabytes of storage
</p>
</section>
<footer style={{ marginTop: 'auto', display: 'flex', flexShrink: 0 }}>
<button class="pure-button" onClick={onCancel}>
<i18n.Translate>cancel</i18n.Translate>
</button>
<div style={{ width: '100%', flexDirection: 'row', justifyContent: 'flex-end', display: 'flex' }}>
<button class="pure-button button-success" style={{ marginLeft: 5 }} onClick={onConfirm}>
<i18n.Translate>confirm</i18n.Translate>
</button>
</div>
</footer>
</div>
}
|