{"version":3,"sources":["../src/utils/utils.ts","../src/utils/dropdown.ts","../src/utils/arraysEqual.ts","../src/utils/activityFilters.ts","../src/utils/questionTypeUtils.ts","../src/utils/formatScore.ts"],"sourcesContent":["import { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}\n\nexport { syncDropdownState } from './dropdown';\nexport {\n  getSelectedIdsFromCategories,\n  toggleArrayItem,\n  toggleSingleValue,\n  areFiltersEqual,\n} from './activityFilters';\nexport {\n  mapQuestionTypeToEnum,\n  mapQuestionTypeToEnumRequired,\n} from './questionTypeUtils';\nexport {\n  getStatusBadgeConfig,\n  formatTimeSpent,\n  formatQuestionNumbers,\n  formatDateToBrazilian,\n  formatActivityDateToBrazilian,\n} from './activityDetailsUtils';\n\n/**\n * Format a number as a rounded percentage string\n * @param value - Number to format (0-100)\n * @returns Formatted string with % suffix (e.g., \"72%\")\n */\nexport function formatPercentageRounded(value: number): string {\n  return `${Math.round(value)}%`;\n}\n\nexport { formatScore } from './formatScore';\n\n/**\n * Convert hex color to rgba with opacity for background\n * @param hex - Hex color (e.g., \"#4B0082\")\n * @param opacity - Opacity value (0-1)\n * @returns rgba string\n */\nexport function hexToRgba(hex: string, opacity: number): string {\n  const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n  if (!result) return `rgba(107, 114, 128, ${opacity})`; // fallback gray\n  const r = Number.parseInt(result[1], 16);\n  const g = Number.parseInt(result[2], 16);\n  const b = Number.parseInt(result[3], 16);\n  return `rgba(${r}, ${g}, ${b}, ${opacity})`;\n}\n\n/**\n * Maps Tailwind bg-* class to CSS variable\n * @param bgClass - Tailwind background class (e.g., \"bg-error-600\")\n * @returns CSS variable string (e.g., \"var(--color-error-600)\")\n */\nexport function bgClassToCssVar(bgClass: string): string {\n  return `var(--color-${bgClass.replace('bg-', '')})`;\n}\n\n/**\n * Converts polar coordinates to Cartesian for SVG arc path calculations.\n * Angles are in degrees, with 0° at the top (12 o'clock position).\n * @param cx - Center X coordinate\n * @param cy - Center Y coordinate\n * @param r - Radius\n * @param angleDeg - Angle in degrees\n * @returns Cartesian coordinates { x, y }\n */\nexport function polarToCartesian(\n  cx: number,\n  cy: number,\n  r: number,\n  angleDeg: number\n): { x: number; y: number } {\n  const rad = ((angleDeg - 90) * Math.PI) / 180;\n  return { x: cx + r * Math.cos(rad), y: cy + r * Math.sin(rad) };\n}\n\n/**\n * Generates an SVG filled arc (pie slice) path string.\n * @param cx - Center X coordinate\n * @param cy - Center Y coordinate\n * @param r - Radius\n * @param startAngle - Start angle in degrees\n * @param endAngle - End angle in degrees\n * @returns SVG path string for the arc\n */\nexport function describeArc(\n  cx: number,\n  cy: number,\n  r: number,\n  startAngle: number,\n  endAngle: number\n): string {\n  const span = endAngle - startAngle;\n\n  // For full circle (or near-full), use two arcs to avoid SVG arc degeneracy\n  if (span >= 359.99) {\n    const midAngle = startAngle + 180;\n    const s = polarToCartesian(cx, cy, r, startAngle);\n    const m = polarToCartesian(cx, cy, r, midAngle);\n    return `M ${cx} ${cy} L ${s.x} ${s.y} A ${r} ${r} 0 1 1 ${m.x} ${m.y} A ${r} ${r} 0 1 1 ${s.x} ${s.y} Z`;\n  }\n\n  const s = polarToCartesian(cx, cy, r, endAngle);\n  const e = polarToCartesian(cx, cy, r, startAngle);\n  const largeArc = span > 180 ? 1 : 0;\n  return `M ${cx} ${cy} L ${s.x} ${s.y} A ${r} ${r} 0 ${largeArc} 0 ${e.x} ${e.y} Z`;\n}\n\n/**\n * Retorna a cor hexadecimal com opacidade 0.3 (4d) se não estiver em dark mode.\n * Se estiver em dark mode, retorna a cor original.\n *\n * @param hexColor - Cor hexadecimal (ex: \"#0066b8\" ou \"0066b8\")\n * @param isDark - booleano indicando se está em dark mode\n * @returns string - cor hexadecimal com opacidade se necessário\n */\nexport function getSubjectColorWithOpacity(\n  hexColor: string | undefined,\n  isDark: boolean\n): string | undefined {\n  if (!hexColor) return undefined;\n  // Remove o '#' se existir\n  let color = hexColor.replace(/^#/, '').toLowerCase();\n\n  if (isDark) {\n    // Se está em dark mode, sempre remove opacidade se existir\n    if (color.length === 8) {\n      color = color.slice(0, 6);\n    }\n    return `#${color}`;\n  } else {\n    // Se não está em dark mode (light mode)\n    let resultColor: string;\n    if (color.length === 6) {\n      // Adiciona opacidade 0.3 (4D) para cores de 6 dígitos\n      resultColor = `#${color}4d`;\n    } else if (color.length === 8) {\n      // Já tem opacidade, retorna como está\n      resultColor = `#${color}`;\n    } else {\n      // Para outros tamanhos (3, 4, 5 dígitos), retorna como está\n      resultColor = `#${color}`;\n    }\n    return resultColor;\n  }\n}\n","import type { Dispatch, SetStateAction } from 'react';\n\n/**\n * Synchronizes dropdown state when it closes externally\n * This ensures the toggle button state matches the dropdown state\n *\n * @param open - Current dropdown open state\n * @param isActive - Current active state of the toggle button\n * @param setActiveStates - Function to update active states\n * @param key - Key identifier for the specific dropdown\n */\nexport const syncDropdownState = (\n  open: boolean,\n  isActive: boolean,\n  setActiveStates: Dispatch<SetStateAction<Record<string, boolean>>>,\n  key: string\n) => {\n  if (!open && isActive) {\n    setActiveStates((prev) => ({ ...prev, [key]: false }));\n  }\n};\n","/**\n * Compares two arrays for equality (order-independent)\n * @param a - First array\n * @param b - Second array\n * @param comparator - Optional comparator function. If not provided, uses string conversion and localeCompare\n * @returns true if arrays contain the same elements, false otherwise\n */\nexport function arraysEqual<T>(\n  a: T[],\n  b: T[],\n  comparator?: (x: T, y: T) => number\n): boolean {\n  if (a.length !== b.length) return false;\n\n  if (a.length === 0 && b.length === 0) return true;\n\n  if (comparator) {\n    const sortedA = [...a].sort(comparator);\n    const sortedB = [...b].sort(comparator);\n    return sortedA.every((val, index) => val === sortedB[index]);\n  }\n\n  const sortedA = [...a].sort((x, y) => String(x).localeCompare(String(y)));\n  const sortedB = [...b].sort((x, y) => String(x).localeCompare(String(y)));\n  return sortedA.every((val, index) => val === sortedB[index]);\n}\n","import type { CategoryConfig } from '../components/CheckBoxGroup/CheckBoxGroup';\nimport type { ActivityFiltersData } from '../types/activityFilters';\nimport { arraysEqual } from './arraysEqual';\n\n/**\n * Extracts selected IDs from knowledge categories by their keys\n * @param categories - Array of category configurations\n * @param keys - Object mapping output keys to category keys\n * @returns Object with extracted selected IDs for each output key\n */\nexport function getSelectedIdsFromCategories(\n  categories: CategoryConfig[],\n  keys: Record<string, string>\n): Record<string, string[]> {\n  const result: Record<string, string[]> = {};\n\n  for (const [outputKey, categoryKey] of Object.entries(keys)) {\n    const category = categories.find((c) => c.key === categoryKey);\n    result[outputKey] = category?.selectedIds || [];\n  }\n\n  return result;\n}\n\n/**\n * Toggles an item in an array (adds if not present, removes if present)\n * @param array - Current array\n * @param item - Item to toggle\n * @returns New array with item toggled\n */\nexport function toggleArrayItem<T>(array: T[], item: T): T[] {\n  return array.includes(item)\n    ? array.filter((i) => i !== item)\n    : [...array, item];\n}\n\n/**\n * Toggles a single value (returns null if current value, otherwise returns new value)\n * @param currentValue - Current selected value\n * @param newValue - Value to toggle to\n * @returns New value or null if toggling off\n */\nexport function toggleSingleValue<T>(\n  currentValue: T | null,\n  newValue: T\n): T | null {\n  return currentValue === newValue ? null : newValue;\n}\n\nexport function areFiltersEqual(\n  filters1: ActivityFiltersData | null,\n  filters2: ActivityFiltersData | null\n): boolean {\n  if (filters1 === filters2) return true;\n  if (!filters1 || !filters2) return false;\n\n  return (\n    arraysEqual(filters1.types, filters2.types) &&\n    arraysEqual(filters1.bankIds, filters2.bankIds) &&\n    arraysEqual(filters1.yearIds, filters2.yearIds) &&\n    arraysEqual(filters1.subjectIds, filters2.subjectIds) &&\n    arraysEqual(filters1.topicIds, filters2.topicIds) &&\n    arraysEqual(filters1.subtopicIds, filters2.subtopicIds) &&\n    arraysEqual(filters1.contentIds, filters2.contentIds)\n  );\n}\n\n/**\n * Type guard to check if an item has a valid id and a bankId within bankIds\n * @param item - The item to validate\n * @param bankIds - Array of valid bank IDs to check against\n * @returns True if item has valid id and bankId that matches bankIds\n */\nfunction isValidBankYearItem(\n  item: unknown,\n  bankIds: string[]\n): item is { id: string; bankId: string } {\n  return (\n    !!item &&\n    typeof (item as { id?: unknown }).id === 'string' &&\n    typeof (item as { bankId?: unknown }).bankId === 'string' &&\n    bankIds.includes((item as { bankId: string }).bankId)\n  );\n}\n\n/**\n * Derives year IDs from bank IDs when explicit year IDs are not provided\n * @param yearItens - Array of year items to filter\n * @param bankIds - Array of bank IDs to filter by\n * @param explicitYearIds - Explicitly provided year IDs (takes precedence)\n * @returns Array of year IDs\n */\nexport function deriveYearIdsFromBankIds(\n  yearItens: unknown[],\n  bankIds: string[],\n  explicitYearIds: string[]\n): string[] {\n  if (explicitYearIds.length > 0) {\n    return explicitYearIds;\n  }\n  return yearItens\n    .filter((item) => isValidBankYearItem(item, bankIds))\n    .map((item) => item.id);\n}\n\n/**\n * Builds the year IDs to send for a set of selected banks, handling mixed\n * selections: explicitly-selected years are retained for the banks that have\n * them, and every selected bank *without* an explicit year contributes all of\n * its available years (the backend filters only by bank-year, so a bank with no\n * year would otherwise match everything). The result is deduplicated.\n * @param yearItens - Array of year items (each with id/bankId)\n * @param bankIds - Array of selected bank IDs\n * @param explicitYearIds - Year IDs the user explicitly selected\n * @returns Deduplicated array of year IDs\n */\nexport function mergeYearIdsForSelectedBanks(\n  yearItens: unknown[],\n  bankIds: string[],\n  explicitYearIds: string[]\n): string[] {\n  const validYears = yearItens.filter((item) =>\n    isValidBankYearItem(item, bankIds)\n  );\n  const explicitSet = new Set(explicitYearIds);\n  const result = new Set<string>(explicitYearIds);\n\n  for (const bankId of bankIds) {\n    const yearsForBank = validYears.filter((year) => year.bankId === bankId);\n    const hasExplicitYear = yearsForBank.some((year) =>\n      explicitSet.has(year.id)\n    );\n    if (!hasExplicitYear) {\n      yearsForBank.forEach((year) => result.add(year.id));\n    }\n  }\n\n  return Array.from(result);\n}\n","import { QUESTION_TYPE } from '../components/Quiz/useQuizStore';\n\n/**\n * Maps API question type string to QUESTION_TYPE enum\n * Converts input to uppercase for case-insensitive matching\n *\n * @param type - Question type string from API\n * @param fallback - Optional fallback QUESTION_TYPE if mapping fails. If not provided, returns null\n * @returns QUESTION_TYPE enum value or null/fallback if not found\n */\nexport function mapQuestionTypeToEnum(\n  type: string,\n  fallback?: QUESTION_TYPE\n): QUESTION_TYPE | null {\n  const upperType = type.toUpperCase();\n\n  const typeMap: Record<string, QUESTION_TYPE> = {\n    ALTERNATIVA: QUESTION_TYPE.ALTERNATIVA,\n    DISSERTATIVA: QUESTION_TYPE.DISSERTATIVA,\n    MULTIPLA_ESCOLHA: QUESTION_TYPE.MULTIPLA_ESCOLHA,\n    VERDADEIRO_FALSO: QUESTION_TYPE.VERDADEIRO_FALSO,\n    IMAGEM: QUESTION_TYPE.IMAGEM,\n    RELACIONAR: QUESTION_TYPE.RELACIONAR,\n    PREENCHER_LACUNAS: QUESTION_TYPE.PREENCHER_LACUNAS,\n  };\n\n  return typeMap[upperType] ?? fallback ?? null;\n}\n\n/**\n * Maps API question type string to QUESTION_TYPE enum with required fallback\n * Always returns a QUESTION_TYPE (never null)\n *\n * @param type - Question type string from API\n * @param fallback - Fallback QUESTION_TYPE if mapping fails (defaults to ALTERNATIVA)\n * @returns QUESTION_TYPE enum value\n */\nexport function mapQuestionTypeToEnumRequired(\n  type: string,\n  fallback: QUESTION_TYPE = QUESTION_TYPE.ALTERNATIVA\n): QUESTION_TYPE {\n  return mapQuestionTypeToEnum(type, fallback) ?? fallback;\n}\n","import { ScoreType } from '../types/common';\n\n/**\n * Format score based on score type\n * @param value - Score value\n * @param scoreType - Score display enum\n * @returns Formatted score string\n */\nexport function formatScore(value: number, scoreType: ScoreType): string {\n  if (scoreType === ScoreType.TRI) {\n    return Math.round(value).toString();\n  }\n\n  return `${value.toFixed(1).replace('.', ',')}%`;\n}\n"],"mappings":"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","names":["sortedA","sortedB","s"]}