Skip to content

Commit c58f6f7

Browse files
authored
Upgrading from Hobby to Pro displays a dialog to confirm (#1545)
* Upgrading from Hobby to Pro displays a dialog to confirm * Improved the logic for upgrading to pro * Added the spinner component to storybook * Improved the dark style spinner
1 parent 6516e15 commit c58f6f7

File tree

4 files changed

+101
-24
lines changed

4 files changed

+101
-24
lines changed

apps/webapp/app/components/primitives/Spinner.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ export function Spinner({
2626
foreground: "#3C4B62",
2727
},
2828
dark: {
29-
background: "#15171A",
30-
foreground: "#272A2E",
29+
background: "rgba(18, 19, 23, 0.35)",
30+
foreground: "#1A1B1F",
3131
},
3232
};
3333

apps/webapp/app/routes/resources.orgs.$organizationSlug.select-plan.tsx

Lines changed: 67 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
ShieldCheckIcon,
66
XMarkIcon,
77
} from "@heroicons/react/20/solid";
8-
import { ArrowDownCircleIcon } from "@heroicons/react/24/outline";
8+
import { ArrowDownCircleIcon, ArrowUpCircleIcon } from "@heroicons/react/24/outline";
99
import { Form, useLocation, useNavigation } from "@remix-run/react";
1010
import { ActionFunctionArgs } from "@remix-run/server-runtime";
1111
import { uiComponent } from "@team-plain/typescript-sdk";
@@ -633,6 +633,11 @@ export function TierPro({
633633
const navigation = useNavigation();
634634
const formAction = `/resources/orgs/${organizationSlug}/select-plan`;
635635
const isLoading = navigation.formAction === formAction;
636+
const [isDialogOpen, setIsDialogOpen] = useState(false);
637+
638+
useEffect(() => {
639+
setIsDialogOpen(false);
640+
}, [subscription]);
636641

637642
return (
638643
<TierContainer>
@@ -645,27 +650,67 @@ export function TierPro({
645650
<input type="hidden" name="type" value="paid" />
646651
<input type="hidden" name="planCode" value={plan.code} />
647652
<input type="hidden" name="callerPath" value={location.pathname} />
648-
<Button
649-
variant="tertiary/large"
650-
fullWidth
651-
form="subscribe-pro"
652-
className="text-md font-medium"
653-
disabled={
654-
isLoading ||
655-
(subscription?.plan?.code === plan.code && subscription.canceledAt === undefined)
656-
}
657-
LeadingIcon={
658-
isLoading && navigation.formData?.get("planCode") === plan.code ? Spinner : undefined
659-
}
660-
>
661-
{subscription?.plan === undefined
662-
? "Select plan"
663-
: subscription.plan.type === "free" || subscription.canceledAt !== undefined
664-
? `Upgrade to ${plan.title}`
665-
: subscription.plan.code === plan.code
666-
? "Current plan"
667-
: `Upgrade to ${plan.title}`}
668-
</Button>
653+
{subscription?.plan !== undefined &&
654+
subscription?.plan?.type === "paid" &&
655+
subscription?.plan?.code !== plan.code &&
656+
subscription.canceledAt === undefined ? (
657+
<Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen} key="upgrade">
658+
<DialogTrigger asChild>
659+
<Button variant="tertiary/large" fullWidth className="text-md font-medium">
660+
{`Upgrade to ${plan.title}`}
661+
</Button>
662+
</DialogTrigger>
663+
<DialogContent className="sm:max-w-md">
664+
<DialogHeader>Upgrade plan?</DialogHeader>
665+
<div className="mb-2 mt-4 flex items-start gap-3">
666+
<span>
667+
<ArrowUpCircleIcon className="size-12 text-primary" />
668+
</span>
669+
<Paragraph variant="base/bright" className="text-text-bright">
670+
Are you sure you want to upgrade to the Pro plan? You will be charged the new
671+
plan price for the remainder of this month on a pro rata basis.
672+
</Paragraph>
673+
</div>
674+
<DialogFooter>
675+
<Button variant="tertiary/medium" onClick={() => setIsDialogOpen(false)}>
676+
Cancel
677+
</Button>
678+
<Button
679+
variant="primary/medium"
680+
disabled={isLoading}
681+
LeadingIcon={isLoading ? () => <Spinner color="dark" /> : undefined}
682+
form="subscribe-pro"
683+
>
684+
{`Upgrade to ${plan.title}`}
685+
</Button>
686+
</DialogFooter>
687+
</DialogContent>
688+
</Dialog>
689+
) : (
690+
<Button
691+
variant="tertiary/large"
692+
fullWidth
693+
form="subscribe-pro"
694+
className="text-md font-medium"
695+
disabled={
696+
isLoading ||
697+
(subscription?.plan?.code === plan.code && subscription.canceledAt === undefined)
698+
}
699+
LeadingIcon={
700+
isLoading && navigation.formData?.get("planCode") === plan.code
701+
? Spinner
702+
: undefined
703+
}
704+
>
705+
{subscription?.plan === undefined
706+
? "Select plan"
707+
: subscription.plan.type === "free" || subscription.canceledAt !== undefined
708+
? `Upgrade to ${plan.title}`
709+
: subscription.plan.code === plan.code
710+
? "Current plan"
711+
: `Upgrade to ${plan.title}`}
712+
</Button>
713+
)}
669714
</div>
670715
</Form>
671716
<ul className="flex flex-col gap-2.5">
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Spinner } from "~/components/primitives/Spinner";
2+
3+
export default function Story() {
4+
return (
5+
<div className="flex flex-col items-start gap-y-3 p-4">
6+
<div className="flex items-center gap-x-4 rounded-md bg-charcoal-750 px-3 py-2 text-text-bright">
7+
Blue: <Spinner color="blue" />
8+
</div>
9+
<div className="flex items-center gap-x-4 rounded-md bg-charcoal-750 px-3 py-2 text-text-bright">
10+
White: <Spinner color="white" />
11+
</div>
12+
<div className="flex items-center gap-x-4 rounded-md bg-charcoal-600 px-3 py-2 text-text-bright">
13+
Muted: <Spinner color="muted" />
14+
</div>
15+
<div className="flex items-center gap-x-2">
16+
<div className="flex items-center gap-x-4 rounded-md bg-charcoal-600 px-3 py-2 text-text-bright">
17+
Dark: <Spinner color="dark" />
18+
</div>
19+
<div className="flex items-center gap-x-4 rounded-md bg-primary px-2 py-2 text-text-bright">
20+
<Spinner color="dark" />
21+
</div>
22+
</div>
23+
<div className="flex items-center gap-x-4 rounded-md bg-charcoal-600 px-3 py-2 text-text-bright">
24+
Custom: <Spinner color={{ background: "#EA189E", foreground: "#6532F5" }} />
25+
</div>
26+
</div>
27+
);
28+
}

apps/webapp/app/routes/storybook/route.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ const stories: Story[] = [
8484
name: "Shortcuts",
8585
slug: "shortcuts",
8686
},
87+
{
88+
name: "Spinners",
89+
slug: "spinner",
90+
},
8791
{
8892
name: "Switch",
8993
slug: "switch",

0 commit comments

Comments
 (0)