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/next/components/billing/invoices-and-receipts.tsx
Views: 687
1
/*
2
* This file is part of CoCalc: Copyright © 2021 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import { Alert, Table } from "antd";
7
8
import { Icon } from "@cocalc/frontend/components/icon";
9
import { cmp, stripeAmount } from "@cocalc/util/misc";
10
import License from "components/licenses/license";
11
import { Paragraph, Title } from "components/misc";
12
import A from "components/misc/A";
13
import Timestamp from "components/misc/timestamp";
14
import Loading from "components/share/loading";
15
import useAPI from "lib/hooks/api";
16
17
function Description({ hosted_invoice_url, lines, metadata }) {
18
const license_id =
19
metadata?.license_id ?? lines.data[0]?.metadata?.license_id;
20
return (
21
<div style={{ wordWrap: "break-word", wordBreak: "break-word" }}>
22
{lines.data[0]?.description}
23
{(lines?.total_count ?? 1) > 1 && ", etc."}
24
{hosted_invoice_url && (
25
<div>
26
<A href={hosted_invoice_url}>
27
<Icon name="external-link" /> Invoice/Receipt
28
</A>
29
</div>
30
)}
31
{license_id && (
32
<div>
33
License: <License license_id={license_id} />
34
</div>
35
)}
36
</div>
37
);
38
}
39
40
function Status({ status, due_date, hosted_invoice_url }) {
41
if (status == "paid") {
42
return <>Paid</>;
43
}
44
return (
45
<A style={{ color: "red" }} href={hosted_invoice_url}>
46
<Icon name="external-link" /> Due{" "}
47
<Timestamp epoch={1000 * due_date} dateOnly />
48
</A>
49
);
50
}
51
52
function Created({ created }) {
53
return <Timestamp epoch={1000 * created} dateOnly />;
54
}
55
56
function Amount({ total, currency }) {
57
return <>{stripeAmount(total, currency)}</>;
58
}
59
60
const columns = [
61
{
62
responsive: ["xs"],
63
title: "Invoices and Receipts",
64
render: (_, invoice) => (
65
<div>
66
<Description {...invoice} />
67
Created: <Created {...invoice} />
68
<br />
69
<Amount {...invoice} />
70
<br />
71
<Status {...invoice} />
72
</div>
73
),
74
},
75
{
76
responsive: ["sm"],
77
title: "Description",
78
width: "50%",
79
render: (_, invoice) => <Description {...invoice} />,
80
},
81
{
82
responsive: ["sm"],
83
title: "Status",
84
align: "center" as "center",
85
render: (_, invoice) => <Status {...invoice} />,
86
sorter: { compare: (a, b) => cmp(a.status, b.status) },
87
},
88
{
89
responsive: ["sm"],
90
title: "Created",
91
align: "center" as "center",
92
render: (_, invoice) => <Created {...invoice} />,
93
sorter: { compare: (a, b) => -cmp(a.created, b.created) },
94
},
95
{
96
responsive: ["sm"],
97
title: "Amount",
98
align: "right",
99
render: (_, invoice) => <Amount {...invoice} />,
100
sorter: { compare: (a, b) => cmp(a.amount_paid ?? 0, b.amount_paid ?? 0) },
101
},
102
];
103
104
export default function InvoicesAndReceipts() {
105
const { result, error } = useAPI("billing/get-invoices-and-receipts");
106
if (error) {
107
return <Alert type="error" message={error} />;
108
}
109
if (!result) {
110
return <Loading />;
111
}
112
return (
113
<div>
114
<Title level={2}>Invoices and Receipts</Title>
115
<Paragraph style={{ marginBottom: "30px" }}>
116
Your recent invoices and receipts are listed below. Click on the
117
"Invoice" link to get a printable invoice or receipt version.
118
</Paragraph>
119
<Table
120
columns={columns as any}
121
dataSource={result.data ?? []}
122
rowKey={"id"}
123
style={{ marginTop: "15px" }}
124
pagination={{ hideOnSinglePage: true, pageSize: 100 }}
125
/>
126
</div>
127
);
128
}
129
130