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/created.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 } from "@cocalc/util/misc";
22
import { money } from "@cocalc/util/licenses/purchase/utils";
23
import Help from "components/vouchers/help";
24
25
const QUERY = {
26
vouchers: [
27
{
28
id: null,
29
created: null,
30
active: null,
31
expire: null,
32
cancel_by: null,
33
title: null,
34
count: null,
35
cost: null,
36
tax: null,
37
cart: null,
38
when_pay: null,
39
purchased: null,
40
},
41
],
42
} as const;
43
44
export const COLUMNS = [
45
{
46
title: "ID",
47
dataIndex: "id",
48
key: "id",
49
},
50
{
51
title: "Created",
52
dataIndex: "created",
53
key: "created",
54
render: (_, { id, created }) => (
55
<A href={`/vouchers/${id}`}>{<TimeAgo datetime={created} />}</A>
56
),
57
},
58
{
59
title: (
60
<>
61
Codes
62
<br />
63
(click to view)
64
</>
65
),
66
dataIndex: "count",
67
key: "count",
68
align: "center",
69
render: (_, { id, count }) => <A href={`/vouchers/${id}`}>{count}</A>,
70
},
71
72
{
73
title: "Cost",
74
dataIndex: "cost",
75
key: "cost",
76
align: "center",
77
render: (_, { id, cost, tax }) => (
78
<A href={`/vouchers/${id}`}>
79
{money(cost, true)}
80
{tax ? ` (+ ${money(tax, true)} tax)` : ""} each
81
</A>
82
),
83
},
84
{
85
title: "Status",
86
render: (_, { id, when_pay, purchased }) => (
87
<A href={`/vouchers/${id}`}>
88
<Status when_pay={when_pay} purchased={purchased} />
89
</A>
90
),
91
},
92
{
93
title: "Description",
94
dataIndex: "title",
95
key: "title",
96
render: (_, { title, id }) => {
97
return <A href={`/vouchers/${id}`}>{title}</A>;
98
},
99
},
100
{
101
title: "Active",
102
dataIndex: "active",
103
key: "active",
104
align: "center",
105
render: (_, { id, active }) => (
106
<A href={`/vouchers/${id}`}>
107
<TimeAgo datetime={active} />
108
</A>
109
),
110
},
111
{
112
title: "Expire",
113
dataIndex: "expire",
114
key: "expire",
115
align: "center",
116
render: (_, { id, expire }) => (
117
<A href={`/vouchers/${id}`}>
118
<TimeAgo datetime={expire} />
119
</A>
120
),
121
},
122
{
123
title: "Cancel By",
124
dataIndex: "cancel_by",
125
key: "cancel_by",
126
align: "center",
127
render: (_, { id, cancel_by }) => (
128
<A href={`/vouchers/${id}`}>
129
<TimeAgo datetime={cancel_by} />
130
</A>
131
),
132
},
133
] as any;
134
135
export default function Created({ customize }) {
136
const { loading, value, error, setError } = useDatabase(QUERY);
137
const profile = useProfile({ noCache: true });
138
const router = useRouter();
139
const data = useMemo(() => {
140
const cmp = field_cmp("created");
141
return (value?.vouchers ?? []).sort((a, b) => -cmp(a, b));
142
}, [value]);
143
144
return (
145
<Customize value={customize}>
146
<Head title="Your Vouchers" />
147
<Layout>
148
<Header />
149
<Layout.Content style={{ background: "white" }}>
150
<div
151
style={{
152
width: "100%",
153
margin: "10vh 0",
154
display: "flex",
155
justifyContent: "center",
156
}}
157
>
158
{profile == null && <Loading />}
159
{profile != null && !profile.account_id && (
160
<Card>
161
<div style={{ fontSize: "75px", textAlign: "center" }}>
162
<Icon name="gift2"/>
163
</div>
164
<InPlaceSignInOrUp
165
title="Created Vouchers"
166
why="to see vouchers you've created"
167
style={{ width: "450px" }}
168
onSuccess={() => {
169
router.reload();
170
}}
171
/>
172
</Card>
173
)}
174
{profile?.account_id && (
175
<Card style={{ background: "#fafafa" }}>
176
<Space direction="vertical" align="center">
177
<A href="/vouchers">
178
<Icon name="gift2" style={{ fontSize: "75px" }} />
179
</A>
180
<h1>Your Vouchers ({data.length})</h1>
181
{error && (
182
<Alert
183
type="error"
184
message={error}
185
showIcon
186
style={{ width: "100%", marginBottom: "30px" }}
187
closable
188
onClose={() => setError("")}
189
/>
190
)}
191
{loading && <Loading />}
192
{!loading && data.length > 0 && (
193
<Table
194
columns={COLUMNS}
195
dataSource={data}
196
rowKey="id"
197
pagination={{ defaultPageSize: 50 }}
198
/>
199
)}
200
{!loading && data.length == 0 && (
201
<div>
202
You have not <A href="/redeem">redeemed any vouchers</A>{" "}
203
yet.
204
</div>
205
)}
206
<Help />
207
</Space>
208
</Card>
209
)}
210
</div>
211
<Footer />
212
</Layout.Content>
213
</Layout>
214
</Customize>
215
);
216
}
217
218
export async function getServerSideProps(context) {
219
return await withCustomize({ context });
220
}
221
222
function Status({ when_pay, purchased }) {
223
if (when_pay == "now") {
224
return <>Paid</>;
225
}
226
if (when_pay == "invoice") {
227
return purchased?.time ? (
228
<>
229
Paid <TimeAgo datetime={purchased.time} />
230
</>
231
) : (
232
<>Invoice at Expiration</>
233
);
234
}
235
if (when_pay == "admin") {
236
return <>Admin (free)</>;
237
}
238
return null;
239
}
240
241