Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/next/components/store/congrats.tsx
1450 views
1
/*
2
Page that you show user after they successfully complete a purchase.
3
4
It queries the backend for "the most recent stuff you bought", thanks
5
you for your purchase, has useful links, etc.
6
7
NOTE: the current implementation is just a really simple one that assumes
8
you are purchasing a license for projects, since that's all we sell
9
right now. This will have to be a bit more sophisticated when there's
10
more products.
11
*/
12
13
import { Icon } from "@cocalc/frontend/components/icon";
14
import { plural } from "@cocalc/util/misc";
15
import { Alert, Card } from "antd";
16
import Image from "components/landing/image";
17
import License from "components/licenses/license";
18
import A from "components/misc/A";
19
import Loading from "components/share/loading";
20
import SiteName from "components/share/site-name";
21
import useAPI from "lib/hooks/api";
22
import bella from "public/shopping/bella.png";
23
import TimeAgo from "timeago-react";
24
25
import type { JSX } from "react";
26
27
export default function Congrats() {
28
const purchases = useAPI("/shopping/cart/recent-purchases", {
29
recent: "2 day",
30
});
31
const vouchers = useAPI("/vouchers/recent-vouchers", {
32
recent: "2 day",
33
});
34
35
if (purchases.error) {
36
return <Alert type="error" message={purchases.error} />;
37
}
38
if (vouchers.error) {
39
return <Alert type="error" message={vouchers.error} />;
40
}
41
if (!purchases.result || !vouchers.result) {
42
return <Loading large center />;
43
}
44
45
const billingInfo = (
46
<Alert
47
showIcon
48
style={{ margin: "15px 0" }}
49
type="info"
50
message={
51
<>
52
Browse your <A href="/settings/payments">invoices</A>,{" "}
53
<A href="/settings/purchases">receipts</A> and{" "}
54
<A href="/settings/subscriptions">subscriptions</A>, or visit the{" "}
55
<A href="/vouchers">voucher center</A>.
56
</>
57
}
58
/>
59
);
60
61
if (purchases.result.length == 0 && vouchers.result.length == 0) {
62
return <div>You have no recent purchases or vouchers. {billingInfo}</div>;
63
}
64
65
function renderNextSteps(): JSX.Element {
66
return (
67
<>
68
<h2>Here are your next steps</h2>
69
<ul>
70
{purchases.result.length > 0 && (
71
<li style={{ marginBottom: "15px" }}>
72
<b>Licenses:</b> You are a manager for each of the licenses you
73
purchased.{" "}
74
<A href="/settings/licenses">You manage your licenses</A>, add
75
other people as managers, edit the title, description and every
76
property of each license, and{" "}
77
<A href="/licenses/how-used">see how a license is being used</A>.
78
<ul>
79
<li style={{ marginBottom: "15px" }}>
80
You can{" "}
81
<A href="https://doc.cocalc.com/project-settings.html#project-add-license">
82
apply a license to projects
83
</A>
84
,{" "}
85
<A href="https://doc.cocalc.com/teaching-upgrade-course.html#install-course-license">
86
courses
87
</A>
88
, or directly share the license code, as{" "}
89
<A href="https://doc.cocalc.com/licenses.html">
90
explained here
91
</A>
92
. It's time to make your <SiteName /> projects much, much
93
better.
94
</li>
95
</ul>
96
</li>
97
)}
98
{vouchers.result.length > 0 && (
99
<li style={{ marginBottom: "15px" }}>
100
<b>Vouchers:</b> You can{" "}
101
<A href="/vouchers/created">
102
browse all the vouchers you have created
103
</A>
104
, and everything else involving vouchers at the{" "}
105
<A href="/vouchers">vouchers center</A>.
106
<ul>
107
<li style={{ marginBottom: "15px" }}>
108
If you're interested in{" "}
109
<A href="/store/vouchers">purchasing</A>,{" "}
110
<A href="/redeem">redeeming</A>, or checking on the{" "}
111
<A href="/vouchers/created">status of your vouchers</A>, visit
112
the <A href="/vouchers">Voucher Center</A> or the{" "}
113
<A href="https://doc.cocalc.com/vouchers.html">
114
voucher docs
115
</A>
116
.
117
</li>
118
</ul>
119
</li>
120
)}
121
{purchases.result.length > 0 ? (
122
<li style={{ marginBottom: "15px" }}>
123
<b>Payments:</b> You can{" "}
124
<A href="/settings/purchases">download your receipt</A> and{" "}
125
<A href="/settings/subscriptions">
126
check on the status of any subscriptions.
127
</A>
128
</li>
129
) : (
130
<li style={{ marginBottom: "15px" }}>
131
<b>Payments:</b> You can{" "}
132
<A href="/settings/purchases">download your receipt</A>.
133
</li>
134
)}
135
<li>
136
<b>Support:</b> If you have questions,{" "}
137
<A href="/support/new">create a support ticket</A>.
138
</li>
139
</ul>
140
{billingInfo}
141
</>
142
);
143
}
144
145
function renderAutomaticallyApplied(): JSX.Element {
146
const appliedProjects = purchases.result.filter(
147
(x) => x.project_id != null,
148
);
149
const numApplied = appliedProjects.length;
150
if (numApplied == 0) return <></>;
151
return (
152
<>
153
<br />
154
<Alert
155
type="info"
156
message={
157
<>
158
<p>
159
The following {plural(numApplied, "project")} automatically got
160
a license applied:
161
</p>
162
<ul>
163
{appliedProjects.map((x) => (
164
<li key={x.project_id}>
165
Project{" "}
166
<A href={`/projects/${x.project_id}`} external={true}>
167
{x.project_id}
168
</A>{" "}
169
got license <License license_id={x.purchased?.license_id} />
170
.
171
</li>
172
))}
173
</ul>
174
</>
175
}
176
></Alert>
177
</>
178
);
179
}
180
181
const licenses = purchases.result.filter((x) => x.purchased.license_id);
182
183
return (
184
<>
185
<div style={{ float: "right" }}>
186
<Image src={bella} width={100} height={141} alt="Picture of Bella!" />
187
</div>
188
<div style={{ fontSize: "12pt" }}>
189
<h1 style={{ fontSize: "24pt" }}>
190
<Icon
191
name="check-circle"
192
style={{ color: "darkgreen", marginRight: "10px" }}
193
/>{" "}
194
Order Complete!
195
</h1>
196
{licenses.length > 0 && (
197
<Card
198
style={{ margin: "15px auto", maxWidth: "700px" }}
199
title={
200
<>
201
<Icon name="key" style={{ marginRight: "15px" }} />
202
Congrats! You recently ordered{" "}
203
{licenses.length >= 2 ? "these" : "this"} {licenses.length}{" "}
204
<SiteName /> {plural(licenses.length, "license")}.
205
</>
206
}
207
>
208
<ul>
209
{licenses.map((item) => (
210
<li key={item.purchased.license_id}>
211
<License
212
key={item.purchased.license_id}
213
license_id={item.purchased.license_id}
214
/>
215
, purchased <TimeAgo datetime={item.purchased.time} />
216
</li>
217
))}
218
</ul>
219
{renderAutomaticallyApplied()}
220
</Card>
221
)}
222
{vouchers.result.length > 0 && (
223
<Card
224
title={
225
<>
226
<Icon name="gift2" style={{ marginRight: "15px" }} />
227
Congrats! You recently created {vouchers.result.length}{" "}
228
{plural(vouchers.result.length, "voucher")}.
229
</>
230
}
231
style={{ margin: "15px auto", maxWidth: "700px" }}
232
>
233
You can download and track your voucher codes via the{" "}
234
{plural(vouchers.result.length, "link")} below.
235
<br />
236
<br />
237
<ul>
238
{vouchers.result.map((item, n) => (
239
<Voucher key={n} {...item} />
240
))}
241
</ul>
242
</Card>
243
)}
244
<br />
245
{renderNextSteps()}
246
</div>
247
</>
248
);
249
}
250
251
function Voucher({ id, title, count, created }) {
252
return (
253
<li key={id}>
254
<A href={`/vouchers/${id}`}>
255
{title}: {count} voucher codes
256
</A>
257
, created <TimeAgo datetime={created} />
258
</li>
259
);
260
}
261
262