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