import { mdiCreditCardOutline } from '@mdi/js' import axios from 'axios' import React, { useEffect, useState } from 'react' import BaseButton from './BaseButton' import CardBox from './CardBox' import { useAppSelector } from '../stores/hooks' import { isInternalAdmin } from '../helpers/portalRoles' type LimitKey = 'monthlyReviewRequests' | 'businesses' | 'teamMembers' | 'paymentConnectors' type SubscriptionLimitStatus = { subscription: { planId: string planName: string effectiveStatus: string isActive: boolean } usage: Record limits: Record } type Props = { limitKey: LimitKey actionLabel: string label?: string className?: string nearLimitPercent?: number } const defaultLabels: Record = { monthlyReviewRequests: 'review requests this month', businesses: 'business profiles', teamMembers: 'team members', paymentConnectors: 'connected payment providers', } function formatNumber(value: number) { return value.toLocaleString() } export default function SubscriptionLimitGate({ limitKey, actionLabel, label, className = 'mb-6', nearLimitPercent = 80, }: Props) { const { currentUser } = useAppSelector((state) => state.auth) const [status, setStatus] = useState(null) const [error, setError] = useState('') useEffect(() => { let isMounted = true const loadStatus = async () => { try { const response = await axios.get('/subscription/me') if (isMounted) { setStatus(response.data) setError('') } } catch (requestError) { console.error('Failed to load subscription limit status:', requestError) if (isMounted) { setError('Could not check plan limits right now. The backend will still enforce them when you submit.') } } } if (!currentUser || isInternalAdmin(currentUser)) { setStatus(null) setError('') return () => { isMounted = false } } loadStatus() return () => { isMounted = false } }, [currentUser]) if (error) { return (

Plan check unavailable

{error}

) } if (!status) { return null } const used = Number(status.usage[limitKey]) || 0 const limit = Number(status.limits[limitKey]) || 0 const limitLabel = label || (limit === 1 && limitKey === 'businesses' ? 'business profile' : defaultLabels[limitKey]) const percent = limit > 0 ? Math.round((used / limit) * 100) : 0 const isInactive = !status.subscription.isActive const isBlocked = isInactive || (limit > 0 && used >= limit) const isNearLimit = !isBlocked && percent >= nearLimitPercent if (!isBlocked && !isNearLimit) { return null } const cardClass = isBlocked ? 'border-0 bg-rose-50 text-rose-950 ring-1 ring-rose-200 dark:bg-rose-950 dark:text-rose-50 dark:ring-rose-800' : 'border-0 bg-amber-50 text-amber-950 ring-1 ring-amber-200 dark:bg-amber-950 dark:text-amber-50 dark:ring-amber-800' const buttonLabel = status.subscription.planId === 'starter' ? 'Upgrade to Pro' : 'Manage plan' return (

{isBlocked ? 'Plan limit reached' : 'Plan limit almost reached'}

{actionLabel} {isBlocked ? 'may be blocked' : 'is getting close to the limit'}

{isInactive ? `Your ${status.subscription.planName} plan is ${status.subscription.effectiveStatus}. Reactivate or choose a plan before continuing.` : `${status.subscription.planName} includes ${formatNumber(limit)} ${limitLabel}. This account is using ${formatNumber(used)}.`} {' '}Existing data stays available.

) }