@@ -63,6 +63,7 @@ import { generalSettingsKeys, useGeneralSettings } from '@/hooks/queries/general
6363import { organizationKeys , useOrganizations } from '@/hooks/queries/organization'
6464import { ssoKeys , useSSOProviders } from '@/hooks/queries/sso'
6565import { subscriptionKeys , useSubscriptionData } from '@/hooks/queries/subscription'
66+ import { useSuperUserStatus } from '@/hooks/queries/user-profile'
6667import { usePermissionConfig } from '@/hooks/use-permission-config'
6768import { useSettingsModalStore } from '@/stores/modals/settings/store'
6869
@@ -204,13 +205,13 @@ export function SettingsModal({ open, onOpenChange }: SettingsModalProps) {
204205 const [ activeSection , setActiveSection ] = useState < SettingsSection > ( 'general' )
205206 const { initialSection, mcpServerId, clearInitialState } = useSettingsModalStore ( )
206207 const [ pendingMcpServerId , setPendingMcpServerId ] = useState < string | null > ( null )
207- const [ isSuperUser , setIsSuperUser ] = useState ( false )
208208 const { data : session } = useSession ( )
209209 const queryClient = useQueryClient ( )
210210 const { data : organizationsData } = useOrganizations ( )
211211 const { data : generalSettings } = useGeneralSettings ( )
212212 const { data : subscriptionData } = useSubscriptionData ( { enabled : isBillingEnabled } )
213213 const { data : ssoProvidersData , isLoading : isLoadingSSO } = useSSOProviders ( )
214+ const { data : superUserData } = useSuperUserStatus ( Boolean ( session ?. user ?. id ) )
214215
215216 const activeOrganization = organizationsData ?. activeOrganization
216217 const { config : permissionConfig } = usePermissionConfig ( )
@@ -229,22 +230,7 @@ export function SettingsModal({ open, onOpenChange }: SettingsModalProps) {
229230 const hasEnterprisePlan = subscriptionStatus . isEnterprise
230231 const hasOrganization = ! ! activeOrganization ?. id
231232
232- // Fetch superuser status
233- useEffect ( ( ) => {
234- const fetchSuperUserStatus = async ( ) => {
235- if ( ! userId ) return
236- try {
237- const response = await fetch ( '/api/user/super-user' )
238- if ( response . ok ) {
239- const data = await response . json ( )
240- setIsSuperUser ( data . isSuperUser )
241- }
242- } catch {
243- setIsSuperUser ( false )
244- }
245- }
246- fetchSuperUserStatus ( )
247- } , [ userId ] )
233+ const isSuperUser = superUserData ?. isSuperUser ?? false
248234
249235 // Memoize SSO provider ownership check
250236 const isSSOProviderOwner = useMemo ( ( ) => {
@@ -328,7 +314,13 @@ export function SettingsModal({ open, onOpenChange }: SettingsModalProps) {
328314 generalSettings ?. superUserModeEnabled ,
329315 ] )
330316
331- // Memoized callbacks to prevent infinite loops in child components
317+ const effectiveActiveSection = useMemo ( ( ) => {
318+ if ( ! isBillingEnabled && ( activeSection === 'subscription' || activeSection === 'team' ) ) {
319+ return 'general'
320+ }
321+ return activeSection
322+ } , [ activeSection ] )
323+
332324 const registerEnvironmentBeforeLeaveHandler = useCallback (
333325 ( handler : ( onProceed : ( ) => void ) => void ) => {
334326 environmentBeforeLeaveHandler . current = handler
@@ -342,19 +334,18 @@ export function SettingsModal({ open, onOpenChange }: SettingsModalProps) {
342334
343335 const handleSectionChange = useCallback (
344336 ( sectionId : SettingsSection ) => {
345- if ( sectionId === activeSection ) return
337+ if ( sectionId === effectiveActiveSection ) return
346338
347- if ( activeSection === 'environment' && environmentBeforeLeaveHandler . current ) {
339+ if ( effectiveActiveSection === 'environment' && environmentBeforeLeaveHandler . current ) {
348340 environmentBeforeLeaveHandler . current ( ( ) => setActiveSection ( sectionId ) )
349341 return
350342 }
351343
352344 setActiveSection ( sectionId )
353345 } ,
354- [ activeSection ]
346+ [ effectiveActiveSection ]
355347 )
356348
357- // Apply initial section from store when modal opens
358349 useEffect ( ( ) => {
359350 if ( open && initialSection ) {
360351 setActiveSection ( initialSection )
@@ -365,7 +356,6 @@ export function SettingsModal({ open, onOpenChange }: SettingsModalProps) {
365356 }
366357 } , [ open , initialSection , mcpServerId , clearInitialState ] )
367358
368- // Clear pending server ID when section changes away from MCP
369359 useEffect ( ( ) => {
370360 if ( activeSection !== 'mcp' ) {
371361 setPendingMcpServerId ( null )
@@ -391,14 +381,6 @@ export function SettingsModal({ open, onOpenChange }: SettingsModalProps) {
391381 }
392382 } , [ onOpenChange ] )
393383
394- // Redirect away from billing tabs if billing is disabled
395- useEffect ( ( ) => {
396- if ( ! isBillingEnabled && ( activeSection === 'subscription' || activeSection === 'team' ) ) {
397- setActiveSection ( 'general' )
398- }
399- } , [ activeSection ] )
400-
401- // Prefetch functions for React Query
402384 const prefetchGeneral = ( ) => {
403385 queryClient . prefetchQuery ( {
404386 queryKey : generalSettingsKeys . settings ( ) ,
@@ -489,9 +471,17 @@ export function SettingsModal({ open, onOpenChange }: SettingsModalProps) {
489471
490472 // Handle dialog close - delegate to environment component if it's active
491473 const handleDialogOpenChange = ( newOpen : boolean ) => {
492- if ( ! newOpen && activeSection === 'environment' && environmentBeforeLeaveHandler . current ) {
474+ if (
475+ ! newOpen &&
476+ effectiveActiveSection === 'environment' &&
477+ environmentBeforeLeaveHandler . current
478+ ) {
493479 environmentBeforeLeaveHandler . current ( ( ) => onOpenChange ( false ) )
494- } else if ( ! newOpen && activeSection === 'integrations' && integrationsCloseHandler . current ) {
480+ } else if (
481+ ! newOpen &&
482+ effectiveActiveSection === 'integrations' &&
483+ integrationsCloseHandler . current
484+ ) {
495485 integrationsCloseHandler . current ( newOpen )
496486 } else {
497487 onOpenChange ( newOpen )
@@ -522,7 +512,7 @@ export function SettingsModal({ open, onOpenChange }: SettingsModalProps) {
522512 { sectionItems . map ( ( item ) => (
523513 < SModalSidebarItem
524514 key = { item . id }
525- active = { activeSection === item . id }
515+ active = { effectiveActiveSection === item . id }
526516 icon = { < item . icon /> }
527517 onMouseEnter = { ( ) => handlePrefetch ( item . id ) }
528518 onClick = { ( ) => handleSectionChange ( item . id ) }
@@ -538,35 +528,36 @@ export function SettingsModal({ open, onOpenChange }: SettingsModalProps) {
538528
539529 < SModalMain >
540530 < SModalMainHeader >
541- { navigationItems . find ( ( item ) => item . id === activeSection ) ?. label || activeSection }
531+ { navigationItems . find ( ( item ) => item . id === effectiveActiveSection ) ?. label ||
532+ effectiveActiveSection }
542533 </ SModalMainHeader >
543534 < SModalMainBody >
544- { activeSection === 'general' && < General onOpenChange = { onOpenChange } /> }
545- { activeSection === 'environment' && (
535+ { effectiveActiveSection === 'general' && < General onOpenChange = { onOpenChange } /> }
536+ { effectiveActiveSection === 'environment' && (
546537 < EnvironmentVariables
547538 registerBeforeLeaveHandler = { registerEnvironmentBeforeLeaveHandler }
548539 />
549540 ) }
550- { activeSection === 'template-profile' && < TemplateProfile /> }
551- { activeSection === 'integrations' && (
541+ { effectiveActiveSection === 'template-profile' && < TemplateProfile /> }
542+ { effectiveActiveSection === 'integrations' && (
552543 < Integrations
553544 onOpenChange = { onOpenChange }
554545 registerCloseHandler = { registerIntegrationsCloseHandler }
555546 />
556547 ) }
557- { activeSection === 'credential-sets' && < CredentialSets /> }
558- { activeSection === 'access-control' && < AccessControl /> }
559- { activeSection === 'apikeys' && < ApiKeys onOpenChange = { onOpenChange } /> }
560- { activeSection === 'files' && < FileUploads /> }
561- { isBillingEnabled && activeSection === 'subscription' && < Subscription /> }
562- { isBillingEnabled && activeSection === 'team' && < TeamManagement /> }
563- { activeSection === 'sso' && < SSO /> }
564- { activeSection === 'byok' && < BYOK /> }
565- { activeSection === 'copilot' && < Copilot /> }
566- { activeSection === 'mcp' && < MCP initialServerId = { pendingMcpServerId } /> }
567- { activeSection === 'custom-tools' && < CustomTools /> }
568- { activeSection === 'workflow-mcp-servers' && < WorkflowMcpServers /> }
569- { activeSection === 'debug' && < Debug /> }
548+ { effectiveActiveSection === 'credential-sets' && < CredentialSets /> }
549+ { effectiveActiveSection === 'access-control' && < AccessControl /> }
550+ { effectiveActiveSection === 'apikeys' && < ApiKeys onOpenChange = { onOpenChange } /> }
551+ { effectiveActiveSection === 'files' && < FileUploads /> }
552+ { isBillingEnabled && effectiveActiveSection === 'subscription' && < Subscription /> }
553+ { isBillingEnabled && effectiveActiveSection === 'team' && < TeamManagement /> }
554+ { effectiveActiveSection === 'sso' && < SSO /> }
555+ { effectiveActiveSection === 'byok' && < BYOK /> }
556+ { effectiveActiveSection === 'copilot' && < Copilot /> }
557+ { effectiveActiveSection === 'mcp' && < MCP initialServerId = { pendingMcpServerId } /> }
558+ { effectiveActiveSection === 'custom-tools' && < CustomTools /> }
559+ { effectiveActiveSection === 'workflow-mcp-servers' && < WorkflowMcpServers /> }
560+ { effectiveActiveSection === 'debug' && < Debug /> }
570561 </ SModalMainBody >
571562 </ SModalMain >
572563 </ SModalContent >
0 commit comments