Openstatus www.openstatus.dev
at main 103 lines 3.3 kB view raw
1import { Link } from "@/components/common/link"; 2import { Note, NoteButton } from "@/components/common/note"; 3import { BillingAddons } from "@/components/content/billing-addons"; 4import { DataTable } from "@/components/data-table/billing/data-table"; 5import { 6 Dialog, 7 DialogContent, 8 DialogDescription, 9 DialogHeader, 10 DialogTitle, 11} from "@/components/ui/dialog"; 12import { Separator } from "@/components/ui/separator"; 13import { useTRPC } from "@/lib/trpc/client"; 14import type { WorkspacePlan } from "@openstatus/db/src/schema"; 15import { allPlans } from "@openstatus/db/src/schema/plan/config"; 16import type { Addons, Limits } from "@openstatus/db/src/schema/plan/schema"; 17import { getPlansForLimit } from "@openstatus/db/src/schema/plan/utils"; 18import type { DialogProps } from "@radix-ui/react-dialog"; 19import { useQuery } from "@tanstack/react-query"; 20import { CalendarClock } from "lucide-react"; 21 22const PLANS = { 23 free: ["starter", "team"], 24 starter: ["team"], 25 team: [], 26} satisfies Record<WorkspacePlan, WorkspacePlan[]>; 27 28export function UpgradeDialog( 29 props: DialogProps & { 30 limit?: keyof Limits; 31 restrictTo?: WorkspacePlan[]; 32 }, 33) { 34 const trpc = useTRPC(); 35 const { data: workspace } = useQuery(trpc.workspace.get.queryOptions()); 36 37 if (!workspace) return null; 38 39 const planAddons = allPlans[workspace.plan].addons; 40 41 const getRestrictTo = () => { 42 if (props.restrictTo) return props.restrictTo; 43 if (props.limit) return getPlansForLimit(workspace.plan, props.limit); 44 return PLANS[workspace.plan]; 45 }; 46 47 const restrictTo = getRestrictTo(); 48 49 const addon = 50 props.limit && Object.prototype.hasOwnProperty.call(planAddons, props.limit) 51 ? (props.limit as keyof Addons) 52 : null; 53 54 return ( 55 <Dialog {...props}> 56 <DialogContent className="max-h-[80vh] overflow-y-auto sm:max-w-2xl"> 57 <DialogHeader> 58 <DialogTitle>Upgrade Workspace</DialogTitle> 59 <DialogDescription> 60 Upgrade your workspace to support more monitors, status pages, 61 regions, and much more. Get an overview within your{" "} 62 <Link 63 onClick={() => props.onOpenChange?.(false)} 64 href="/settings/billing" 65 > 66 billing settings 67 </Link> 68 . 69 </DialogDescription> 70 </DialogHeader> 71 {addon && planAddons[addon] ? ( 72 <> 73 <BillingAddons 74 label={planAddons[addon].title} 75 description={planAddons[addon].description} 76 addon={addon} 77 workspace={workspace} 78 /> 79 <Separator /> 80 </> 81 ) : null} 82 {restrictTo.length === 0 ? ( 83 <Note> 84 <CalendarClock /> 85 Please contact us to upgrade your plan. 86 <NoteButton variant="outline" asChild> 87 <a 88 href="https://openstatus.dev/cal" 89 target="_blank" 90 rel="noreferrer" 91 className="text-nowrap" 92 > 93 Book a call 94 </a> 95 </NoteButton> 96 </Note> 97 ) : ( 98 <DataTable restrictTo={restrictTo} /> 99 )} 100 </DialogContent> 101 </Dialog> 102 ); 103}