Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getAuthenticatedClient } from "@features/auth/hooks/authClient";
import { useSwitchOrgMutation } from "@features/auth/hooks/authMutations";
import { useAuthStateValue } from "@features/auth/hooks/authQueries";
import { TokenSpendAnalysisBanner } from "@features/billing/components/TokenSpendAnalysisBanner";
import { useUsage } from "@features/billing/hooks/useUsage";
Expand Down Expand Up @@ -32,21 +32,6 @@ const log = logger.scope("plan-usage");

const SPEND_ANALYSIS_FLAG = "posthog-code-spend-analysis";

async function openBillingPage(orgId: string | null): Promise<void> {
if (orgId) {
try {
const client = await getAuthenticatedClient();
if (client) {
await client.switchOrganization(orgId);
}
} catch (err) {
log.warn("Failed to switch org before opening billing", err);
}
}
const url = getBillingUrl();
if (url) window.open(url, "_blank");
}

function formatResetTime(seconds: number): string {
if (seconds < 3600) return "less than 1 hour";
if (seconds < 86400) {
Expand Down Expand Up @@ -74,7 +59,38 @@ export function PlanUsageSettings() {
const { fetchSeat, upgradeToPro, cancelSeat, reactivateSeat, clearError } =
useSeatStore();
const cloudRegion = useAuthStateValue((state) => state.cloudRegion);
const currentOrgId = useAuthStateValue((state) => state.currentOrgId);
const switchOrgMutation = useSwitchOrgMutation();
const billingUrl = getBillingUrl(cloudRegion);

const [billingSwitch, setBillingSwitch] = useState<{
pending: boolean;
error: boolean;
}>({ pending: false, error: false });

async function openBillingPage(orgId: string | null): Promise<void> {
if (orgId && orgId !== currentOrgId) {
try {
await switchOrgMutation.mutateAsync(orgId);
} catch (err) {
log.warn("Failed to switch org before opening billing", err);
return;
}
}
if (billingUrl) window.open(billingUrl, "_blank");
}

async function switchToBillingOrg(orgId: string): Promise<void> {
Comment thread
charlesvien marked this conversation as resolved.
setBillingSwitch({ pending: true, error: false });
try {
await switchOrgMutation.mutateAsync(orgId);
await fetchSeat({ autoProvision: true });
setBillingSwitch({ pending: false, error: false });
} catch (err) {
log.warn("Failed to switch to billing org", err);
setBillingSwitch({ pending: false, error: true });
}
}
const redirectFullUrl = redirectUrl
? (getPostHogUrl(redirectUrl, cloudRegion) ?? billingUrl)
: null;
Expand Down Expand Up @@ -178,10 +194,37 @@ export function PlanUsageSettings() {
<Callout.Icon>
<Info size={16} />
</Callout.Icon>
<Callout.Text className="text-sm">
You have a Pro plan on{" "}
<Text weight="medium">{seat.organization_name}</Text>. Usage on this
page reflects your current organization.
<Callout.Text>
<Flex direction="column" gap="2">
<Text className="text-sm">
You have a Pro plan on{" "}
<Text weight="medium">{seat.organization_name}</Text>. Usage on
this page reflects your current organization.
</Text>
{billingOrgId && (
<Flex direction="column" gap="1" className="self-start">
<Button
size="1"
variant="outline"
disabled={billingSwitch.pending}
onClick={() => {
void switchToBillingOrg(billingOrgId);
}}
>
{billingSwitch.pending ? (
<Spinner size="1" />
) : (
`Switch to ${seat.organization_name ?? "Pro org"}`
)}
</Button>
{billingSwitch.error && (
<Text className="text-(--red-11) text-[12px]">
Switching failed. Try again or switch from the sidebar.
</Text>
)}
</Flex>
)}
</Flex>
</Callout.Text>
</Callout.Root>
)}
Expand Down
Loading