Skip to content

Commit a81f384

Browse files
authored
fix(usage-data): refetch on usage limit update in settings (#2032)
1 parent 6f3dee8 commit a81f384

2 files changed

Lines changed: 38 additions & 30 deletions

File tree

  • apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components-new/settings-modal/components/subscription

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components-new/settings-modal/components/subscription/components/usage-limit/usage-limit.tsx

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Button } from '@/components/ui/button'
66
import { createLogger } from '@/lib/logs/console/logger'
77
import { cn } from '@/lib/utils'
88
import { useUsageLimits } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel-new/hooks'
9+
import { useUpdateUsageLimit } from '@/hooks/queries/subscription'
910

1011
const logger = createLogger('UsageLimit')
1112

@@ -42,20 +43,22 @@ export const UsageLimit = forwardRef<UsageLimitRef, UsageLimitProps>(
4243
const [isEditing, setIsEditing] = useState(false)
4344
const inputRef = useRef<HTMLInputElement>(null)
4445

45-
// Use centralized usage limits hook
46-
const { updateLimit, isUpdating } = useUsageLimits({
46+
const { updateLimit, isUpdating: isOrgUpdating } = useUsageLimits({
4747
context,
4848
organizationId,
4949
autoRefresh: false, // Don't auto-refresh, we receive values via props
5050
})
5151

52+
const updateUsageLimitMutation = useUpdateUsageLimit()
53+
const isUpdating =
54+
context === 'organization' ? isOrgUpdating : updateUsageLimitMutation.isPending
55+
5256
const handleStartEdit = () => {
5357
if (!canEdit) return
5458
setIsEditing(true)
5559
setInputValue(currentLimit.toString())
5660
}
5761

58-
// Expose startEdit method through ref
5962
useImperativeHandle(
6063
ref,
6164
() => ({
@@ -68,15 +71,13 @@ export const UsageLimit = forwardRef<UsageLimitRef, UsageLimitProps>(
6871
setInputValue(currentLimit.toString())
6972
}, [currentLimit])
7073

71-
// Focus input when entering edit mode
7274
useEffect(() => {
7375
if (isEditing && inputRef.current) {
7476
inputRef.current.focus()
7577
inputRef.current.select()
7678
}
7779
}, [isEditing])
7880

79-
// Clear error after 2 seconds
8081
useEffect(() => {
8182
if (hasError) {
8283
const timer = setTimeout(() => {
@@ -96,11 +97,9 @@ export const UsageLimit = forwardRef<UsageLimitRef, UsageLimitProps>(
9697
return
9798
}
9899

99-
// Check if new limit is below current usage
100100
if (newLimit < currentUsage) {
101101
setHasError(true)
102102
setErrorType('belowUsage')
103-
// Don't reset input value - let user see what they typed
104103
return
105104
}
106105

@@ -109,20 +108,43 @@ export const UsageLimit = forwardRef<UsageLimitRef, UsageLimitProps>(
109108
return
110109
}
111110

112-
// Use the centralized hook to update the limit
113-
const result = await updateLimit(newLimit)
111+
try {
112+
if (context === 'organization') {
113+
const result = await updateLimit(newLimit)
114+
115+
if (result.success) {
116+
setInputValue(newLimit.toString())
117+
onLimitUpdated?.(newLimit)
118+
setIsEditing(false)
119+
setErrorType(null)
120+
setHasError(false)
121+
} else {
122+
logger.error('Failed to update usage limit', { error: result.error })
123+
124+
if (result.error?.includes('below current usage')) {
125+
setErrorType('belowUsage')
126+
} else {
127+
setErrorType('general')
128+
}
129+
130+
setHasError(true)
131+
}
132+
133+
return
134+
}
135+
136+
await updateUsageLimitMutation.mutateAsync({ limit: newLimit })
114137

115-
if (result.success) {
116138
setInputValue(newLimit.toString())
117139
onLimitUpdated?.(newLimit)
118140
setIsEditing(false)
119141
setErrorType(null)
120142
setHasError(false)
121-
} else {
122-
logger.error('Failed to update usage limit', { error: result.error })
143+
} catch (err) {
144+
logger.error('Failed to update usage limit', { error: err })
123145

124-
// Check if the error is about being below current usage
125-
if (result.error?.includes('below current usage')) {
146+
const message = err instanceof Error ? err.message : String(err)
147+
if (message.includes('below current usage')) {
126148
setErrorType('belowUsage')
127149
} else {
128150
setErrorType('general')
@@ -161,7 +183,6 @@ export const UsageLimit = forwardRef<UsageLimitRef, UsageLimitProps>(
161183
onChange={(e) => setInputValue(e.target.value)}
162184
onKeyDown={handleKeyDown}
163185
onBlur={(e) => {
164-
// Don't submit if clicking on the button (it will handle submission)
165186
const relatedTarget = e.relatedTarget as HTMLElement
166187
if (relatedTarget?.closest('button')) {
167188
return

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components-new/settings-modal/components/subscription/subscription.tsx

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,6 @@ export function Subscription({ onOpenChange }: SubscriptionProps) {
169169
const canManageWorkspaceKeys = userPermissions.canAdmin
170170
const logger = createLogger('Subscription')
171171

172-
// React Query hooks for data fetching
173172
const { data: subscriptionData, isLoading: isSubscriptionLoading } = useSubscriptionData()
174173
const { data: usageLimitResponse, isLoading: isUsageLimitLoading } = useUsageLimitData()
175174
const { data: workspaceData, isLoading: isWorkspaceLoading } = useWorkspaceSettings(workspaceId)
@@ -179,18 +178,15 @@ export function Subscription({ onOpenChange }: SubscriptionProps) {
179178
const activeOrganization = orgsData?.activeOrganization
180179
const activeOrgId = activeOrganization?.id
181180

182-
// Fetch organization billing data with React Query
183181
const { data: organizationBillingData, isLoading: isOrgBillingLoading } = useOrganizationBilling(
184182
activeOrgId || ''
185183
)
186184

187185
const [upgradeError, setUpgradeError] = useState<'pro' | 'team' | null>(null)
188186
const usageLimitRef = useRef<UsageLimitRef | null>(null)
189187

190-
// Combine all loading states
191188
const isLoading = isSubscriptionLoading || isUsageLimitLoading || isWorkspaceLoading
192189

193-
// Extract subscription status from subscriptionData.data
194190
const subscription = {
195191
isFree: subscriptionData?.data?.plan === 'free' || !subscriptionData?.data?.plan,
196192
isPro: subscriptionData?.data?.plan === 'pro',
@@ -205,28 +201,23 @@ export function Subscription({ onOpenChange }: SubscriptionProps) {
205201
seats: subscriptionData?.data?.seats || 1,
206202
}
207203

208-
// Extract usage data from subscriptionData.data.usage (same source as panel usage indicator)
209204
const usage = {
210205
current: subscriptionData?.data?.usage?.current || 0,
211206
limit: subscriptionData?.data?.usage?.limit || 0,
212207
percentUsed: subscriptionData?.data?.usage?.percentUsed || 0,
213208
}
214209

215-
// Extract usage limit metadata from usageLimitResponse.data
216210
const usageLimitData = {
217211
currentLimit: usageLimitResponse?.data?.currentLimit || 0,
218212
minimumLimit: usageLimitResponse?.data?.minimumLimit || (subscription.isPro ? 20 : 40),
219213
}
220214

221-
// Extract billing status
222215
const billingStatus = subscriptionData?.data?.billingBlocked ? 'blocked' : 'ok'
223216

224-
// Extract workspace settings
225217
const billedAccountUserId = workspaceData?.settings?.workspace?.billedAccountUserId ?? null
226218
const workspaceAdmins =
227219
workspaceData?.permissions?.users?.filter((user: any) => user.permissionType === 'admin') || []
228220

229-
// Update workspace settings handler
230221
const updateWorkspaceSettings = async (updates: { billedAccountUserId?: string }) => {
231222
if (!workspaceId) return
232223
try {
@@ -240,7 +231,6 @@ export function Subscription({ onOpenChange }: SubscriptionProps) {
240231
}
241232
}
242233

243-
// Auto-clear upgrade error
244234
useEffect(() => {
245235
if (upgradeError) {
246236
const timer = setTimeout(() => {
@@ -250,11 +240,9 @@ export function Subscription({ onOpenChange }: SubscriptionProps) {
250240
}
251241
}, [upgradeError])
252242

253-
// User role and permissions
254243
const userRole = getUserRole(activeOrganization, session?.user?.email)
255244
const isTeamAdmin = ['owner', 'admin'].includes(userRole)
256245

257-
// Get permissions based on subscription state and user role
258246
const permissions = getSubscriptionPermissions(
259247
{
260248
isFree: subscription.isFree,
@@ -271,7 +259,6 @@ export function Subscription({ onOpenChange }: SubscriptionProps) {
271259
}
272260
)
273261

274-
// Get visible plans based on current subscription
275262
const visiblePlans = getVisiblePlans(
276263
{
277264
isFree: subscription.isFree,
@@ -459,8 +446,8 @@ export function Subscription({ onOpenChange }: SubscriptionProps) {
459446
}
460447
context={subscription.isTeam && isTeamAdmin ? 'organization' : 'user'}
461448
organizationId={subscription.isTeam && isTeamAdmin ? activeOrgId : undefined}
462-
onLimitUpdated={async () => {
463-
// React Query will automatically refetch when the mutation completes
449+
onLimitUpdated={() => {
450+
logger.info('Usage limit updated')
464451
}}
465452
/>
466453
) : undefined

0 commit comments

Comments
 (0)