{"version":3,"sources":["../src/components/PerformanceRanking/PerformanceRanking.tsx"],"sourcesContent":["import { type HTMLAttributes } from 'react';\nimport {\n  TrendUpIcon,\n  TrendDownIcon,\n  MedalIcon,\n  SealWarningIcon,\n} from '@phosphor-icons/react';\nimport Text from '../Text/Text';\nimport { cn } from '../../utils/utils';\nimport {\n  type RankingVariant,\n  BADGE_BACKGROUND_CLASSES,\n  PERCENTAGE_BADGE_CLASSES,\n  getPositionBackgroundClass,\n  BaseRankingCard,\n  RankingLayout,\n} from '../shared/RankingShared';\n\n/**\n * Single item in the performance ranking\n */\nexport interface PerformanceRankingItem {\n  position: number;\n  name: string;\n  count: number;\n  percentage: number;\n  trend: 'up' | 'down' | null;\n  /** Only present when groupedBy = 'class' */\n  shift?: string;\n  /** Only present when groupedBy = 'class' */\n  grade?: string;\n}\n\n/**\n * How the ranking data is grouped\n */\nexport type GroupedBy = 'state' | 'municipality' | 'class';\n\n/**\n * Full ranking data from the API\n */\nexport interface PerformanceRankingData {\n  /** Informational only — the component does not branch on this value.\n   *  Class-specific rendering (shift/grade) is derived from field presence. */\n  groupedBy: GroupedBy;\n  highlighted: (PerformanceRankingItem | null)[];\n  needsAttention: (PerformanceRankingItem | null)[];\n}\n\n/**\n * Props for the PerformanceRanking component\n */\nexport interface PerformanceRankingProps extends HTMLAttributes<HTMLDivElement> {\n  /** Ranking data from the API */\n  data: PerformanceRankingData;\n  /** Title for the highlight card */\n  highlightTitle?: string;\n  /** Title for the attention card */\n  attentionTitle?: string;\n  /** Label displayed next to the count value (e.g. \"estudantes\") */\n  countLabel?: string;\n}\n\n/**\n * Position badge text color per variant\n */\nconst POSITION_TEXT_CLASSES = {\n  highlight: 'text-text-950',\n  attention: 'text-text',\n} as const;\n\n/**\n * Count badge classes — neutral color to distinguish from percentage\n */\nconst COUNT_BADGE_CLASSES = {\n  highlight: 'bg-success-background text-success-800',\n  attention: 'bg-error-background text-error-800',\n} as const;\n\n/**\n * Render the trend icon based on the item's trend value\n */\nfunction TrendIcon({\n  trend,\n  variant,\n}: Readonly<{\n  trend: 'up' | 'down' | null;\n  variant: RankingVariant;\n}>) {\n  if (trend === 'up') {\n    return <TrendUpIcon size={16} weight=\"bold\" aria-hidden=\"true\" />;\n  }\n  if (trend === 'down') {\n    return <TrendDownIcon size={16} weight=\"bold\" aria-hidden=\"true\" />;\n  }\n  // Intentional UX decision: when the API returns null (trend unavailable),\n  // we show the variant's default direction (up for highlight, down for attention)\n  // so the badge layout stays uniform across all rows — confirmed in Figma.\n  const DefaultIcon = variant === 'highlight' ? TrendUpIcon : TrendDownIcon;\n  return <DefaultIcon size={16} weight=\"bold\" aria-hidden=\"true\" />;\n}\n\n/**\n * Build the display name including shift/grade inline when present.\n * e.g. \"Turma A (Manhã) (3° ano)\"\n */\nfunction buildDisplayName(item: PerformanceRankingItem): string {\n  const parts = [item.name];\n  if (item.shift) parts.push(`(${item.shift})`);\n  if (item.grade) parts.push(`(${item.grade})`);\n  return parts.join(' ');\n}\n\n/**\n * Individual performance ranking item card\n */\nfunction PerformanceItemCard({\n  item,\n  variant,\n  countLabel,\n}: Readonly<{\n  item: PerformanceRankingItem;\n  variant: RankingVariant;\n  countLabel?: string;\n}>) {\n  const backgroundClass = getPositionBackgroundClass(variant, item.position);\n  const displayName = buildDisplayName(item);\n  const countText = countLabel\n    ? `${item.count} ${countLabel}`\n    : String(item.count);\n\n  return (\n    <div\n      className={cn(\n        'flex flex-row items-center w-full p-4 gap-2 rounded-xl',\n        backgroundClass\n      )}\n    >\n      {/* Position badge */}\n      <Text\n        size=\"xs\"\n        weight=\"bold\"\n        aria-label={`Position ${item.position}`}\n        className={cn(\n          'w-5 h-5 rounded-full flex items-center justify-center flex-shrink-0',\n          POSITION_TEXT_CLASSES[variant],\n          BADGE_BACKGROUND_CLASSES[variant]\n        )}\n      >\n        {item.position}\n      </Text>\n\n      {/* Name (with shift/grade inline) */}\n      <Text\n        size=\"sm\"\n        weight=\"bold\"\n        className=\"flex-1 min-w-0 text-text-950 tracking-[0.2px] truncate\"\n      >\n        {displayName}\n      </Text>\n\n      {/* Count badge */}\n      <Text\n        size=\"xs\"\n        aria-label={`Count ${item.count}`}\n        className={cn(\n          'flex-shrink-0 h-[22px] px-2 flex items-center rounded',\n          COUNT_BADGE_CLASSES[variant]\n        )}\n      >\n        {countText}\n      </Text>\n\n      {/* Percentage badge with trend */}\n      <Text\n        size=\"xs\"\n        weight=\"bold\"\n        aria-label={`Performance ${item.percentage}%`}\n        className={cn(\n          'flex flex-row items-center flex-shrink-0 h-[22px] px-2 gap-1 rounded text-text',\n          PERCENTAGE_BADGE_CLASSES[variant]\n        )}\n      >\n        <TrendIcon trend={item.trend} variant={variant} />\n        {item.percentage}%\n      </Text>\n    </div>\n  );\n}\n\n/**\n * Render a single ranking item (handles null items)\n */\nfunction createRenderPerformanceItem(countLabel?: string) {\n  return function renderPerformanceItem(\n    item: PerformanceRankingItem | null,\n    variant: RankingVariant,\n    index: number\n  ) {\n    if (!item) {\n      return (\n        <div\n          key={`${variant}-empty-${index}`}\n          className=\"flex items-center justify-center w-full p-4 rounded-xl bg-background-50 border border-dashed border-border-100\"\n        >\n          <Text size=\"xs\" className=\"text-text-400\">\n            Sem dados\n          </Text>\n        </div>\n      );\n    }\n\n    return (\n      <PerformanceItemCard\n        key={`${variant}-${index}-${item.position}`}\n        item={item}\n        variant={variant}\n        countLabel={countLabel}\n      />\n    );\n  };\n}\n\n/**\n * PerformanceRanking component — displays two cards side by side showing\n * highlighted regions/municipalities/classes and those needing attention.\n *\n * Supports nullable items, per-item trend indicators, count badges,\n * and optional shift/grade info for class grouping.\n *\n * @example\n * ```tsx\n * <PerformanceRanking\n *   data={{\n *     groupedBy: 'state',\n *     highlighted: [\n *       { position: 1, name: 'SP', count: 150, percentage: 85, trend: 'up' },\n *       { position: 2, name: 'RJ', count: 120, percentage: 78, trend: 'down' },\n *       { position: 3, name: 'MG', count: 100, percentage: 72, trend: null },\n *     ],\n *     needsAttention: [\n *       { position: 1, name: 'BA', count: 30, percentage: 25, trend: 'down' },\n *       { position: 2, name: 'PE', count: 35, percentage: 28, trend: null },\n *       { position: 3, name: 'CE', count: 40, percentage: 32, trend: 'up' },\n *     ],\n *   }}\n * />\n * ```\n */\nexport const PerformanceRanking = ({\n  data,\n  highlightTitle = 'Em destaque',\n  attentionTitle = 'Precisando de atenção',\n  countLabel,\n  className,\n  ...props\n}: PerformanceRankingProps) => {\n  const renderItem = createRenderPerformanceItem(countLabel);\n\n  return (\n    <RankingLayout className={className} {...props}>\n      <BaseRankingCard\n        title={highlightTitle}\n        variant=\"highlight\"\n        items={data.highlighted}\n        renderItem={renderItem}\n        headerIcon={<MedalIcon size={14} className=\"text-text-950\" />}\n      />\n      <BaseRankingCard\n        title={attentionTitle}\n        variant=\"attention\"\n        items={data.needsAttention}\n        renderItem={renderItem}\n        headerIcon={<SealWarningIcon size={14} className=\"text-text\" />}\n      />\n    </RankingLayout>\n  );\n};\n\nexport default PerformanceRanking;\n"],"mappings":"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","names":[]}