Skip to content

Commit 0d002fd

Browse files
committed
[dashboard] Implement a pendingDowngradeCancellation in order to show visual feedback faster
1 parent 94a2909 commit 0d002fd

File tree

1 file changed

+41
-7
lines changed

1 file changed

+41
-7
lines changed

components/dashboard/src/settings/Plans.tsx

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ import { PageWithSubMenu } from "../components/PageWithSubMenu";
2020
import settingsMenu from "./settings-menu";
2121

2222
type PlanWithOriginalPrice = Plan & { originalPrice?: number };
23-
type PendingPlan = PlanWithOriginalPrice & { pendingSince: number };
23+
type Pending = { pendingSince: number };
24+
type PendingPlan = PlanWithOriginalPrice & Pending;
2425

2526
type TeamClaimModal = {
2627
errorText: string;
@@ -183,11 +184,38 @@ export default function () {
183184
}
184185
}
185186

187+
const [ pendingDowngradeCancellation, setPendingDowngradeCancellation ] = useState<Pending | undefined>(getLocalStorageObject('pendingDowngradeCancellation'));
188+
const setPendingCancelDowngrade = (cancellation: Pending) => {
189+
clearTimeout(pollAccountStatementTimeout!);
190+
setLocalStorageObject('pendingDowngradeCancellation', cancellation);
191+
setPendingDowngradeCancellation(cancellation);
192+
};
193+
const removePendingCancelDowngrade = () => {
194+
clearTimeout(pollAccountStatementTimeout!);
195+
removeLocalStorageObject('pendingDowngradeCancellation');
196+
setPendingDowngradeCancellation(undefined);
197+
}
198+
if (!!pendingDowngradeCancellation) {
199+
if (!scheduledDowngradePlanId) {
200+
// The downgrade cancellation worked
201+
removePendingCancelDowngrade();
202+
} else if ((pendingDowngradeCancellation.pendingSince + 1000 * 60 * 5) < Date.now()) {
203+
// Pending downgrade cancellations expire after 5 minutes
204+
removePendingCancelDowngrade();
205+
} else if (!pollAccountStatementTimeout) {
206+
// Refresh account statement in 10 seconds in orer to poll for downgrade cancelled
207+
pollAccountStatementTimeout = setTimeout(async () => {
208+
const statement = await server.getAccountStatement({});
209+
setAccountStatement(statement);
210+
}, 10000);
211+
}
212+
}
213+
186214
const [ confirmUpgradeToPlan, setConfirmUpgradeToPlan ] = useState<Plan>();
187215
const [ confirmDowngradeToPlan, setConfirmDowngradeToPlan ] = useState<Plan>();
188216
const [ isConfirmCancelDowngrade, setIsConfirmCancelDowngrade ] = useState<boolean>(false);
189217
const confirmUpgrade = (to: Plan) => {
190-
if (pendingUpgradePlan || pendingDowngradePlan) {
218+
if (pendingUpgradePlan || pendingDowngradePlan || pendingDowngradeCancellation) {
191219
// Don't upgrade if we're still waiting for a Chargebee callback
192220
return;
193221
}
@@ -229,7 +257,7 @@ export default function () {
229257
}
230258
}
231259
const confirmDowngrade = (to: Plan) => {
232-
if (pendingUpgradePlan || pendingDowngradePlan) {
260+
if (pendingUpgradePlan || pendingDowngradePlan || pendingDowngradeCancellation) {
233261
// Don't downgrade if we're still waiting for a Chargebee callback
234262
return;
235263
}
@@ -269,6 +297,10 @@ export default function () {
269297
}
270298
}
271299
const confirmCancelDowngrade = () => {
300+
if (pendingUpgradePlan || pendingDowngradePlan || pendingDowngradeCancellation) {
301+
// Don't cancel downgrade if we're still waiting for a Chargebee callback
302+
return;
303+
}
272304
if (!scheduledDowngradePlanId) {
273305
// No scheduled downgrade to be cancelled?
274306
return;
@@ -284,7 +316,9 @@ export default function () {
284316
}
285317
try {
286318
await server.subscriptionCancelDowngrade(paidSubscription.uid);
287-
// TODO: Update state somehow?
319+
setPendingCancelDowngrade({
320+
pendingSince: Date.now(),
321+
})
288322
} catch (error) {
289323
console.error('Cancel Downgrade Error', error);
290324
} finally {
@@ -305,7 +339,7 @@ export default function () {
305339
} else {
306340
const targetPlan = freePlan;
307341
let bottomLabel;
308-
if (scheduledDowngradePlanId === targetPlan.chargebeeId) {
342+
if (scheduledDowngradePlanId === targetPlan.chargebeeId && !pendingDowngradeCancellation) {
309343
bottomLabel = <p className="text-green-600">Downgrade scheduled<br/><a className="text-blue-light leading-6" href="javascript:void(0)" onClick={() => confirmCancelDowngrade()}>Cancel</a></p>;
310344
} else if (pendingDowngradePlan?.chargebeeId === targetPlan.chargebeeId) {
311345
bottomLabel = <p className="text-green-600 animate-pulse">Downgrade scheduled</p>;
@@ -328,7 +362,7 @@ export default function () {
328362
} else {
329363
const targetPlan = applyCoupons(personalPlan, availableCoupons);
330364
let bottomLabel;
331-
if (scheduledDowngradePlanId === targetPlan.chargebeeId) {
365+
if (scheduledDowngradePlanId === targetPlan.chargebeeId && !pendingDowngradeCancellation) {
332366
bottomLabel = <p className="text-green-600">Downgrade scheduled<br/><a className="text-blue-light leading-6" href="javascript:void(0)" onClick={() => confirmCancelDowngrade()}>Cancel</a></p>;
333367
} else if (pendingDowngradePlan?.chargebeeId === targetPlan.chargebeeId) {
334368
bottomLabel = <p className="text-green-600">Downgrade scheduled</p>;
@@ -354,7 +388,7 @@ export default function () {
354388
} else {
355389
const targetPlan = applyCoupons(professionalPlan, availableCoupons);
356390
let bottomLabel;
357-
if (scheduledDowngradePlanId === targetPlan.chargebeeId) {
391+
if (scheduledDowngradePlanId === targetPlan.chargebeeId && !pendingDowngradeCancellation) {
358392
bottomLabel = <p className="text-green-600">Downgrade scheduled<br/><a className="text-blue-light leading-6" href="javascript:void(0)" onClick={() => confirmCancelDowngrade()}>Cancel</a></p>;
359393
} else if (pendingDowngradePlan?.chargebeeId === targetPlan.chargebeeId) {
360394
bottomLabel = <p className="text-green-600">Downgrade scheduled</p>;

0 commit comments

Comments
 (0)