From 46b6e28f14621091c02dc93480afd790d861f47e Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 23:47:39 +0000 Subject: [PATCH] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/components/cases/documents-tab.tsx | 32 ++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/components/cases/documents-tab.tsx b/src/components/cases/documents-tab.tsx index 97e0025..1e105b7 100644 --- a/src/components/cases/documents-tab.tsx +++ b/src/components/cases/documents-tab.tsx @@ -28,6 +28,7 @@ import { DialogTitle, } from "@/components/ui/dialog"; import { ShareDocumentDialog } from "./share-document-dialog"; +import JSZip from "jszip"; const MAX_BYTES = 150 * 1024 * 1024; @@ -135,6 +136,37 @@ export function CaseDocumentsTab({ caseId }: { caseId: string }) { const list = Array.from(files); let ok = 0; for (const f of list) { + // Auto-expand ZIP files into folders/files + if (/\.zip$/i.test(f.name) || f.type === "application/zip" || f.type === "application/x-zip-compressed") { + try { + const zip = await JSZip.loadAsync(await f.arrayBuffer()); + const zipRootName = sanitizeName(f.name.replace(/\.zip$/i, "")); + const zipRoot = baseFolder ? `${baseFolder}/${zipRootName}` : zipRootName; + await ensureFolder(zipRoot); + const entries = Object.values(zip.files); + for (const entry of entries) { + // Skip macOS metadata noise + if (/(^|\/)__MACOSX\//.test(entry.name) || /(^|\/)\.DS_Store$/.test(entry.name)) continue; + const parts = entry.name.split("/").filter(Boolean); + if (entry.dir) { + const sub = parts.map(sanitizeName).join("/"); + if (sub) await ensureFolder(`${zipRoot}/${sub}`); + continue; + } + const fname = parts.pop() || "file"; + const sub = parts.map(sanitizeName).join("/"); + const folderForFile = sub ? `${zipRoot}/${sub}` : zipRoot; + if (sub) await ensureFolder(folderForFile); + const blob = await entry.async("blob"); + const file = new File([blob], fname, { type: blob.type || "application/octet-stream" }); + const success = await uploadFile(file, folderForFile); + if (success) ok++; + } + } catch (err: any) { + toast.error(`${f.name}: could not unzip`, { description: err?.message }); + } + continue; + } // webkitRelativePath supports folder uploads when input has webkitdirectory const rel: string = (f as File & { webkitRelativePath?: string }).webkitRelativePath || ""; let folderForFile = baseFolder;