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/pages/vouchers/redeemed.tsx
Views: 687
1
/*
2
* This file is part of CoCalc: Copyright © 2023 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import { useMemo } from "react";
7
import Footer from "components/landing/footer";
8
import Header from "components/landing/header";
9
import Head from "components/landing/head";
10
import { Alert, Card, Layout, Space, Table } from "antd";
11
import withCustomize from "lib/with-customize";
12
import { Customize } from "lib/customize";
13
import { Icon } from "@cocalc/frontend/components/icon";
14
import A from "components/misc/A";
15
import InPlaceSignInOrUp from "components/auth/in-place-sign-in-or-up";
16
import useProfile from "lib/hooks/profile";
17
import { useRouter } from "next/router";
18
import Loading from "components/share/loading";
19
import useDatabase from "lib/hooks/database";
20
import TimeAgo from "timeago-react";
21
import { field_cmp, plural } from "@cocalc/util/misc";
22
import { r_join } from "@cocalc/frontend/components/r_join";
23
import License from "components/licenses/license";
24
import Help from "components/vouchers/help";
25
26
const VOUCHER_CODES_QUERY = {
27
voucher_codes: [
28
{
29
code: null,
30
id: null,
31
when_redeemed: null,
32
canceled: null,
33
license_ids: null,
34
purchase_ids: null,
35
},
36
],
37
} as const;
38
39
const COLUMNS = [
40
{
41
title: "Code",
42
dataIndex: "code",
43
key: "code",
44
},
45
{
46
title: "When Redeemed",
47
dataIndex: "when_redeemed",
48
key: "when_redeemed",
49
render: (_, { when_redeemed }) => (
50
<>
51
<TimeAgo datetime={when_redeemed} />
52
</>
53
),
54
},
55
{
56
title: "Canceled",
57
dataIndex: "canceled",
58
key: "canceled",
59
align: "center",
60
render: (_, { canceled }) => (canceled ? "Yes" : "-"),
61
},
62
{
63
title: "Licenses",
64
dataIndex: "license_ids",
65
key: "license_ids",
66
render: (_, { license_ids }) => {
67
if (!license_ids || license_ids.length == 0) return null;
68
return r_join(
69
license_ids.map((license_id) => (
70
<License key={license_id} license_id={license_id} />
71
))
72
);
73
},
74
},
75
{
76
title: "Credits to Account",
77
dataIndex: "purchase_ids",
78
key: "purchase_ids",
79
render: (_, { purchase_ids }) => {
80
if (!purchase_ids || purchase_ids.length == 0) return null;
81
return (
82
<div>
83
<A href="/settings/purchases" external>
84
{plural(purchase_ids.length, "Transaction Id")}:{" "}
85
{purchase_ids.join(", ")}
86
</A>
87
</div>
88
);
89
},
90
},
91
] as any;
92
93
export default function Redeemed({ customize }) {
94
const { loading, value, error, setError } = useDatabase(VOUCHER_CODES_QUERY);
95
const profile = useProfile({ noCache: true });
96
const router = useRouter();
97
const data = useMemo(() => {
98
const cmp = field_cmp("when_redeemed");
99
return (value?.voucher_codes ?? []).sort((a, b) => -cmp(a, b));
100
}, [value]);
101
102
return (
103
<Customize value={customize}>
104
<Head title="Vouchers You Redeemed" />
105
<Layout>
106
<Header />
107
<Layout.Content style={{ background: "white" }}>
108
<div
109
style={{
110
width: "100%",
111
margin: "10vh 0",
112
display: "flex",
113
justifyContent: "center",
114
}}
115
>
116
{profile == null && <Loading />}
117
{profile != null && !profile.account_id && (
118
<Card>
119
<div style={{ fontSize: "75px", textAlign: "center" }}>
120
<Icon name="gift2"/>
121
</div>
122
<InPlaceSignInOrUp
123
title="Redeemed Vouchers"
124
why="to see vouchers you've redeemed"
125
style={{ width: "450px" }}
126
onSuccess={() => {
127
router.reload();
128
}}
129
/>
130
</Card>
131
)}
132
{profile?.account_id && (
133
<Card style={{ background: "#fafafa" }}>
134
<Space direction="vertical" align="center">
135
<A href="/vouchers">
136
<Icon name="gift2" style={{ fontSize: "75px" }} />
137
</A>
138
<h1>Vouchers You Redeemed</h1>
139
{error && (
140
<Alert
141
type="error"
142
message={error}
143
showIcon
144
style={{ width: "100%", marginBottom: "30px" }}
145
closable
146
onClose={() => setError("")}
147
/>
148
)}
149
{loading && <Loading />}
150
{!loading && data.length > 0 && (
151
<Table
152
columns={COLUMNS}
153
dataSource={data}
154
rowKey="code"
155
pagination={{ defaultPageSize: 50 }}
156
/>
157
)}
158
{!loading && data.length == 0 && (
159
<div>
160
You have not <A href="/redeem">redeemed any vouchers</A>{" "}
161
yet.
162
</div>
163
)}
164
<Help />
165
</Space>
166
</Card>
167
)}
168
</div>
169
<Footer />
170
</Layout.Content>
171
</Layout>
172
</Customize>
173
);
174
}
175
176
export async function getServerSideProps(context) {
177
return await withCustomize({ context });
178
}
179
180