import { useQueries, useQuery } from '@tanstack/react-query' import { LOCAL_STORAGE_KEYS, useFlag } from 'common' import { useCallback, useMemo } from 'react' import { getRelevantIncidentIds, shouldShowBanner } from './StatusPageBanner.utils' import { useOrganizationsQuery } from '@/data/organizations/organizations-query' import { incidentBannerQueryOptions } from '@/data/platform/incident-banner-query' import { projectKeys } from '@/data/projects/keys' import { getOrganizationProjects, type OrgProject, } from '@/data/projects/org-projects-infinite-query' import { useLocalStorageQuery } from '@/hooks/misc/useLocalStorage' export type StatusPageBannerData = { title: string; dismiss?: () => void } export function useStatusPageBannerVisibility(): StatusPageBannerData | null { const showIncidentBannerOverride = useFlag('ongoingIncident') || process.env.NEXT_PUBLIC_ONGOING_INCIDENT === 'true' const { data: incidentBannerData } = useQuery(incidentBannerQueryOptions()) const bannerItems = incidentBannerData?.incidents ?? [] const incidents = bannerItems.map((i) => ({ id: i.id, cache: i.metadata })) const hasActiveIncidents = incidents.length > 0 const { data: organizations } = useOrganizationsQuery({ enabled: !showIncidentBannerOverride && hasActiveIncidents, }) const orgProjectsQueries = useQueries({ queries: (organizations ?? []).map((org) => ({ queryKey: projectKeys.bannerProjectsByOrg(org.slug), queryFn: () => getOrganizationProjects({ slug: org.slug, limit: 100 }), staleTime: 5 * 60 * 1000, enabled: !showIncidentBannerOverride && hasActiveIncidents, })), }) const isProjectsFetched = organizations !== undefined && (organizations.length === 0 || orgProjectsQueries.every((q) => q.isFetched)) const allProjects = orgProjectsQueries.flatMap((q) => q.data?.projects ?? []) const hasProjects = allProjects.length > 0 const userRegions = useMemo( () => new Set( allProjects.flatMap((project: OrgProject) => project.databases.map((db) => db.region)) ), [allProjects] ) const hasUnknownRegions = orgProjectsQueries.some( (q) => q.isError || (q.data !== undefined && q.data.pagination.count > q.data.projects.length) ) const [dismissedIds, setDismissedIds, { isSuccess: isDismissedLoaded }] = useLocalStorageQuery< Array >(LOCAL_STORAGE_KEYS.INCIDENT_BANNER_DISMISSED_IDS, []) const dismiss = useCallback(() => { const activeIncidentIds = new Set(incidents.map((i) => i.id)) const relevantIds = getRelevantIncidentIds({ incidents, hasProjects, userRegions, hasUnknownRegions, }) setDismissedIds((prev) => [ ...new Set([...prev.filter((id) => activeIncidentIds.has(id)), ...relevantIds]), ]) }, [incidents, hasProjects, userRegions, hasUnknownRegions, setDismissedIds]) if (showIncidentBannerOverride) return { title: 'We are investigating a technical issue' } if (!hasActiveIncidents || !isProjectsFetched) return null const dismissedIdSet = new Set(dismissedIds) const undismissedIncidents = incidents.filter((i) => !dismissedIdSet.has(i.id)) if ( !isDismissedLoaded || !shouldShowBanner({ incidents: undismissedIncidents, hasProjects, userRegions, hasUnknownRegions, }) ) return null const title = hasProjects ? 'We are investigating a technical issue' : 'Project creation may be impacted in some regions' return { title, dismiss } }