import { Check, ChipLink, ChipTag, cn } from '@sim/emcn'
import { SlackIcon } from '@/components/icons'
import type { CellValue } from '@/app/workspace/[workspaceId]/upgrade/components/comparison-table/comparison-data'
/** Maps a cell-icon identifier to its brand icon component. */
const CELL_ICONS = { slack: SlackIcon } as const
/** Resolved CTA for a pricing card - label, chip variant, and destination href. */
export interface PricingCardCta {
label: string
variant: 'primary' | 'border-shadow'
href: string
}
/** A labelled group of feature rows for one plan, transposed from the comparison data. */
export interface PricingCardSection {
/** Stable key for the section, used for React reconciliation. */
key: string
/** Section header, e.g. `"Rate limits (runs/min)"`. Omit to render the rows without a header. */
title?: string
/** Feature rows - this plan's value for each comparison row in the section. */
rows: { label: string; value: CellValue }[]
}
/**
* Props for {@link PricingCard}.
*/
export interface PricingCardProps {
/** Plan name, e.g. `"Pro"`. */
name: string
/** Headline price, e.g. `"$25"`, `"$0"`, or `"Custom"`. */
price: string
/** Small line under the price, e.g. `"per user/month, billed monthly"`. */
priceSubtext?: string
/** Optional discount pill next to the price, e.g. `"15% off"`. */
discountLabel?: string
/** Resolved CTA - label, variant, and destination href. */
cta: PricingCardCta
/** Full feature breakdown for this plan, grouped by section. */
sections: PricingCardSection[]
/** Extra outer classes. */
className?: string
}
/**
* Renders one plan's value for a feature row: `true` → check, `false` → em-dash,
* an icon reference → its brand icon, a string → right-aligned text.
*/
function FeatureValue({ value }: { value: CellValue }) {
if (value === true) {
return
}
if (value === false) {
return –
}
if (typeof value === 'object') {
const Icon = CELL_ICONS[value.icon]
return
}
return (
{value}
)
}
/**
* Public pricing card - one plan rendered as a self-contained spec sheet: the
* header (name, price, CTA, segment) above the full comparison breakdown, grouped
* by section with a hairline rule under each section header.
*
* The radius (`rounded-lg`) matches the landing hero's visual panel so the cards
* line up with the rest of the landing chrome. Every card carries the identical
* row structure (only values differ) so a grid of them renders at exactly the
* same height. Feature rows are transposed from the shared comparison data, so
* the card can never drift from the platform.
*/
export function PricingCard({
name,
price,
priceSubtext,
discountLabel,
cta,
sections,
className,
}: PricingCardProps) {
return (