Skip to content

Commit 153c49a

Browse files
feat(tables): add Upgrade action to the row-limit toast
1 parent c42018e commit 153c49a

1 file changed

Lines changed: 24 additions & 8 deletions

File tree

apps/sim/hooks/queries/tables.ts

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ import {
9292
optimisticallyScheduleNewlyEligibleGroups,
9393
} from '@/lib/table/deps'
9494
import { runUploadStrategy } from '@/lib/uploads/client/direct-upload'
95+
import { useSettingsNavigation } from '@/hooks/use-settings-navigation'
9596

9697
const logger = createLogger('TableQueries')
9798

@@ -571,8 +572,28 @@ export function useDeleteTable(workspaceId: string) {
571572
* Populates the cache on success so the new row is immediately available
572573
* without waiting for the background refetch triggered by invalidation.
573574
*/
575+
/**
576+
* Toasts a failed row write. A plan row-limit failure (the best-effort cap in
577+
* `assertRowCapacity`) gets an "Upgrade" action routing to billing; other errors are
578+
* a plain auto-dismissing toast. Validation errors are surfaced inline, not here.
579+
*/
580+
function notifyRowWriteError(
581+
error: Error,
582+
navigateToSettings: ReturnType<typeof useSettingsNavigation>['navigateToSettings']
583+
): void {
584+
if (isValidationError(error)) return
585+
if (error.message.toLowerCase().includes('row limit')) {
586+
toast.error(error.message, {
587+
action: { label: 'Upgrade', onClick: () => navigateToSettings({ section: 'billing' }) },
588+
})
589+
return
590+
}
591+
toast.error(error.message, { duration: 5000 })
592+
}
593+
574594
export function useCreateTableRow({ workspaceId, tableId }: RowMutationContext) {
575595
const queryClient = useQueryClient()
596+
const { navigateToSettings } = useSettingsNavigation()
576597

577598
return useMutation({
578599
mutationFn: async (
@@ -617,10 +638,7 @@ export function useCreateTableRow({ workspaceId, tableId }: RowMutationContext)
617638
predicate: (query) => !isDefaultOrderRowsQuery(query.queryKey),
618639
})
619640
},
620-
onError: (error) => {
621-
if (isValidationError(error)) return
622-
toast.error(error.message, { duration: 5000 })
623-
},
641+
onError: (error) => notifyRowWriteError(error, navigateToSettings),
624642
onSettled: () => {
625643
// `reconcileCreatedRow` (onSuccess) is the source of truth for the rows
626644
// cache + its `totalCount`; only refresh the count surfaces here so a late
@@ -783,6 +801,7 @@ type BatchCreateTableRowsResponse = ContractJsonResponse<typeof batchCreateTable
783801
*/
784802
export function useBatchCreateTableRows({ workspaceId, tableId }: RowMutationContext) {
785803
const queryClient = useQueryClient()
804+
const { navigateToSettings } = useSettingsNavigation()
786805

787806
return useMutation({
788807
mutationFn: async (
@@ -798,10 +817,7 @@ export function useBatchCreateTableRows({ workspaceId, tableId }: RowMutationCon
798817
},
799818
})
800819
},
801-
onError: (error) => {
802-
if (isValidationError(error)) return
803-
toast.error(error.message, { duration: 5000 })
804-
},
820+
onError: (error) => notifyRowWriteError(error, navigateToSettings),
805821
onSettled: () => {
806822
invalidateRowCount(queryClient, tableId)
807823
},

0 commit comments

Comments
 (0)