import React from "react"; import { Lock, AlertCircle, Sparkle } from "lucide-react"; import { Button, type ButtonProps } from "@/src/components/ui/button"; import { HoverCard, HoverCardContent, HoverCardTrigger, } from "@/src/components/ui/hover-card"; import { HoverCardPortal } from "@radix-ui/react-hover-card"; import Link from "next/link"; import { usePostHogClientCapture } from "@/src/features/posthog-analytics/usePostHogClientCapture"; const BUTTON_STATE_MESSAGES = { limitReached: (current: number, max: number) => `You have reached the limit (${current}/${max}) for this resource at your current plan. Upgrade your plan to increase the limit.`, noAccess: "You do not have access to this resource, please ask your admin to grant you access.", entitlement: "This feature is not available in your current plan.", } as const; interface ActionButtonProps extends ButtonProps { icon?: React.ReactNode; loading?: boolean; hasAccess?: boolean; hasEntitlement?: boolean; limitValue?: number; limit?: number | false; children: React.ReactNode; className?: string; href?: string; trackingEventName?: Parameters>[0]; trackingProps?: Record; } export const ActionButton = React.forwardRef< HTMLButtonElement, ActionButtonProps >(function ActionButton( { loading = false, hasAccess = true, hasEntitlement = true, limitValue, limit = false, disabled = false, children, icon, className, href, trackingEventName, trackingProps, ...buttonProps }, ref, ) { const capture = usePostHogClientCapture(); const hasReachedLimit = typeof limit === "number" && limitValue !== undefined && limitValue >= limit; const isDisabled = disabled || !hasAccess || !hasEntitlement || hasReachedLimit; const getMessage = () => { if (!hasAccess) return BUTTON_STATE_MESSAGES.noAccess; if (!hasEntitlement) return BUTTON_STATE_MESSAGES.entitlement; if ( hasReachedLimit && typeof limit === "number" && limitValue !== undefined ) { return BUTTON_STATE_MESSAGES.limitReached(limitValue, limit); } return null; }; const message = getMessage(); // Handle click tracking for external links const handleLinkClick = () => { if (trackingEventName && href && isExternalUrl(href)) { capture(trackingEventName, trackingProps ?? null); } }; const btnContent = ( {children} ); if (isDisabled && message) { return ( {btnContent} {message} ); } return btnContent; }); const isExternalUrl = (url: string) => { return ( url.startsWith("http://") || url.startsWith("https://") || url.startsWith("//") ); }; const ButtonContent = React.forwardRef< HTMLButtonElement, { icon?: React.ReactNode; isDisabled: boolean; loading: boolean; hasAccess: boolean; hasEntitlement: boolean; hasReachedLimit: boolean; className?: string; buttonProps: Omit; children: React.ReactNode; href?: string; onLinkClick?: () => void; } >(function ButtonContent( { icon, isDisabled, loading, hasAccess, hasEntitlement, hasReachedLimit, className, buttonProps, children, href, onLinkClick, }, ref, ) { const content = ( <> {!hasAccess ? ( ) : !hasEntitlement ? ( ) : hasReachedLimit ? ( ) : icon ? (
{icon}
) : null} {children} ); const renderLink = href && !isDisabled; const isExternal = href && isExternalUrl(href); return ( ); });