{"version":3,"file":"questionInsights.mjs","names":["FIELD_TYPE","Object","freeze","Hidden","SingleLineText","MultiLineText","Checkbox","RadioButton","DropdownSingleSelect","DropdownMultipleSelect","ListMultiSelect","DateSelector","TimeSelector","DateTimeSelector","FileUpload","YesNo","Signature","Tally","Number","Paragraph","ImageUpload","FormMetadataDisplay","Location","Table","DISPLAY_ONLY","Set","isDisplayOnly","fieldTypeId","has","FIELD_TYPE_NAME","FIELD_TYPE_ICON","getFieldTypeIcon","TYPE_FAMILIES","key","label","types","FAMILY_BY_TYPE","m","fam","t","getFamilyKey","tryParse","v","JSON","parse","isEmpty","raw","SUFFIX_RE","sectionName","RegExp","replace","readSlotValues","submission","questionName","data","formSubmission_Data","responseData","SubmissionResponseData","submissionResponseData","re","values","secKey","secValue","entries","test","slot","toLowerCase","Value","value","undefined","push","getOptionList","question","items","fieldProperties","Array","isArray","filter","i","map","display","String","o","length","aggregateChoice","options","counts","Map","answered","skipped","set","get","top","opt","val","count","find","sort","a","b","kind","viz","aggregateMultiChoice","parts","split","s","trim","Boolean","p","aggregateYesNo","_question","yes","no","formatNum","n","isInteger","toFixed","aggregateNumber","nums","isFinite","stat","sorted","min","max","sum","reduce","avg","percentile","idx","Math","floor","p50","p90","aggregateText","from","slice","tail","tailSum","c","bucketDate","d","yyyy","getFullYear","mm","getMonth","padStart","bucketHour","timeStr","match","h","isNaN","aggregateDate","Date","getTime","aggregateTime","aggregatePresence","getQuestionInsight","section","submissions","sub","name","reason"],"sources":["../../../../src/udp/pages/UdpQuestionFormOverviewPage/questionInsights.js"],"sourcesContent":["// Per-question insight aggregation for the form overview tabs.\n// Pure functions only — given a section + question definition and the list\n// of submissions returned from `/UdpFormWithSubmissionsView/search`, produce\n// a normalized `{ kind, ... }` shape the renderer can dispatch on.\n//\n// Backend stores `formSubmission_Data` as PascalCase JSON; the original copy\n// of a section uses its bare name (`section1`), repeatable-section copies\n// use suffixed keys (`section1_2`, `section1_3`, …). The aggregator walks\n// every copy so repeatable sections contribute all instances.\n\nexport const FIELD_TYPE = Object.freeze({\n  Hidden: 1,\n  SingleLineText: 2,\n  MultiLineText: 3,\n  Checkbox: 4,\n  RadioButton: 5,\n  DropdownSingleSelect: 6,\n  DropdownMultipleSelect: 7,\n  ListMultiSelect: 8,\n  DateSelector: 9,\n  TimeSelector: 10,\n  DateTimeSelector: 11,\n  FileUpload: 12,\n  YesNo: 13,\n  Signature: 14,\n  Tally: 15,\n  Number: 16,\n  Paragraph: 17,\n  ImageUpload: 18,\n  FormMetadataDisplay: 19,\n  Location: 20,\n  Table: 21,\n});\n\nconst DISPLAY_ONLY = new Set([\n  FIELD_TYPE.Hidden,\n  FIELD_TYPE.Paragraph,\n  FIELD_TYPE.FormMetadataDisplay,\n]);\nexport const isDisplayOnly = (fieldTypeId) => DISPLAY_ONLY.has(fieldTypeId);\n\nexport const FIELD_TYPE_NAME = {\n  [FIELD_TYPE.SingleLineText]: 'Text',\n  [FIELD_TYPE.MultiLineText]: 'Long text',\n  [FIELD_TYPE.Checkbox]: 'Checkbox',\n  [FIELD_TYPE.RadioButton]: 'Radio',\n  [FIELD_TYPE.DropdownSingleSelect]: 'Dropdown',\n  [FIELD_TYPE.DropdownMultipleSelect]: 'Multi dropdown',\n  [FIELD_TYPE.ListMultiSelect]: 'List',\n  [FIELD_TYPE.DateSelector]: 'Date',\n  [FIELD_TYPE.TimeSelector]: 'Time',\n  [FIELD_TYPE.DateTimeSelector]: 'Date & time',\n  [FIELD_TYPE.FileUpload]: 'File',\n  [FIELD_TYPE.YesNo]: 'Yes / No',\n  [FIELD_TYPE.Signature]: 'Signature',\n  [FIELD_TYPE.Tally]: 'Tally',\n  [FIELD_TYPE.Number]: 'Number',\n  [FIELD_TYPE.ImageUpload]: 'Image',\n  [FIELD_TYPE.Location]: 'Location',\n  [FIELD_TYPE.Table]: 'Table',\n};\n\n// Fluent icon name per field type — mirrors the builder's template registry\n// (builder/form-item-types/templates.ts) so the Form Structure rail here reads\n// the same as the builder's outline.\nexport const FIELD_TYPE_ICON = {\n  [FIELD_TYPE.SingleLineText]: 'text-font',\n  [FIELD_TYPE.MultiLineText]: 'text-paragraph',\n  [FIELD_TYPE.Checkbox]: 'checkbox-checked',\n  [FIELD_TYPE.RadioButton]: 'radio-button',\n  [FIELD_TYPE.DropdownSingleSelect]: 'chevron-down',\n  [FIELD_TYPE.DropdownMultipleSelect]: 'list',\n  [FIELD_TYPE.ListMultiSelect]: 'apps-list-detail',\n  [FIELD_TYPE.DateSelector]: 'calendar',\n  [FIELD_TYPE.TimeSelector]: 'clock',\n  [FIELD_TYPE.DateTimeSelector]: 'calendar-clock',\n  [FIELD_TYPE.FileUpload]: 'cloud-upload',\n  [FIELD_TYPE.YesNo]: 'checkmark',\n  [FIELD_TYPE.Signature]: 'document',\n  [FIELD_TYPE.Tally]: 'apps-list',\n  [FIELD_TYPE.Number]: 'number',\n  [FIELD_TYPE.ImageUpload]: 'cloud-upload',\n  [FIELD_TYPE.Location]: 'location',\n  [FIELD_TYPE.Table]: 'table',\n};\nexport const getFieldTypeIcon = (fieldTypeId) => FIELD_TYPE_ICON[fieldTypeId] ?? 'question';\n\n// Type families for the filter chips. Each family groups the field types that\n// share an analytics shape. Trimmed to the types our system actually has —\n// the mockup's star-rating / NPS families have no corresponding field type.\nexport const TYPE_FAMILIES = [\n  { key: 'text', label: 'Text', types: [FIELD_TYPE.SingleLineText, FIELD_TYPE.MultiLineText] },\n  { key: 'number', label: 'Number', types: [FIELD_TYPE.Number] },\n  {\n    key: 'choice',\n    label: 'Choice',\n    types: [\n      FIELD_TYPE.Checkbox,\n      FIELD_TYPE.RadioButton,\n      FIELD_TYPE.DropdownSingleSelect,\n      FIELD_TYPE.DropdownMultipleSelect,\n      FIELD_TYPE.ListMultiSelect,\n      FIELD_TYPE.YesNo,\n    ],\n  },\n  {\n    key: 'datetime',\n    label: 'Date & time',\n    types: [FIELD_TYPE.DateSelector, FIELD_TYPE.TimeSelector, FIELD_TYPE.DateTimeSelector],\n  },\n  { key: 'files', label: 'Files', types: [FIELD_TYPE.FileUpload, FIELD_TYPE.ImageUpload, FIELD_TYPE.Signature] },\n  { key: 'other', label: 'Other', types: [FIELD_TYPE.Location, FIELD_TYPE.Table, FIELD_TYPE.Tally] },\n];\n\nconst FAMILY_BY_TYPE = (() => {\n  const m = {};\n  for (const fam of TYPE_FAMILIES) for (const t of fam.types) m[t] = fam.key;\n  return m;\n})();\nexport const getFamilyKey = (fieldTypeId) => FAMILY_BY_TYPE[fieldTypeId] ?? 'other';\n\nconst tryParse = (v) => {\n  if (v == null) return null;\n  if (typeof v === 'object') return v;\n  if (typeof v !== 'string') return null;\n  try { return JSON.parse(v); } catch { return null; }\n};\n\nconst isEmpty = (raw) => raw == null || raw === '';\n\n// Read every wire value submitted for (sectionName, questionName) across\n// original + repeatable-section copies (`section1`, `section1_2`, ...).\nconst SUFFIX_RE = (sectionName) =>\n  new RegExp(`^${sectionName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}(?:_\\\\d+)?$`);\n\nconst readSlotValues = (submission, sectionName, questionName) => {\n  const data = tryParse(submission?.formSubmission_Data);\n  const responseData = data?.SubmissionResponseData ?? data?.submissionResponseData;\n  if (!responseData) return [];\n  const re = SUFFIX_RE(sectionName);\n  const values = [];\n  for (const [secKey, secValue] of Object.entries(responseData)) {\n    if (!re.test(secKey)) continue;\n    const slot = secValue?.[questionName] ?? secValue?.[questionName?.toLowerCase?.()];\n    const raw = slot?.Value ?? slot?.value;\n    if (raw === undefined) continue;\n    values.push(raw);\n  }\n  return values;\n};\n\nconst getOptionList = (question) => {\n  const items = question?.fieldProperties?.items;\n  if (!Array.isArray(items)) return [];\n  return items\n    .filter((i) => i && typeof i === 'object')\n    .map((i) => ({\n      display: String(i.display ?? i.value ?? ''),\n      value: String(i.value ?? i.display ?? ''),\n    }))\n    .filter((o) => o.display.length > 0 || o.value.length > 0);\n};\n\n// =======================================================================\n// Per-type aggregators. Each returns `{ kind, answered, skipped, ... }`.\n// The renderer dispatches on `kind`.\n// =======================================================================\n\nconst aggregateChoice = (question, values) => {\n  const options = getOptionList(question);\n  const counts = new Map();\n  let answered = 0;\n  let skipped = 0;\n  for (const v of values) {\n    if (isEmpty(v)) { skipped++; continue; }\n    answered++;\n    counts.set(v, (counts.get(v) ?? 0) + 1);\n  }\n  const top = [];\n  if (options.length > 0) {\n    for (const opt of options) {\n      top.push([opt.display, counts.get(opt.value) ?? 0]);\n    }\n    for (const [val, count] of counts.entries()) {\n      if (!options.find((o) => o.value === val)) top.push([val, count]);\n    }\n  } else {\n    for (const [val, count] of counts.entries()) top.push([val, count]);\n  }\n  top.sort((a, b) => b[1] - a[1]);\n  // Single-select → mutually exclusive answers → part-to-whole donut.\n  return { kind: 'top', viz: 'donut', answered, skipped, top };\n};\n\nconst aggregateMultiChoice = (question, values) => {\n  const options = getOptionList(question);\n  const counts = new Map();\n  let answered = 0;\n  let skipped = 0;\n  for (const raw of values) {\n    if (isEmpty(raw)) { skipped++; continue; }\n    answered++;\n    const parts = String(raw).split(',').map((s) => s.trim()).filter(Boolean);\n    for (const p of parts) counts.set(p, (counts.get(p) ?? 0) + 1);\n  }\n  const top = [];\n  if (options.length > 0) {\n    for (const opt of options) {\n      top.push([opt.display, counts.get(opt.value) ?? 0]);\n    }\n    for (const [val, count] of counts.entries()) {\n      if (!options.find((o) => o.value === val)) top.push([val, count]);\n    }\n  } else {\n    for (const [val, count] of counts.entries()) top.push([val, count]);\n  }\n  top.sort((a, b) => b[1] - a[1]);\n  // A submission can pick several → not part-to-whole → ranked horizontal bars.\n  return { kind: 'top', viz: 'bar-h', answered, skipped, top };\n};\n\nconst aggregateYesNo = (_question, values) => {\n  let yes = 0;\n  let no = 0;\n  let skipped = 0;\n  for (const v of values) {\n    if (v === 'true') yes++;\n    else if (v === 'false') no++;\n    else skipped++;\n  }\n  return {\n    kind: 'top',\n    viz: 'donut',\n    answered: yes + no,\n    skipped,\n    top: [\n      ['Yes', yes],\n      ['No', no],\n    ],\n  };\n};\n\nconst formatNum = (n) => (Number.isInteger(n) ? String(n) : n.toFixed(1));\n\nconst aggregateNumber = (_question, values) => {\n  const nums = [];\n  let skipped = 0;\n  for (const v of values) {\n    if (isEmpty(v)) { skipped++; continue; }\n    const n = Number(v);\n    if (Number.isFinite(n)) nums.push(n);\n  }\n  if (nums.length === 0) {\n    return { kind: 'stat', viz: 'stat', answered: 0, skipped, stat: null };\n  }\n  const sorted = [...nums].sort((a, b) => a - b);\n  const min = sorted[0];\n  const max = sorted[sorted.length - 1];\n  const sum = nums.reduce((a, b) => a + b, 0);\n  const avg = sum / nums.length;\n  const percentile = (p) => {\n    if (sorted.length === 1) return sorted[0];\n    const idx = Math.min(sorted.length - 1, Math.floor((sorted.length - 1) * p));\n    return sorted[idx];\n  };\n  return {\n    kind: 'stat',\n    viz: 'stat',\n    answered: nums.length,\n    skipped,\n    stat: {\n      avg: formatNum(avg),\n      min: formatNum(min),\n      max: formatNum(max),\n      p50: formatNum(percentile(0.5)),\n      p90: formatNum(percentile(0.9)),\n    },\n  };\n};\n\nconst aggregateText = (_question, values) => {\n  const counts = new Map();\n  let answered = 0;\n  let skipped = 0;\n  for (const v of values) {\n    if (isEmpty(v)) { skipped++; continue; }\n    answered++;\n    const key = String(v).trim();\n    counts.set(key, (counts.get(key) ?? 0) + 1);\n  }\n  // Top 5 most frequent answers; bucket the long tail as \"Other\".\n  const sorted = Array.from(counts.entries()).sort((a, b) => b[1] - a[1]);\n  const top = sorted.slice(0, 5);\n  const tail = sorted.slice(5);\n  if (tail.length > 0) {\n    const tailSum = tail.reduce((sum, [, c]) => sum + c, 0);\n    if (tailSum > 0) top.push(['Other', tailSum]);\n  }\n  // Free text → most-frequent answers ranked as horizontal bars.\n  return { kind: 'top', viz: 'bar-h', answered, skipped, top };\n};\n\n// Date / Time / DateTime: bin into a \"top\" shape so they reuse the bar\n// renderer. Granularity picked to stay readable in the per-question card.\nconst bucketDate = (d) => {\n  const yyyy = d.getFullYear();\n  const mm = String(d.getMonth() + 1).padStart(2, '0');\n  return `${yyyy}-${mm}`; // month bucket\n};\nconst bucketHour = (timeStr) => {\n  const m = String(timeStr).match(/^(\\d{1,2}):/);\n  if (!m) return null;\n  const h = Number(m[1]);\n  if (Number.isNaN(h) || h < 0 || h > 23) return null;\n  return `${String(h).padStart(2, '0')}:00`;\n};\n\nconst aggregateDate = (_question, values) => {\n  const counts = new Map();\n  let answered = 0;\n  let skipped = 0;\n  for (const v of values) {\n    if (isEmpty(v)) { skipped++; continue; }\n    const d = new Date(v);\n    if (Number.isNaN(d.getTime())) { skipped++; continue; }\n    answered++;\n    const key = bucketDate(d);\n    counts.set(key, (counts.get(key) ?? 0) + 1);\n  }\n  const top = Array.from(counts.entries()).sort((a, b) => (a[0] > b[0] ? 1 : -1));\n  // Chronological month buckets → filled trend over time.\n  return { kind: 'top', viz: 'area', answered, skipped, top };\n};\n\nconst aggregateTime = (_question, values) => {\n  const counts = new Map();\n  let answered = 0;\n  let skipped = 0;\n  for (const v of values) {\n    if (isEmpty(v)) { skipped++; continue; }\n    const key = bucketHour(v);\n    if (key == null) { skipped++; continue; }\n    answered++;\n    counts.set(key, (counts.get(key) ?? 0) + 1);\n  }\n  const top = Array.from(counts.entries()).sort((a, b) => (a[0] > b[0] ? 1 : -1));\n  // Chronological hour-of-day buckets → vertical bars.\n  return { kind: 'top', viz: 'bar-v', answered, skipped, top };\n};\n\n// Files / Images / Signature / Location / Table — just count which\n// submissions provided a value. The card renderer surfaces this as a\n// non-chart KPI plus a link affordance for the file types.\nconst aggregatePresence = (_question, values, kind = 'count') => {\n  let answered = 0;\n  let skipped = 0;\n  for (const v of values) {\n    if (isEmpty(v)) { skipped++; continue; }\n    answered++;\n  }\n  // Provided vs skipped → small completeness donut + a count/link affordance.\n  return { kind, viz: 'presence', answered, skipped };\n};\n\n// =======================================================================\n// Top-level dispatch\n// =======================================================================\n\nexport const getQuestionInsight = (section, question, submissions) => {\n  if (!section || !question) return null;\n  if (isDisplayOnly(question.fieldTypeId)) return null;\n\n  const values = [];\n  for (const sub of submissions ?? []) {\n    for (const v of readSlotValues(sub, section.name, question.name)) {\n      values.push(v);\n    }\n  }\n\n  switch (question.fieldTypeId) {\n    case FIELD_TYPE.YesNo:\n      return aggregateYesNo(question, values);\n    case FIELD_TYPE.Number:\n      return aggregateNumber(question, values);\n    case FIELD_TYPE.RadioButton:\n    case FIELD_TYPE.DropdownSingleSelect:\n      return aggregateChoice(question, values);\n    case FIELD_TYPE.Checkbox:\n    case FIELD_TYPE.DropdownMultipleSelect:\n    case FIELD_TYPE.ListMultiSelect:\n      return aggregateMultiChoice(question, values);\n    case FIELD_TYPE.DateSelector:\n    case FIELD_TYPE.DateTimeSelector:\n      return aggregateDate(question, values);\n    case FIELD_TYPE.TimeSelector:\n      return aggregateTime(question, values);\n    case FIELD_TYPE.SingleLineText:\n    case FIELD_TYPE.MultiLineText:\n      return aggregateText(question, values);\n    case FIELD_TYPE.FileUpload:\n    case FIELD_TYPE.ImageUpload:\n      return aggregatePresence(question, values, 'file');\n    case FIELD_TYPE.Signature:\n    case FIELD_TYPE.Location:\n    case FIELD_TYPE.Table:\n      return aggregatePresence(question, values, 'count');\n    case FIELD_TYPE.Tally:\n      return { kind: 'unsupported', viz: 'message', reason: 'Tally is computed live — no aggregate.' };\n    default:\n      return { kind: 'unsupported', viz: 'message', reason: 'No insight available for this field type.' };\n  }\n};\n"],"mappings":"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"}