Files
supabase/apps/studio/components/interfaces/Home/ProjectList/ProjectCard.tsx
T
Jordi EnricandClaude Sonnet 4.6 9c5fabcc7b fix(project-list): remove duplicate resource exhaustion badge DEBUG-48 (#44174)
## Problem

Project cards on the home page showed resource exhaustion warnings
twice: once as a badge in the card header, and again as an alert in the
card footer. This created a confusing, redundant UI as seen when a
project has disk IO, CPU, or other resource warnings active.

## Fix

Removed `resourceWarnings` from the footer `ProjectCardStatus` render in
`ProjectCard.tsx`. Resource exhaustion state now only appears as the
header badge (which already shows a tooltip with the description on
hover). Project status indicators such as paused or restarting still
appear in the footer since those do not depend on resource warnings.

Also removed the dead `showResourceExhaustionWarnings = false` flag from
`ProjectCardStatus.tsx`, which was hardcoded to false and only gated
description text that was no longer reachable.

## How to test

- Navigate to the org home page with a project that has an active
resource warning (disk IO, disk space, CPU, memory, or read-only mode).
- Confirm the warning badge appears in the card header with the correct
color (warning or critical).
- Confirm no duplicate alert appears in the card footer area.
- Confirm that paused or restarting projects still show the status alert
in the footer.
- Confirm the table view still shows the badge correctly in the status
column.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

**Style**
- Project status information now displays exclusively in the project
card footer, removing redundant header display for a cleaner interface.
- Simplified resource warning notification logic for more consistent and
straightforward warning presentation.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 17:01:04 +02:00

157 lines
6.4 KiB
TypeScript

import { Copy, Github, MoreVertical, Settings } from 'lucide-react'
import { useRouter } from 'next/router'
import InlineSVG from 'react-inlinesvg'
import { toast } from 'sonner'
import {
Button,
copyToClipboard,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from 'ui'
import { inferProjectStatus } from './ProjectCard.utils'
import { ProjectCardStatus } from './ProjectCardStatus'
import CardButton from '@/components/ui/CardButton'
import { ComputeBadgeWrapper } from '@/components/ui/ComputeBadgeWrapper'
import type { IntegrationProjectConnection } from '@/data/integrations/integrations.types'
import { ProjectIndexPageLink } from '@/data/prefetchers/project.$ref'
import { getComputeSize, OrgProject } from '@/data/projects/org-projects-infinite-query'
import type { ResourceWarning } from '@/data/usage/resource-warnings-query'
import { useCustomContent } from '@/hooks/custom-content/useCustomContent'
import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
import { BASE_PATH } from '@/lib/constants'
import type { Organization } from '@/types'
export interface ProjectCardProps {
slug?: string
project: OrgProject
organization?: Organization
rewriteHref?: string
githubIntegration?: IntegrationProjectConnection
vercelIntegration?: IntegrationProjectConnection
resourceWarnings?: ResourceWarning
}
export const ProjectCard = ({
slug,
project,
rewriteHref,
githubIntegration,
vercelIntegration,
resourceWarnings,
}: ProjectCardProps) => {
const router = useRouter()
const { name, ref: projectRef } = project
const { infraAwsNimbusLabel } = useCustomContent(['infra:aws_nimbus_label'])
const providerLabel =
project.cloud_provider === 'AWS_NIMBUS' ? infraAwsNimbusLabel : project.cloud_provider
const desc = `${providerLabel} | ${project.region}`
const { projectHomepageShowInstanceSize } = useIsFeatureEnabled([
'project_homepage:show_instance_size',
])
const isGithubIntegrated = githubIntegration !== undefined
const isVercelIntegrated = vercelIntegration !== undefined
const githubRepository = githubIntegration?.metadata.name ?? undefined
const projectStatus = inferProjectStatus(project.status)
return (
<>
<li className="list-none h-min">
<CardButton
linkHref={rewriteHref ? rewriteHref : `/project/${projectRef}`}
className="h-44 !px-0 group pt-5 pb-0 overflow-hidden relative"
hideChevron
title={
<div className="w-full flex flex-col gap-y-4 justify-between px-5">
<div className="flex flex-col gap-y-0.5 relative">
<div className="flex items-center justify-between">
<h5 className="text-sm flex-shrink truncate pr-5">{name}</h5>
<div onClick={(e) => e.preventDefault()}>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
type="text"
icon={<MoreVertical size={14} />}
className="w-6 h-6 px-0"
onClick={(e) => {
e.stopPropagation()
e.preventDefault()
}}
onPointerDown={(e) => e.stopPropagation()}
/>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-48">
<DropdownMenuItem
className="gap-x-2"
onClick={(e) => {
e.stopPropagation()
copyToClipboard(projectRef)
toast.success('Copied project ID to clipboard')
}}
>
<Copy size={14} />
<span>Copy project ID</span>
</DropdownMenuItem>
<DropdownMenuItem
className="gap-x-2"
onClick={(e) => {
e.stopPropagation()
router.push(`/project/${projectRef}/settings/general`)
}}
>
<Settings size={14} />
<span>Settings</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
</div>
<p className="text-sm text-foreground-lighter">{desc}</p>
</div>
<div className="flex items-center gap-x-1.5 relative overflow-hidden">
{project.status !== 'INACTIVE' && projectHomepageShowInstanceSize && (
<ComputeBadgeWrapper
slug={slug}
projectRef={project.ref}
cloudProvider={project.cloud_provider}
computeSize={getComputeSize(project)}
resourceWarnings={resourceWarnings}
badgeClassName="text-[10px] leading-none tracking-[0.07em]"
/>
)}
{isVercelIntegrated && (
<div className="bg-surface-100 w-5 h-5 p-1 border border-strong rounded-md flex items-center justify-center text-black dark:text-white">
<InlineSVG
src={`${BASE_PATH}/img/icons/vercel-icon.svg`}
title="Vercel Icon"
className="w-3"
/>
</div>
)}
{isGithubIntegrated && (
<div className="bg-surface-100 flex items-center gap-x-0.5 h-5 pr-1 border border-strong rounded-md min-w-0">
<div className="w-5 h-5 p-1 flex items-center justify-center shrink-0">
<Github size={12} strokeWidth={1.5} />
</div>
<p className="text-xs text-foreground-light truncate">{githubRepository}</p>
</div>
)}
</div>
</div>
}
footer={
<ProjectCardStatus projectStatus={projectStatus} resourceWarnings={resourceWarnings} />
}
containerElement={<ProjectIndexPageLink projectRef={projectRef} />}
/>
</li>
</>
)
}