{"version":3,"file":"SubmissionAttachmentsDrawer.mjs","names":["React","useEffect","useState","useTranslation","UdpDrawer","UdpList","UdpListItem","UdpText","UdpIconButton","UdpSpinner","UdpFlexbox","ConfigService","apiGet","drawerBodyStyle","padding","decodeName","encoded","decodeURIComponent","parseFileToken","token","trimmed","trim","pipeIdx","indexOf","dataRef","slice","startsWith","driveFileId","name","extractAttachments","raw","responses","data","submissionResponseData","found","sectionKey","sectionResponses","Object","entries","questionKey","response","value","includes","split","parsed","push","slot","IMAGE_EXTS","Set","iconForFile","ext","pop","toLowerCase","has","SubmissionAttachmentsDrawer","t0","$","_c","open","submissionId","onClose","t","loading","setLoading","t1","Symbol","for","attachments","setAttachments","errorMessage","setErrorMessage","t2","t3","cancelled","productV1ApiUrl","then","catch","err","console","error","defaultValue","finally","handleDownload","_temp","t4","t5","t6","t7","length","t8","map","att","t9","t10","fileName","blob","tenantV1ApiUrl","responseType","objectUrl","URL","createObjectURL","a","document","createElement","href","download","body","appendChild","click","remove","setTimeout","revokeObjectURL"],"sources":["../../../../src/udp/pages/UdpQuestionFormOverviewPage/SubmissionAttachmentsDrawer.jsx"],"sourcesContent":["import React, { useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n  UdpDrawer,\n  UdpList,\n  UdpListItem,\n  UdpText,\n  UdpIconButton,\n  UdpSpinner,\n  UdpFlexbox,\n} from '../../../UI/fluent-web-components';\nimport { ConfigService } from '../../../configService';\nimport { apiGet } from '../../../utilities/apiClient';\n\nconst drawerBodyStyle = { padding: 16 };\n\nconst decodeName = (encoded) => {\n  try {\n    return decodeURIComponent(encoded);\n  } catch {\n    return encoded;\n  }\n};\n\n// Parse one `<urlencoded-name>|udp:<guid>` token. Returns null when the token\n// has no drive id (a pending/local upload that isn't persisted yet — won't\n// appear on a saved submission anyway).\nconst parseFileToken = (token) => {\n  const trimmed = token?.trim();\n  if (!trimmed) return null;\n  const pipeIdx = trimmed.indexOf('|');\n  if (pipeIdx < 0) return null;\n  const dataRef = trimmed.slice(pipeIdx + 1);\n  if (!dataRef.startsWith('udp:')) return null;\n  const driveFileId = dataRef.slice(4);\n  if (!driveFileId) return null;\n  return { name: decodeName(trimmed.slice(0, pipeIdx)), driveFileId };\n};\n\n// Walks the submission's wire response data and extracts every (name,\n// driveFileId) it finds. Detection is by token shape so we don't need the form\n// schema — covers file uploads (comma-joined tokens), image uploads (same\n// shape), and signatures (single token).\nconst extractAttachments = (raw) => {\n  const responses = raw?.data?.submissionResponseData ?? {};\n  const found = [];\n  for (const [sectionKey, sectionResponses] of Object.entries(responses)) {\n    for (const [questionKey, response] of Object.entries(sectionResponses)) {\n      const value = response?.value;\n      if (typeof value !== 'string' || !value.includes('|udp:')) continue;\n      for (const token of value.split(',')) {\n        const parsed = parseFileToken(token);\n        if (parsed) {\n          found.push({ ...parsed, slot: `${sectionKey}.${questionKey}` });\n        }\n      }\n    }\n  }\n  return found;\n};\n\nconst IMAGE_EXTS = new Set([\n  'png',\n  'jpg',\n  'jpeg',\n  'gif',\n  'webp',\n  'bmp',\n  'svg',\n  'heic',\n]);\n\nconst iconForFile = (name) => {\n  const ext = name.split('.').pop()?.toLowerCase();\n  return ext && IMAGE_EXTS.has(ext) ? 'image' : 'attach';\n};\n\nexport const SubmissionAttachmentsDrawer = ({ open, submissionId, onClose }) => {\n  const { t } = useTranslation();\n  const [loading, setLoading] = useState(false);\n  const [attachments, setAttachments] = useState([]);\n  const [errorMessage, setErrorMessage] = useState(null);\n\n  useEffect(() => {\n    if (!open || !submissionId) return undefined;\n    let cancelled = false;\n    setLoading(true);\n    setErrorMessage(null);\n    setAttachments([]);\n    apiGet(ConfigService.productV1ApiUrl, `UdpFormSubmission/${submissionId}/Full`)\n      .then((data) => {\n        if (cancelled) return;\n        setAttachments(extractAttachments(data));\n      })\n      .catch((err) => {\n        if (cancelled) return;\n        console.error('Failed to load submission attachments', err);\n        setErrorMessage(\n          t('formOverview.attachments.loadFailed', { defaultValue: 'Failed to load attachments.' })\n        );\n      })\n      .finally(() => {\n        if (!cancelled) setLoading(false);\n      });\n    return () => {\n      cancelled = true;\n    };\n  }, [open, submissionId, t]);\n\n  const handleDownload = async (driveFileId, fileName) => {\n    try {\n      const blob = await apiGet(\n        ConfigService.tenantV1ApiUrl,\n        `UdpDrive/${driveFileId}/stream`,\n        { responseType: 'blob' }\n      );\n      const objectUrl = URL.createObjectURL(blob);\n      const a = document.createElement('a');\n      a.href = objectUrl;\n      a.download = fileName;\n      document.body.appendChild(a);\n      a.click();\n      a.remove();\n      setTimeout(() => URL.revokeObjectURL(objectUrl), 1000);\n    } catch (err) {\n      console.error('Failed to download attachment', err);\n    }\n  };\n\n  return (\n    <UdpDrawer\n      drawerTitle={t('formOverview.attachments.title', { defaultValue: 'Submission Attachments' })}\n      open={open}\n      onDrawerClose={onClose}\n      size='medium'\n    >\n      <div style={drawerBodyStyle}>\n        {loading && (\n          <UdpFlexbox direction='row' align='center' gap='sm'>\n            <UdpSpinner size='small' />\n            <UdpText variant='caption1'>{t('formOverview.attachments.loading', { defaultValue: 'Loading attachments…' })}</UdpText>\n          </UdpFlexbox>\n        )}\n        {!loading && errorMessage && (\n          <UdpText variant='body1'>{errorMessage}</UdpText>\n        )}\n        {!loading && !errorMessage && attachments.length === 0 && (\n          <UdpText variant='body1'>{t('formOverview.attachments.none', { defaultValue: 'No attachments on this submission.' })}</UdpText>\n        )}\n        {!loading && !errorMessage && attachments.length > 0 && (\n          <UdpList showDivider>\n            {attachments.map((att) => (\n              <UdpListItem\n                key={`${att.slot}:${att.driveFileId}`}\n                value={att.driveFileId}\n                startIconName={iconForFile(att.name)}\n                label={att.name}\n                subtitle={att.slot}\n              >\n                <UdpIconButton\n                  slot='end'\n                  size='medium'\n                  appearance='transparent'\n                  fillOnHover\n                  iconName='download'\n                  title={t('common.download', { defaultValue: 'Download' })}\n                  onClick={() => handleDownload(att.driveFileId, att.name)}\n                />\n              </UdpListItem>\n            ))}\n          </UdpList>\n        )}\n      </div>\n    </UdpDrawer>\n  );\n};\n\nexport default SubmissionAttachmentsDrawer;\n"],"mappings":"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"}