Skip to content

Commit cf559c1

Browse files
committed
wip2
1 parent 13db002 commit cf559c1

File tree

2 files changed

+77
-26
lines changed

2 files changed

+77
-26
lines changed

components/dashboard/src/AppNotifications.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,7 @@ function convertToAppNotification(array: string[] | AppNotification[] | any): Ap
119119
}
120120
return notifications;
121121
}
122+
123+
export const resetAllNotifications = () => {
124+
removeLocalStorageObject(KEY_APP_NOTIFICATIONS);
125+
};

components/dashboard/src/SwitchToPAYG.tsx

Lines changed: 73 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ import Alert from "./components/Alert";
1616
import { useLocalStorage } from "./hooks/use-local-storage";
1717
import { Subscription } from "@gitpod/gitpod-protocol/lib/accounting-protocol";
1818
import { TeamSubscription, TeamSubscription2 } from "@gitpod/gitpod-protocol/lib/team-subscription-protocol";
19+
import { useConfetti } from "./contexts/ConfettiContext";
20+
import { resetAllNotifications } from "./AppNotifications";
21+
import { Plans } from "@gitpod/gitpod-protocol/lib/plans";
1922

2023
/**
2124
* Keys of known page params
@@ -37,7 +40,11 @@ type PageParams = {
3740
type PageState = {
3841
phase: "call-to-action" | "trigger-signup" | "wait-for-signup" | "cleanup" | "done";
3942
attributionId?: string;
40-
oldSubscriptionId?: string;
43+
old?: {
44+
planName: string;
45+
planDetails: string;
46+
subscriptionId: string;
47+
};
4148
};
4249

4350
function SwitchToPAYG() {
@@ -52,9 +59,11 @@ function SwitchToPAYG() {
5259
const [errorMessage, setErrorMessage] = useState<string | undefined>();
5360
const [showBillingSetupModal, setShowBillingSetupModal] = useState<boolean>(false);
5461
const [pendingStripeSubscription, setPendingStripeSubscription] = useState<boolean>(false);
62+
const [droppedConfetti, setDroppedConfetti] = useState<boolean>(false);
63+
const { dropConfetti } = useConfetti();
5564

5665
useEffect(() => {
57-
const { phase, attributionId, oldSubscriptionId } = pageState;
66+
const { phase, attributionId, old } = pageState;
5867
const { setupIntentId, type, oldSubscriptionOrTeamId } = pageParams || {};
5968

6069
if (!type) {
@@ -74,10 +83,10 @@ function SwitchToPAYG() {
7483
(async () => {
7584
// Old Subscription still active?
7685
let derivedAttributionId: string | undefined = undefined;
77-
let oldSubscriptionId: string;
86+
let old: PageState["old"];
7887
switch (type) {
7988
case "personalSubscription": {
80-
oldSubscriptionId = oldSubscriptionOrTeamId;
89+
const oldSubscriptionId = oldSubscriptionOrTeamId;
8190
const statement = await getGitpodService().server.getAccountStatement({});
8291
if (!statement) {
8392
console.error("No AccountStatement!");
@@ -96,12 +105,17 @@ function SwitchToPAYG() {
96105
}
97106
return;
98107
}
108+
old = {
109+
subscriptionId: sub.uid,
110+
planName: Plans.getById(sub.planId!)!.name,
111+
planDetails: "personal",
112+
};
99113
derivedAttributionId = AttributionId.render({ kind: "user", userId: sub.userId });
100114
break;
101115
}
102116

103117
case "teamSubscription": {
104-
oldSubscriptionId = oldSubscriptionOrTeamId;
118+
const oldSubscriptionId = oldSubscriptionOrTeamId;
105119
const tss = await getGitpodService().server.tsGet();
106120
const ts = tss.find((s) => s.id === oldSubscriptionId);
107121
if (!ts) {
@@ -116,6 +130,11 @@ function SwitchToPAYG() {
116130
}
117131
return;
118132
}
133+
old = {
134+
subscriptionId: ts.id,
135+
planName: Plans.getById(ts.planId!)!.name,
136+
planDetails: `${ts.quantity} Members`,
137+
};
119138
// no derivedAttributionId: user has to select/create new org
120139
break;
121140
}
@@ -127,7 +146,6 @@ function SwitchToPAYG() {
127146
console.error(`No TeamSubscription2 for team ${teamId}!`);
128147
break;
129148
}
130-
oldSubscriptionId = ts2.id;
131149
const now = new Date().toISOString();
132150
if (TeamSubscription2.isCancelled(ts2, now) || !TeamSubscription2.isActive(ts2, now)) {
133151
// We're happy!
@@ -136,14 +154,19 @@ function SwitchToPAYG() {
136154
}
137155
return;
138156
}
157+
old = {
158+
subscriptionId: ts2.id,
159+
planName: Plans.getById(ts2.planId!)!.name,
160+
planDetails: `${ts2.quantity} Members`,
161+
};
139162
derivedAttributionId = AttributionId.render({ kind: "team", teamId });
140163
break;
141164
}
142165
}
143-
if (!cancelled) {
166+
if (!cancelled && !attributionId) {
144167
setPageState((s) => {
145168
const attributionId = s.attributionId || derivedAttributionId;
146-
return { ...s, attributionId, oldSubscriptionId };
169+
return { ...s, attributionId, old };
147170
});
148171
}
149172
})().catch(console.error);
@@ -248,8 +271,9 @@ function SwitchToPAYG() {
248271
}
249272

250273
case "cleanup": {
274+
const oldSubscriptionId = old?.subscriptionId;
251275
if (!oldSubscriptionId) {
252-
setErrorMessage("Error during params parsing: oldSubscriptionOrTeamId not set!");
276+
setErrorMessage("Error during cleanup: old.oldSubscriptionId not set!");
253277
return;
254278
}
255279
switch (type) {
@@ -291,10 +315,15 @@ function SwitchToPAYG() {
291315
}
292316

293317
case "done":
294-
// Render hooray and confetti!
318+
// Hooray and confetti!
319+
resetAllNotifications();
320+
if (!droppedConfetti) {
321+
setDroppedConfetti(true);
322+
dropConfetti();
323+
}
295324
return;
296325
}
297-
}, [location.search, pageParams, pageState, setPageState]);
326+
}, [location.search, pageParams, pageState, setPageState, dropConfetti, droppedConfetti]);
298327

299328
const onUpgradePlan = useCallback(async () => {
300329
if (pageState.phase !== "call-to-action" || !pageState.attributionId) {
@@ -334,8 +363,11 @@ function SwitchToPAYG() {
334363
} else if (pageParams?.type === "teamSubscription2") {
335364
titleModifier = "organization's plan";
336365
}
366+
367+
const planName = pageState.old?.planName || "Legacy Plan";
368+
const planDescription = pageState.old?.planDetails || "";
337369
return (
338-
<div className="flex flex-col max-h-screen max-w-2xl mx-auto items-center w-full mt-32">
370+
<div className="flex flex-col max-h-screen max-w-3xl mx-auto items-center w-full mt-32">
339371
<h1>{`Update your ${titleModifier}`}</h1>
340372
<div className="w-full text-gray-500 text-center">
341373
Switch to the new pricing model to keep uninterrupted access and get <strong>large workspaces</strong>{" "}
@@ -347,24 +379,39 @@ function SwitchToPAYG() {
347379
Learn more →
348380
</a>
349381
</div>
350-
<div className="w-96 mt-6 text-sm">
351-
<div className="w-full h-h96 rounded-xl text-center text-gray-500 bg-gray-50 dark:bg-gray-800"></div>
352-
<div className="mt-6 w-full text-center">
353-
{renderCard({
354-
headline: "LEGACY SUBSCRIPTION",
355-
title: "Team Professional",
356-
description: "29 Members",
357-
selected: false,
358-
action: <>Discontinued</>,
359-
additionalStyles: "w-80",
360-
})}
361-
</div>
382+
<div className="mt-6 space-x-3 flex">
383+
{renderCard({
384+
headline: "LEGACY PLAN",
385+
title: planName,
386+
description: planDescription,
387+
selected: false,
388+
action: (
389+
<Alert type="error">
390+
Discontinued on <strong>March 31st</strong>
391+
</Alert>
392+
),
393+
additionalStyles: "",
394+
})}
395+
{renderCard({
396+
headline: "NEW PLAN",
397+
title: "$9 / month (1,000 credits)",
398+
description: "Pay-as-you-go after that for $0.036 per credit.",
399+
selected: true,
400+
action: (
401+
<a className="gp-link" href="https://www.gitpod.io/pricing#cost-estimator">
402+
Estimate costs
403+
</a>
404+
),
405+
additionalStyles: "",
406+
})}
407+
</div>
408+
<div className="w-full mt-6 grid justify-items-center">
362409
{pendingStripeSubscription && (
363410
<div className="w-full mt-6 text-center">
364411
<SpinnerLoader small={false} content="Creating subscription with Stripe" />
365412
</div>
366413
)}
367-
<div className="w-full mt-10 text-center">
414+
<div className="w-96 mt-10 text-center">
368415
<button
369416
className="w-full"
370417
onClick={onUpgradePlan}
@@ -435,7 +482,7 @@ function renderCard(props: {
435482
>
436483
{props.description}
437484
</div>
438-
<div className="text-xl my-1 flex-row flex align-middle">
485+
<div className="text-xl my-1 flex-row flex align-middle items-end">
439486
<div
440487
className={`text-sm font-normal truncate w-full ${
441488
props.selected ? "text-gray-300 dark:text-gray-500" : "text-gray-500 dark:text-gray-400"

0 commit comments

Comments
 (0)