import { ChevronDownIcon, Loader2Icon, MoreVerticalIcon, RefreshCwIcon, SettingsIcon, TrashIcon, } from 'lucide-react' import Link from 'next/link' import { forwardRef, useCallback, useState } from 'react' import { toast } from 'sonner' import { Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from 'ui' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { IntegrationConnection, IntegrationConnectionProps, } from '@/components/interfaces/Integrations/VercelGithub/IntegrationPanels' import { ButtonTooltip } from '@/components/ui/ButtonTooltip' import { useIntegrationsVercelConnectionSyncEnvsMutation } from '@/data/integrations/integrations-vercel-connection-sync-envs-mutation' import type { IntegrationProjectConnection } from '@/data/integrations/integrations.types' import { useProjectDetailQuery } from '@/data/projects/project-detail-query' import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization' interface IntegrationConnectionItemProps extends IntegrationConnectionProps { disabled?: boolean isProjectScoped?: boolean onDeleteConnection: (connection: IntegrationProjectConnection) => void | Promise } export const IntegrationConnectionItem = forwardRef( ({ disabled, isProjectScoped = false, onDeleteConnection, ...props }, _ref) => { const { data: org } = useSelectedOrganizationQuery() const { type, connection } = props const { data: project } = useProjectDetailQuery({ ref: connection.supabase_project_ref }) const isBranchingEnabled = project?.is_branch_enabled === true const [isOpen, setIsOpen] = useState(false) const [isDeleting, setIsDeleting] = useState(false) const [dropdownVisible, setDropdownVisible] = useState(false) const onConfirm = useCallback(async () => { try { setIsDeleting(true) await onDeleteConnection(connection) } catch (error) { // [Joshen] No need for error handler } finally { setIsDeleting(false) setIsOpen(false) } }, [connection, onDeleteConnection]) const onCancel = useCallback(() => { setIsOpen(false) }, []) const { mutate: syncEnvs, isPending: isSyncEnvLoading } = useIntegrationsVercelConnectionSyncEnvsMutation({ onSuccess: () => { toast.success('Successfully synced environment variables') setDropdownVisible(false) }, }) const onReSyncEnvVars = useCallback(async () => { syncEnvs({ connectionId: connection.id }) }, [connection, syncEnvs]) const projectIntegrationUrl = `/project/[ref]/settings/integrations` // Project-scoped Vercel rows have their own "Edit" toggle, so "Manage" collapses to an icon const isManageCompact = isProjectScoped && type === 'Vercel' const triggerLabel = isManageCompact ? null : 'Manage' const triggerProps = isManageCompact ? { icon: , className: 'px-1.5', 'aria-label': 'Manage connection' } : { iconRight: } return ( <> {triggerLabel} ) : ( setDropdownVisible(!dropdownVisible)} modal={false} > {!isProjectScoped && ( Configure connection )} {type === 'Vercel' && org?.managed_by !== 'vercel-marketplace' && ( { event.preventDefault() onReSyncEnvVars() }} disabled={isSyncEnvLoading} > {isSyncEnvLoading ? ( ) : ( )}

Resync environment variables

)} {((type === 'Vercel' && org?.managed_by !== 'vercel-marketplace') || !isProjectScoped) && } setIsOpen(true)}>

Delete connection

) } {...props} />

{type === 'Vercel' ? 'Deleting this Vercel connection will stop syncing environment variables to your Vercel project. Existing environment variables will remain unchanged.' : 'Deleting this GitHub connection will stop automatic creation and merging of preview branches. Existing preview branches will remain unchanged.'}

) } ) IntegrationConnectionItem.displayName = 'IntegrationConnectionItem'