CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/billing/payment-method.tsx
Views: 687
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import { Rendered, useState } from "../app-framework";
7
import {
8
Alert,
9
Button,
10
ButtonToolbar,
11
Row,
12
Col,
13
} from "@cocalc/frontend/antd-bootstrap";
14
import { Icon, IconName } from "../components/icon";
15
import { Gap } from "../components/gap";
16
import { brand_to_icon_name } from "./data";
17
18
import { Source } from "./types";
19
20
interface Props {
21
source: Source;
22
default?: boolean; // required for set_as_default
23
set_as_default?: Function; // called when this card should be set to default
24
delete_method?: Function; // called when this card should be deleted
25
}
26
27
export const PaymentMethod: React.FC<Props> = (props) => {
28
const [confirm_default, set_confirm_default] = useState<boolean>(false);
29
const [confirm_delete, set_confirm_delete] = useState<boolean>(false);
30
31
function icon_name(): IconName {
32
return brand_to_icon_name(
33
props.source.brand != null ? props.source.brand.toLowerCase() : undefined,
34
);
35
}
36
37
function render_confirm_default(): Rendered {
38
return (
39
<Alert bsStyle="warning">
40
<Row>
41
<Col md={5} mdOffset={2}>
42
<p>
43
Are you sure you want to set this payment card to be the default?
44
</p>
45
<p>
46
All future payments will be made with the card that is the default{" "}
47
<b>at the time of renewal</b>. Changing your default card right
48
before a subscription renewal will cause the <Gap />
49
new default to be charged instead of the previous one.
50
</p>
51
</Col>
52
<Col md={5}>
53
<ButtonToolbar>
54
<Button
55
onClick={() => {
56
set_confirm_default(false);
57
if (props.set_as_default != null) props.set_as_default();
58
}}
59
bsStyle="warning"
60
>
61
<Icon name="trash" /> Set to Default
62
</Button>
63
<Button onClick={() => set_confirm_default(false)}>Cancel</Button>
64
</ButtonToolbar>
65
</Col>
66
</Row>
67
</Alert>
68
);
69
}
70
71
function render_confirm_delete(): Rendered {
72
return (
73
<Alert bsStyle="danger">
74
<Row>
75
<Col md={5} mdOffset={2}>
76
Are you sure you want to delete this payment method?
77
</Col>
78
<Col md={5}>
79
<ButtonToolbar>
80
<Button
81
bsStyle="danger"
82
onClick={() => {
83
set_confirm_delete(false);
84
if (props.delete_method != null) props.delete_method();
85
}}
86
>
87
<Icon name="trash" /> Delete Payment Method
88
</Button>
89
<Button onClick={() => set_confirm_delete(false)}>Cancel</Button>
90
</ButtonToolbar>
91
</Col>
92
</Row>
93
</Alert>
94
);
95
}
96
97
function render_card(): Rendered {
98
return (
99
<Row>
100
<Col md={2}>
101
<Icon name={icon_name()} /> {props.source.brand}
102
</Col>
103
<Col md={1}>
104
<em>····</em>
105
{props.source.last4}
106
</Col>
107
<Col md={1}>
108
{props.source.exp_month}/{props.source.exp_year}
109
</Col>
110
<Col md={2}>{props.source.name}</Col>
111
<Col md={1}>{props.source.address_country}</Col>
112
<Col md={2}>
113
{props.source.address_state}
114
<Gap />
115
<Gap />
116
{props.source.address_zip}
117
</Col>
118
{props.set_as_default != null || props.delete_method != null
119
? render_action_buttons()
120
: undefined}
121
</Row>
122
);
123
}
124
125
function render_action_buttons(): Rendered {
126
return (
127
<Col md={3}>
128
<ButtonToolbar style={{ float: "right" }}>
129
{props.set_as_default != null ? (
130
<Button
131
onClick={() => set_confirm_default(true)}
132
disabled={props.default}
133
bsStyle={props.default ? "primary" : "default"}
134
>
135
Default{!props.default ? <span>... </span> : undefined}
136
</Button>
137
) : undefined}
138
139
{props.delete_method != null ? (
140
<Button onClick={() => set_confirm_delete(true)}>
141
<Icon name="trash" /> Delete
142
</Button>
143
) : undefined}
144
</ButtonToolbar>
145
</Col>
146
);
147
}
148
149
return (
150
<div
151
style={{
152
borderBottom: "1px solid #999",
153
paddingTop: "5px",
154
paddingBottom: "5px",
155
}}
156
>
157
{render_card()}
158
{confirm_default ? render_confirm_default() : undefined}
159
{confirm_delete ? render_confirm_delete() : undefined}
160
</div>
161
);
162
};
163
164