diff --git a/vite/src/hooks/common/useOrg.tsx b/vite/src/hooks/common/useOrg.tsx
index 131fb2147..4b516cbbd 100644
--- a/vite/src/hooks/common/useOrg.tsx
+++ b/vite/src/hooks/common/useOrg.tsx
@@ -4,23 +4,12 @@ import { useEffect } from "react";
import { authClient, useListOrganizations } from "@/lib/auth-client";
import { useAxiosInstance } from "@/services/useAxiosInstance";
-const ORG_STORAGE_KEY = "autumn_org";
-
let lastSwitchedOrgId: string | null = null;
export const setLastSwitchedOrgId = (id: string) => {
lastSwitchedOrgId = id;
};
export const getLastSwitchedOrgId = () => lastSwitchedOrgId;
-/** Clears all org-related localStorage cache entries. Call before reload on session changes (impersonation start/stop). */
-export const clearOrgCache = () => {
- for (const key of Object.keys(localStorage)) {
- if (key.startsWith(ORG_STORAGE_KEY)) {
- localStorage.removeItem(key);
- }
- }
-};
-
export const useOrg = (params?: { env?: AppEnv }) => {
const axiosInstance = useAxiosInstance({ env: params?.env });
const { data: orgList } = useListOrganizations();
@@ -28,32 +17,12 @@ export const useOrg = (params?: { env?: AppEnv }) => {
const fetcher = async () => {
try {
const { data } = await axiosInstance.get("/organization");
- if (data) {
- const storageKey = params?.env
- ? `${ORG_STORAGE_KEY}_${params.env}`
- : ORG_STORAGE_KEY;
- localStorage.setItem(storageKey, JSON.stringify(data));
- }
return data;
} catch {
return null;
}
};
- const getInitialData = () => {
- try {
- const storageKey = params?.env
- ? `${ORG_STORAGE_KEY}_${params.env}`
- : ORG_STORAGE_KEY;
- const stored = localStorage.getItem(storageKey);
- return stored ? JSON.parse(stored) : undefined;
- } catch {
- return undefined;
- }
- };
-
- const initialDataValue = getInitialData();
-
const {
data: org,
isLoading,
@@ -62,7 +31,6 @@ export const useOrg = (params?: { env?: AppEnv }) => {
} = useQuery({
queryKey: params?.env ? ["org", params.env] : ["org"],
queryFn: fetcher,
- initialData: initialDataValue,
placeholderData: keepPreviousData,
refetchOnWindowFocus: true,
staleTime: 30_000,
@@ -78,10 +46,10 @@ export const useOrg = (params?: { env?: AppEnv }) => {
} else {
console.log("No org to set active, signing out");
await authClient.signOut();
+ window.location.href = "/sign-in";
}
};
- // 1. If no org...
if (!org && !isLoading) {
handleNoActiveOrg();
}
diff --git a/vite/src/views/admin/AdminView.tsx b/vite/src/views/admin/AdminView.tsx
index 336f7a5d2..68b085cb7 100644
--- a/vite/src/views/admin/AdminView.tsx
+++ b/vite/src/views/admin/AdminView.tsx
@@ -2,7 +2,6 @@ import { Globe } from "@phosphor-icons/react";
import { useNavigate } from "react-router";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
-import { clearOrgCache } from "@/hooks/common/useOrg";
import { authClient } from "@/lib/auth-client";
import { AdminOrgTable } from "@/views/admin/AdminOrgTable";
import { AdminUserTable } from "@/views/admin/AdminUserTable";
@@ -35,7 +34,6 @@ export const AdminView = () => {
return;
}
- clearOrgCache();
window.location.reload();
};
diff --git a/vite/src/views/admin/ImpersonateRedirect.tsx b/vite/src/views/admin/ImpersonateRedirect.tsx
index 779eecd42..6a6b630fe 100644
--- a/vite/src/views/admin/ImpersonateRedirect.tsx
+++ b/vite/src/views/admin/ImpersonateRedirect.tsx
@@ -2,7 +2,6 @@ import { AlertCircle, Loader2, ShieldCheck } from "lucide-react";
import { useEffect, useState } from "react";
import { useNavigate, useSearchParams } from "react-router";
import { Button } from "@/components/v2/buttons/Button";
-import { clearOrgCache } from "@/hooks/common/useOrg";
import { authClient } from "@/lib/auth-client";
import { useAxiosInstance } from "../../services/useAxiosInstance";
import { useAdmin } from "./hooks/useAdmin";
@@ -65,9 +64,6 @@ export function ImpersonateRedirect() {
// Step 5: Navigate to the redirect path
setStatus("Redirecting...");
-
- // Clear stale org cache before navigating so the new session loads fresh data
- clearOrgCache();
window.location.href = redirect;
} catch (err: unknown) {
const errorMessage =
diff --git a/vite/src/views/admin/adminUtils.ts b/vite/src/views/admin/adminUtils.ts
index 102c54174..534de8030 100644
--- a/vite/src/views/admin/adminUtils.ts
+++ b/vite/src/views/admin/adminUtils.ts
@@ -10,7 +10,6 @@ import type {
Rollover,
} from "@autumn/shared";
import { toast } from "sonner";
-import { clearOrgCache } from "@/hooks/common/useOrg";
import { authClient } from "@/lib/auth-client";
import { formatUnixToDate } from "../../utils/formatUtils/formatDateUtils";
@@ -66,7 +65,6 @@ export const impersonateUser = async ({
await authClient.organization.setActive({ organizationId });
}
- clearOrgCache();
window.location.reload();
};
diff --git a/vite/src/views/auth/Consent.tsx b/vite/src/views/auth/Consent.tsx
index d3a839423..48996686e 100644
--- a/vite/src/views/auth/Consent.tsx
+++ b/vite/src/views/auth/Consent.tsx
@@ -1,5 +1,4 @@
import { type GroupedPermission, groupAndFormatScopes } from "@autumn/shared";
-import { clearOrgCache } from "@/hooks/common/useOrg";
import {
Check,
ChevronDown,
@@ -147,7 +146,6 @@ export const Consent = () => {
await authClient.organization.setActive({
organizationId: orgId,
});
- clearOrgCache();
window.location.reload();
} catch (_) {
toast.error("Failed to switch organization");
diff --git a/vite/src/views/customers2/components/sheets/AutoTopUpSection.tsx b/vite/src/views/customers2/components/sheets/AutoTopUpSection.tsx
deleted file mode 100644
index eb4731684..000000000
--- a/vite/src/views/customers2/components/sheets/AutoTopUpSection.tsx
+++ /dev/null
@@ -1,121 +0,0 @@
-import { PurchaseLimitInterval } from "@autumn/shared";
-import {
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger,
- SelectValue,
-} from "@/components/v2/selects/Select";
-import type { BalanceEditFormInstance } from "./useBalanceEditForm";
-
-const RATE_LIMIT_INTERVALS = [
- { value: PurchaseLimitInterval.Hour, label: "Hour" },
- { value: PurchaseLimitInterval.Day, label: "Day" },
- { value: PurchaseLimitInterval.Week, label: "Week" },
- { value: PurchaseLimitInterval.Month, label: "Month" },
-];
-
-export function AutoTopUpSection({ form }: { form: BalanceEditFormInstance }) {
- return (
-
-
- {(field) => (
-
- )}
-
-
-
- {(enabledField) =>
- enabledField.state.value && (
- <>
-
-
- {(field) => (
-
- )}
-
-
- {(field) => (
-
- )}
-
-
-
-
- {(field) => (
-
- )}
-
-
-
- {(maxField) =>
- maxField.state.value && (
-
-
- {(field) => (
-
-
- Interval
-
-
- Rate limit reset period
-
-
-
- )}
-
-
- {(field) => (
-
- )}
-
-
- )
- }
-
- >
- )
- }
-
-
- );
-}
diff --git a/vite/src/views/customers2/components/sheets/BalanceEditSheet.tsx b/vite/src/views/customers2/components/sheets/BalanceEditSheet.tsx
index d9f027239..3af988c3c 100644
--- a/vite/src/views/customers2/components/sheets/BalanceEditSheet.tsx
+++ b/vite/src/views/customers2/components/sheets/BalanceEditSheet.tsx
@@ -1,12 +1,9 @@
import {
- type AutoTopup,
computeGrantedBalanceInput,
type Entity,
type FullCusProduct,
type FullCustomerEntitlement,
type FullCustomerPrice,
- isOneOffPrice,
- isPrepaidPrice,
isUnlimitedCusEnt,
numberWithCommas,
} from "@autumn/shared";
@@ -23,14 +20,12 @@ import { LabelInput } from "@/components/v2/inputs/LabelInput";
import { SheetHeader, SheetSection } from "@/components/v2/sheets/InlineSheet";
import { useCustomerBalanceSheetStore } from "@/hooks/stores/useCustomerBalanceSheetStore";
import { useSheetStore } from "@/hooks/stores/useSheetStore";
-import { CusService } from "@/services/customers/CusService";
import { useAxiosInstance } from "@/services/useAxiosInstance";
import { formatUnixToDateTime } from "@/utils/formatUtils/formatDateUtils";
import { getBackendErr, notNullish } from "@/utils/genUtils";
import { useCusQuery } from "@/views/customers/customer/hooks/useCusQuery";
import { InfoBox } from "@/views/onboarding2/integrate/components/InfoBox";
import { useCustomerContext } from "../../customer/CustomerContext";
-import { AutoTopUpSection } from "./AutoTopUpSection";
import { BalanceEditPreviews } from "./BalanceEditPreviews";
import { GrantedBalancePopover } from "./GrantedBalancePopover";
import {
@@ -80,19 +75,6 @@ export function BalanceEditSheet() {
cp.price.entitlement_id === selectedCusEnt.entitlement.id,
);
- const hasOneOffPrepaidPrice = cusPrice
- ? isOneOffPrice(cusPrice.price) && isPrepaidPrice(cusPrice.price)
- : false;
- const hasExistingAutoTopUp = customer?.auto_topups?.some(
- (c: AutoTopup) => c.feature_id === featureId,
- );
- const isEligibleForAutoTopUp =
- hasOneOffPrepaidPrice || !!hasExistingAutoTopUp;
-
- const existingAutoTopUp =
- customer?.auto_topups?.find((c: AutoTopup) => c.feature_id === featureId) ??
- null;
-
return (
)}
@@ -161,8 +141,6 @@ function BalanceEditForm({
cusProduct,
cusPrice,
featureId,
- existingAutoTopUp,
- isEligibleForAutoTopUp,
}: {
selectedCusEnt: FullCustomerEntitlement;
entityId: string | null;
@@ -170,13 +148,10 @@ function BalanceEditForm({
cusProduct: FullCusProduct | undefined;
cusPrice: FullCustomerPrice | undefined;
featureId: string;
- existingAutoTopUp: AutoTopup | null;
- isEligibleForAutoTopUp: boolean;
}) {
const form = useBalanceEditForm({
selectedCusEnt,
entityId,
- existingAutoTopUp,
});
return (
@@ -190,7 +165,7 @@ function BalanceEditForm({
/>
-
+
- {isEligibleForAutoTopUp && (
-
-
-
- )}
-
c.feature_id !== featureId,
- );
-
- promises.push(
- CusService.updateCustomer({
- axios: axiosInstance,
- customer_id: customer.id || customer.internal_id,
- data: {
- billing_controls: {
- auto_topups: [...otherConfigs, newConfig],
- },
- },
- }),
- );
- }
-
await Promise.all(promises);
toast.success("Updated successfully");
handleClose();
@@ -630,20 +565,3 @@ function hasBalanceChanges({
);
}
-function hasAutoTopUpChanges({
- form,
-}: {
- form: BalanceEditFormInstance;
-}): boolean {
- const meta = form.state.fieldMeta;
-
- return (
- meta["autoTopUp.enabled"]?.isDirty ||
- meta["autoTopUp.threshold"]?.isDirty ||
- meta["autoTopUp.quantity"]?.isDirty ||
- meta["autoTopUp.maxPurchasesEnabled"]?.isDirty ||
- meta["autoTopUp.interval"]?.isDirty ||
- meta["autoTopUp.maxPurchases"]?.isDirty ||
- false
- );
-}
diff --git a/vite/src/views/customers2/components/sheets/balanceEditFormSchema.ts b/vite/src/views/customers2/components/sheets/balanceEditFormSchema.ts
index 8dc542a1b..046fe06b9 100644
--- a/vite/src/views/customers2/components/sheets/balanceEditFormSchema.ts
+++ b/vite/src/views/customers2/components/sheets/balanceEditFormSchema.ts
@@ -1,4 +1,3 @@
-import { PurchaseLimitInterval } from "@autumn/shared";
import { z } from "zod/v4";
export const BalanceEditFormSchema = z
@@ -8,17 +7,9 @@ export const BalanceEditFormSchema = z
grantedAndPurchasedBalance: z.number().nullable(),
nextResetAt: z.number().nullable(),
addValue: z.number().nullable(),
- autoTopUp: z.object({
- enabled: z.boolean(),
- threshold: z.number().min(0).nullable(),
- quantity: z.number().min(1).nullable(),
- maxPurchasesEnabled: z.boolean(),
- interval: z.enum(PurchaseLimitInterval),
- maxPurchases: z.number().min(1).nullable(),
- }),
})
.check((ctx) => {
- const { mode, balance, addValue, autoTopUp } = ctx.value;
+ const { mode, balance, addValue } = ctx.value;
if (mode === "set" && balance === null) {
ctx.issues.push({
@@ -37,35 +28,6 @@ export const BalanceEditFormSchema = z
input: addValue,
});
}
-
- if (autoTopUp.enabled) {
- if (autoTopUp.threshold === null || autoTopUp.threshold < 0) {
- ctx.issues.push({
- code: "custom",
- message: "Threshold must be 0 or above",
- path: ["autoTopUp", "threshold"],
- input: autoTopUp.threshold,
- });
- }
- if (autoTopUp.quantity === null || autoTopUp.quantity < 1) {
- ctx.issues.push({
- code: "custom",
- message: "Quantity must be 1 or above",
- path: ["autoTopUp", "quantity"],
- input: autoTopUp.quantity,
- });
- }
- if (autoTopUp.maxPurchasesEnabled) {
- if (autoTopUp.maxPurchases === null || autoTopUp.maxPurchases < 1) {
- ctx.issues.push({
- code: "custom",
- message: "Max purchases must be 1 or above",
- path: ["autoTopUp", "maxPurchases"],
- input: autoTopUp.maxPurchases,
- });
- }
- }
- }
});
export type BalanceEditForm = z.infer;
diff --git a/vite/src/views/customers2/components/sheets/useBalanceEditForm.ts b/vite/src/views/customers2/components/sheets/useBalanceEditForm.ts
index 1e2bf4cbd..133a83263 100644
--- a/vite/src/views/customers2/components/sheets/useBalanceEditForm.ts
+++ b/vite/src/views/customers2/components/sheets/useBalanceEditForm.ts
@@ -1,11 +1,9 @@
import {
- type AutoTopup,
cusEntsToBalance,
cusEntsToGrantedBalance,
cusEntsToPrepaidQuantity,
type FullCusEntWithFullCusProduct,
nullish,
- PurchaseLimitInterval,
} from "@autumn/shared";
import { useAppForm } from "@/hooks/form/form";
import {
@@ -16,11 +14,9 @@ import {
export function useBalanceEditForm({
selectedCusEnt,
entityId,
- existingAutoTopUp,
}: {
selectedCusEnt: FullCusEntWithFullCusProduct;
entityId: string | null;
- existingAutoTopUp: AutoTopup | null;
}) {
const prepaidAllowance = cusEntsToPrepaidQuantity({
cusEnts: [selectedCusEnt],
@@ -47,16 +43,6 @@ export function useBalanceEditForm({
grantedAndPurchasedBalance: grantedAndPurchasedBalance ?? null,
nextResetAt: selectedCusEnt.next_reset_at ?? null,
addValue: null,
- autoTopUp: {
- enabled: existingAutoTopUp?.enabled ?? false,
- threshold: existingAutoTopUp?.threshold ?? null,
- quantity: existingAutoTopUp?.quantity ?? null,
- maxPurchasesEnabled: !!existingAutoTopUp?.purchase_limit,
- interval:
- existingAutoTopUp?.purchase_limit?.interval ??
- PurchaseLimitInterval.Month,
- maxPurchases: existingAutoTopUp?.purchase_limit?.limit ?? null,
- },
} as BalanceEditForm,
validators: {
onChange: BalanceEditFormSchema,
diff --git a/vite/src/views/main-sidebar/components/AdminDropdownItems.tsx b/vite/src/views/main-sidebar/components/AdminDropdownItems.tsx
index c1a1170d5..fb1fe3638 100644
--- a/vite/src/views/main-sidebar/components/AdminDropdownItems.tsx
+++ b/vite/src/views/main-sidebar/components/AdminDropdownItems.tsx
@@ -5,7 +5,6 @@ import {
DropdownMenuItem,
DropdownMenuSeparator,
} from "@/components/ui/dropdown-menu";
-import { clearOrgCache } from "@/hooks/common/useOrg";
import { authClient, useSession } from "@/lib/auth-client";
import { getBackendErr, notNullish } from "@/utils/genUtils";
import { AdminOnly } from "@/views/admin/components/AdminOnly";
@@ -27,7 +26,6 @@ export const AdminDropdownItems = () => {
setStopImpersonatingLoading(true);
try {
await authClient.admin.stopImpersonating();
- clearOrgCache();
window.location.reload();
} catch (error) {
toast.error(getBackendErr(error, "Failed to stop impersonation"));
diff --git a/vite/src/views/main-sidebar/components/LogOutItem.tsx b/vite/src/views/main-sidebar/components/LogOutItem.tsx
index cc5513866..93d0da389 100644
--- a/vite/src/views/main-sidebar/components/LogOutItem.tsx
+++ b/vite/src/views/main-sidebar/components/LogOutItem.tsx
@@ -1,7 +1,6 @@
import { LogOut } from "lucide-react";
import React from "react";
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
-import { clearOrgCache } from "@/hooks/common/useOrg";
import { authClient } from "@/lib/auth-client";
export const LogOutItem = () => {
@@ -11,10 +10,10 @@ export const LogOutItem = () => {
onClick={async () => {
try {
await authClient.signOut();
- clearOrgCache();
- window.location.href = "/sign-in";
} catch (error) {
console.error("Error signing out:", error);
+ } finally {
+ window.location.href = "/sign-in";
}
}}
>
diff --git a/vite/src/views/main-sidebar/components/OrgDropdown.tsx b/vite/src/views/main-sidebar/components/OrgDropdown.tsx
index e680bfe8a..223627447 100644
--- a/vite/src/views/main-sidebar/components/OrgDropdown.tsx
+++ b/vite/src/views/main-sidebar/components/OrgDropdown.tsx
@@ -27,11 +27,7 @@ import {
} from "@/components/ui/dropdown-menu";
import { Skeleton } from "@/components/ui/skeleton";
import { useTheme } from "@/contexts/ThemeProvider";
-import {
- clearOrgCache,
- setLastSwitchedOrgId,
- useOrg,
-} from "@/hooks/common/useOrg";
+import { setLastSwitchedOrgId, useOrg } from "@/hooks/common/useOrg";
import {
authClient,
useListOrganizations,
@@ -257,8 +253,6 @@ export const useOrgSwitch = () => {
organizationId: orgId,
});
- clearOrgCache();
-
const { data: newOrg } = await axiosInstance.get("/organization");
if (newOrg?.id) setLastSwitchedOrgId(newOrg.id);