fix(usage-data): refetch on usage limit update in settings (#2032)

This commit is contained in:
Waleed
2025-11-17 15:07:52 -08:00
committed by GitHub
parent 6f3dee867c
commit a81f3847df
2 changed files with 38 additions and 30 deletions

View File

@@ -6,6 +6,7 @@ import { Button } from '@/components/ui/button'
import { createLogger } from '@/lib/logs/console/logger'
import { cn } from '@/lib/utils'
import { useUsageLimits } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel-new/hooks'
import { useUpdateUsageLimit } from '@/hooks/queries/subscription'
const logger = createLogger('UsageLimit')
@@ -42,20 +43,22 @@ export const UsageLimit = forwardRef<UsageLimitRef, UsageLimitProps>(
const [isEditing, setIsEditing] = useState(false)
const inputRef = useRef<HTMLInputElement>(null)
// Use centralized usage limits hook
const { updateLimit, isUpdating } = useUsageLimits({
const { updateLimit, isUpdating: isOrgUpdating } = useUsageLimits({
context,
organizationId,
autoRefresh: false, // Don't auto-refresh, we receive values via props
})
const updateUsageLimitMutation = useUpdateUsageLimit()
const isUpdating =
context === 'organization' ? isOrgUpdating : updateUsageLimitMutation.isPending
const handleStartEdit = () => {
if (!canEdit) return
setIsEditing(true)
setInputValue(currentLimit.toString())
}
// Expose startEdit method through ref
useImperativeHandle(
ref,
() => ({
@@ -68,7 +71,6 @@ export const UsageLimit = forwardRef<UsageLimitRef, UsageLimitProps>(
setInputValue(currentLimit.toString())
}, [currentLimit])
// Focus input when entering edit mode
useEffect(() => {
if (isEditing && inputRef.current) {
inputRef.current.focus()
@@ -76,7 +78,6 @@ export const UsageLimit = forwardRef<UsageLimitRef, UsageLimitProps>(
}
}, [isEditing])
// Clear error after 2 seconds
useEffect(() => {
if (hasError) {
const timer = setTimeout(() => {
@@ -96,11 +97,9 @@ export const UsageLimit = forwardRef<UsageLimitRef, UsageLimitProps>(
return
}
// Check if new limit is below current usage
if (newLimit < currentUsage) {
setHasError(true)
setErrorType('belowUsage')
// Don't reset input value - let user see what they typed
return
}
@@ -109,20 +108,43 @@ export const UsageLimit = forwardRef<UsageLimitRef, UsageLimitProps>(
return
}
// Use the centralized hook to update the limit
const result = await updateLimit(newLimit)
try {
if (context === 'organization') {
const result = await updateLimit(newLimit)
if (result.success) {
setInputValue(newLimit.toString())
onLimitUpdated?.(newLimit)
setIsEditing(false)
setErrorType(null)
setHasError(false)
} else {
logger.error('Failed to update usage limit', { error: result.error })
if (result.error?.includes('below current usage')) {
setErrorType('belowUsage')
} else {
setErrorType('general')
}
setHasError(true)
}
return
}
await updateUsageLimitMutation.mutateAsync({ limit: newLimit })
if (result.success) {
setInputValue(newLimit.toString())
onLimitUpdated?.(newLimit)
setIsEditing(false)
setErrorType(null)
setHasError(false)
} else {
logger.error('Failed to update usage limit', { error: result.error })
} catch (err) {
logger.error('Failed to update usage limit', { error: err })
// Check if the error is about being below current usage
if (result.error?.includes('below current usage')) {
const message = err instanceof Error ? err.message : String(err)
if (message.includes('below current usage')) {
setErrorType('belowUsage')
} else {
setErrorType('general')
@@ -161,7 +183,6 @@ export const UsageLimit = forwardRef<UsageLimitRef, UsageLimitProps>(
onChange={(e) => setInputValue(e.target.value)}
onKeyDown={handleKeyDown}
onBlur={(e) => {
// Don't submit if clicking on the button (it will handle submission)
const relatedTarget = e.relatedTarget as HTMLElement
if (relatedTarget?.closest('button')) {
return

View File

@@ -169,7 +169,6 @@ export function Subscription({ onOpenChange }: SubscriptionProps) {
const canManageWorkspaceKeys = userPermissions.canAdmin
const logger = createLogger('Subscription')
// React Query hooks for data fetching
const { data: subscriptionData, isLoading: isSubscriptionLoading } = useSubscriptionData()
const { data: usageLimitResponse, isLoading: isUsageLimitLoading } = useUsageLimitData()
const { data: workspaceData, isLoading: isWorkspaceLoading } = useWorkspaceSettings(workspaceId)
@@ -179,7 +178,6 @@ export function Subscription({ onOpenChange }: SubscriptionProps) {
const activeOrganization = orgsData?.activeOrganization
const activeOrgId = activeOrganization?.id
// Fetch organization billing data with React Query
const { data: organizationBillingData, isLoading: isOrgBillingLoading } = useOrganizationBilling(
activeOrgId || ''
)
@@ -187,10 +185,8 @@ export function Subscription({ onOpenChange }: SubscriptionProps) {
const [upgradeError, setUpgradeError] = useState<'pro' | 'team' | null>(null)
const usageLimitRef = useRef<UsageLimitRef | null>(null)
// Combine all loading states
const isLoading = isSubscriptionLoading || isUsageLimitLoading || isWorkspaceLoading
// Extract subscription status from subscriptionData.data
const subscription = {
isFree: subscriptionData?.data?.plan === 'free' || !subscriptionData?.data?.plan,
isPro: subscriptionData?.data?.plan === 'pro',
@@ -205,28 +201,23 @@ export function Subscription({ onOpenChange }: SubscriptionProps) {
seats: subscriptionData?.data?.seats || 1,
}
// Extract usage data from subscriptionData.data.usage (same source as panel usage indicator)
const usage = {
current: subscriptionData?.data?.usage?.current || 0,
limit: subscriptionData?.data?.usage?.limit || 0,
percentUsed: subscriptionData?.data?.usage?.percentUsed || 0,
}
// Extract usage limit metadata from usageLimitResponse.data
const usageLimitData = {
currentLimit: usageLimitResponse?.data?.currentLimit || 0,
minimumLimit: usageLimitResponse?.data?.minimumLimit || (subscription.isPro ? 20 : 40),
}
// Extract billing status
const billingStatus = subscriptionData?.data?.billingBlocked ? 'blocked' : 'ok'
// Extract workspace settings
const billedAccountUserId = workspaceData?.settings?.workspace?.billedAccountUserId ?? null
const workspaceAdmins =
workspaceData?.permissions?.users?.filter((user: any) => user.permissionType === 'admin') || []
// Update workspace settings handler
const updateWorkspaceSettings = async (updates: { billedAccountUserId?: string }) => {
if (!workspaceId) return
try {
@@ -240,7 +231,6 @@ export function Subscription({ onOpenChange }: SubscriptionProps) {
}
}
// Auto-clear upgrade error
useEffect(() => {
if (upgradeError) {
const timer = setTimeout(() => {
@@ -250,11 +240,9 @@ export function Subscription({ onOpenChange }: SubscriptionProps) {
}
}, [upgradeError])
// User role and permissions
const userRole = getUserRole(activeOrganization, session?.user?.email)
const isTeamAdmin = ['owner', 'admin'].includes(userRole)
// Get permissions based on subscription state and user role
const permissions = getSubscriptionPermissions(
{
isFree: subscription.isFree,
@@ -271,7 +259,6 @@ export function Subscription({ onOpenChange }: SubscriptionProps) {
}
)
// Get visible plans based on current subscription
const visiblePlans = getVisiblePlans(
{
isFree: subscription.isFree,
@@ -459,8 +446,8 @@ export function Subscription({ onOpenChange }: SubscriptionProps) {
}
context={subscription.isTeam && isTeamAdmin ? 'organization' : 'user'}
organizationId={subscription.isTeam && isTeamAdmin ? activeOrgId : undefined}
onLimitUpdated={async () => {
// React Query will automatically refetch when the mutation completes
onLimitUpdated={() => {
logger.info('Usage limit updated')
}}
/>
) : undefined