Added ZIP upload support

X-Lovable-Edit-ID: edt-7c9c8e31-2960-4964-a296-a5b115e765bc
Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com>
This commit is contained in:
gpt-engineer-app[bot]
2026-04-27 23:48:27 +00:00
co-authored by renee-png
4 changed files with 33 additions and 9 deletions
BIN
View File
Binary file not shown.
+1
View File
@@ -78,6 +78,7 @@
"input-otp": "^1.4.2",
"jspdf": "^4.2.1",
"jspdf-autotable": "^5.0.7",
"jszip": "^3.10.1",
"lucide-react": "^0.575.0",
"mailparser": "3.7.1",
"papaparse": "^5.5.3",
+32
View File
@@ -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;
-9
View File
@@ -1314,12 +1314,3 @@ const rootRouteChildren: RootRouteChildren = {
export const routeTree = rootRouteImport
._addFileChildren(rootRouteChildren)
._addFileTypes<FileRouteTypes>()
import type { getRouter } from './router.tsx'
import type { createStart } from '@tanstack/react-start'
declare module '@tanstack/react-start' {
interface Register {
ssr: true
router: Awaited<ReturnType<typeof getRouter>>
}
}