summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.env.development4
-rw-r--r--.env.production4
-rw-r--r--.gitignore1
-rw-r--r--components/form-data/form-data-report-batch-dialog.tsx307
-rw-r--r--components/form-data/form-data-report-dialog.tsx2
-rw-r--r--components/form-data/form-data-table.tsx23
-rw-r--r--db/migrations/meta/_journal.json2
-rw-r--r--package-lock.json445
-rw-r--r--package.json3
-rw-r--r--pages/api/pdftron/createVendorDataReports.ts36
10 files changed, 822 insertions, 5 deletions
diff --git a/.env.development b/.env.development
index 435884dd..183c6f93 100644
--- a/.env.development
+++ b/.env.development
@@ -10,7 +10,9 @@ NEXT_PUBLIC_MUI_KEY=da30586e1f20b93856a9783012fc9258Tz04ODI0MyxFPTE3NDQ0NTM2Nzgw
NEXT_PUBLIC_URL=http://3.36.56.124:3000
NEXT_PUBLIC_BASE_URL=http://3.36.56.124:3001
- NEXT_PUBLIC_PDFTRON_WEBVIEW_KEY=demo:1739264618684:616161d7030000000091db1c97c6f386d41d3506ab5b507381ef2ee2bd
+# PDFTRON KEYS
+NEXT_PUBLIC_PDFTRON_WEBVIEW_KEY=demo:1739264618684:616161d7030000000091db1c97c6f386d41d3506ab5b507381ef2ee2bd
+NEXT_PUBLIC_PDFTRON_SERVER_KEY=demo:1740034881027:6175a0fc0300000000f155d153480e5ba091f17922a109cbd7cf6e40b3
# 기간계 시스템 연동 설정
ERP_API_URL=https://erp.example.com/api/vendors
diff --git a/.env.production b/.env.production
index 997653c5..1ada78ec 100644
--- a/.env.production
+++ b/.env.production
@@ -10,7 +10,9 @@ NEXT_PUBLIC_MUI_KEY=da30586e1f20b93856a9783012fc9258Tz04ODI0MyxFPTE3NDQ0NTM2Nzgw
NEXT_PUBLIC_URL=https://evcp.dtsolution.io
NEXT_PUBLIC_BASE_URL=https://evcp.dtsolution.io
- NEXT_PUBLIC_PDFTRON_WEBVIEW_KEY=demo:1739264618684:616161d7030000000091db1c97c6f386d41d3506ab5b507381ef2ee2bd
+# PDFTRON KEYS
+NEXT_PUBLIC_PDFTRON_WEBVIEW_KEY=demo:1739264618684:616161d7030000000091db1c97c6f386d41d3506ab5b507381ef2ee2bd
+NEXT_PUBLIC_PDFTRON_SERVER_KEY=demo:1740034881027:6175a0fc0300000000f155d153480e5ba091f17922a109cbd7cf6e40b3
# 기간계 시스템 연동 설정
ERP_API_URL=https://erp.example.com/api/vendors
diff --git a/.gitignore b/.gitignore
index 7a6dfa0e..4aa665ad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -51,6 +51,7 @@ next-env.d.ts
/public/uploads
/public/vendors
/public/profiles
+/public/vendorFormData
# 직접 참조가 불가능해 복사가 필요했던 라이브러리 (pdftrone)
# node_modules/@pdftron/public 경로에서 core 및 ui 경로를 복사해 사용
diff --git a/components/form-data/form-data-report-batch-dialog.tsx b/components/form-data/form-data-report-batch-dialog.tsx
new file mode 100644
index 00000000..e3fd7ea2
--- /dev/null
+++ b/components/form-data/form-data-report-batch-dialog.tsx
@@ -0,0 +1,307 @@
+"use client";
+
+import React, {
+ FC,
+ Dispatch,
+ SetStateAction,
+ useState,
+ useEffect,
+ useRef,
+} from "react";
+import { useToast } from "@/hooks/use-toast";
+import prettyBytes from "pretty-bytes";
+import { X, Loader2 } from "lucide-react";
+import { Badge } from "@/components/ui/badge";
+import {
+ Dialog,
+ DialogContent,
+ DialogHeader,
+ DialogTitle,
+ DialogDescription,
+ DialogFooter,
+} from "@/components/ui/dialog";
+import { ScrollArea } from "@/components/ui/scroll-area";
+import { Label } from "@/components/ui/label";
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/components/ui/select";
+import {
+ Dropzone,
+ DropzoneDescription,
+ DropzoneInput,
+ DropzoneTitle,
+ DropzoneUploadIcon,
+ DropzoneZone,
+} from "@/components/ui/dropzone";
+import {
+ FileList,
+ FileListAction,
+ FileListDescription,
+ FileListHeader,
+ FileListIcon,
+ FileListInfo,
+ FileListItem,
+ FileListName,
+} from "@/components/ui/file-list";
+import { Button } from "@/components/ui/button";
+import { getReportTempList } from "@/lib/forms/services";
+import { DataTableColumnJSON } from "./form-data-table-columns";
+
+const MAX_FILE_SIZE = 3000000;
+
+type ReportData = {
+ [key: string]: any;
+};
+
+interface tempFile {
+ fileName: string;
+ filePath: string;
+}
+
+interface FormDataReportBatchDialogProps {
+ open: boolean;
+ setOpen: Dispatch<SetStateAction<boolean>>;
+ columnsJSON: DataTableColumnJSON[];
+ reportData: ReportData[];
+ packageId: number;
+ formId: number;
+ formCode: string;
+}
+
+export const FormDataReportBatchDialog: FC<FormDataReportBatchDialogProps> = ({
+ open,
+ setOpen,
+ columnsJSON,
+ reportData,
+ packageId,
+ formId,
+ formCode,
+}) => {
+ const { toast } = useToast();
+ const [tempList, setTempList] = useState<tempFile[]>([]);
+ const [selectTemp, setSelectTemp] = useState<string>("");
+ const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
+ const [isUploading, setIsUploading] = useState(false);
+
+ useEffect(() => {
+ updateReportTempList(packageId, formId, setTempList);
+ }, [packageId, formId]);
+
+ const onClose = () => {
+ if (isUploading) {
+ return;
+ }
+ setOpen(false);
+ };
+
+ // 드롭존 - 파일 드랍 처리
+ const handleDropAccepted = (acceptedFiles: File[]) => {
+ const newFiles = [...acceptedFiles];
+ setSelectedFiles(newFiles);
+ };
+
+ // 드롭존 - 파일 거부(에러) 처리
+ const handleDropRejected = (fileRejections: any[]) => {
+ fileRejections.forEach((rejection) => {
+ toast({
+ variant: "destructive",
+ title: "File Error",
+ description: `${rejection.file.name}: ${
+ rejection.errors[0]?.message || "Upload failed"
+ }`,
+ });
+ });
+ };
+
+ // 파일 제거 핸들러
+ const removeFile = (index: number) => {
+ const updatedFiles = [...selectedFiles];
+ updatedFiles.splice(index, 1);
+ setSelectedFiles(updatedFiles);
+ };
+
+ const submitData = async () => {
+ setIsUploading(true);
+
+ try {
+ const totalFiles = selectedFiles.length;
+ let successCount = 0;
+
+ for (let i = 0; i < totalFiles; i++) {
+ const file = selectedFiles[i];
+
+ const formData = new FormData();
+ formData.append("file", file);
+ formData.append("customFileName", file.name);
+
+ // await uploadReportTemp(packageId, formId, formData);
+
+ successCount++;
+ }
+ } catch (err) {
+ console.error(err);
+ toast({
+ title: "Error",
+ description: "파일 업로드 중 오류가 발생했습니다.",
+ variant: "destructive",
+ });
+ } finally {
+ setIsUploading(false);
+ setOpen(false);
+ }
+ };
+
+ return (
+ <Dialog open={open} onOpenChange={onClose}>
+ <DialogContent className="w-[600px]" style={{ maxWidth: "none" }}>
+ <DialogHeader>
+ <DialogTitle>Batch Report Download</DialogTitle>
+ <DialogDescription>
+ Report Template을 선택하신 후 갑지를 업로드하여 주시기 바랍니다.
+ </DialogDescription>
+ </DialogHeader>
+ <div className="h-[60px]">
+ <Label>Report Template Select</Label>
+ <Select value={selectTemp} onValueChange={setSelectTemp}>
+ <SelectTrigger className="w-[100%]">
+ <SelectValue placeholder="사용하시고자하는 Report Template를 선택하여 주시기 바랍니다." />
+ </SelectTrigger>
+ <SelectContent>
+ {tempList.map((c) => {
+ const { fileName, filePath } = c;
+
+ return (
+ <SelectItem key={filePath} value={filePath}>
+ {fileName}
+ </SelectItem>
+ );
+ })}
+ </SelectContent>
+ </Select>
+ </div>
+ <div>
+ <Label>Report Cover Page Upload</Label>
+ <Dropzone
+ maxSize={MAX_FILE_SIZE}
+ multiple={false}
+ accept={{ accept: [".docx"] }}
+ onDropAccepted={handleDropAccepted}
+ onDropRejected={handleDropRejected}
+ disabled={isUploading}
+ >
+ {({ maxSize }) => (
+ <>
+ <DropzoneZone className="flex justify-center">
+ <DropzoneInput />
+ <div className="flex items-center gap-6">
+ <DropzoneUploadIcon />
+ <div className="grid gap-0.5">
+ <DropzoneTitle>파일을 여기에 드롭하세요</DropzoneTitle>
+ <DropzoneDescription>
+ 또는 클릭하여 파일을 선택하세요. 최대 크기:{" "}
+ {maxSize ? prettyBytes(maxSize) : "무제한"}
+ </DropzoneDescription>
+ </div>
+ </div>
+ </DropzoneZone>
+ <Label className="text-xs text-muted-foreground">
+ 여러 파일을 선택할 수 있습니다.
+ </Label>
+ </>
+ )}
+ </Dropzone>
+ </div>
+
+ {selectedFiles.length > 0 && (
+ <div className="grid gap-2">
+ <div className="flex items-center justify-between">
+ <h6 className="text-sm font-semibold">
+ 선택된 파일 ({selectedFiles.length})
+ </h6>
+ <Badge variant="secondary">{selectedFiles.length}개 파일</Badge>
+ </div>
+ <ScrollArea>
+ <UploadFileItem
+ selectedFiles={selectedFiles}
+ removeFile={removeFile}
+ isUploading={isUploading}
+ />
+ </ScrollArea>
+ </div>
+ )}
+
+ <DialogFooter>
+ <Button
+ disabled={selectedFiles.length === 0 || selectTemp.length === 0}
+ onClick={submitData}
+ >
+ 다운로드
+ </Button>
+ </DialogFooter>
+ </DialogContent>
+ </Dialog>
+ );
+};
+
+interface UploadFileItemProps {
+ selectedFiles: File[];
+ removeFile: (index: number) => void;
+ isUploading: boolean;
+}
+
+const UploadFileItem: FC<UploadFileItemProps> = ({
+ selectedFiles,
+ removeFile,
+ isUploading,
+}) => {
+ return (
+ <FileList className="max-h-[200px] gap-3">
+ {selectedFiles.map((file, index) => (
+ <FileListItem key={index} className="p-3">
+ <FileListHeader>
+ <FileListIcon />
+ <FileListInfo>
+ <FileListName>{file.name}</FileListName>
+ <FileListDescription>
+ {prettyBytes(file.size)}
+ </FileListDescription>
+ </FileListInfo>
+ <FileListAction
+ onClick={() => removeFile(index)}
+ disabled={isUploading}
+ >
+ <X className="h-4 w-4" />
+ <span className="sr-only">Remove</span>
+ </FileListAction>
+ </FileListHeader>
+ </FileListItem>
+ ))}
+ </FileList>
+ );
+};
+
+type UpdateReportTempList = (
+ packageId: number,
+ formId: number,
+ setPrevReportTemp: Dispatch<SetStateAction<tempFile[]>>
+) => void;
+
+const updateReportTempList: UpdateReportTempList = async (
+ packageId,
+ formId,
+ setTempList
+) => {
+ const tempList = await getReportTempList(packageId, formId);
+
+ setTempList(
+ tempList.map((c) => {
+ const { fileName, filePath } = c;
+ return { fileName, filePath };
+ })
+ );
+};
diff --git a/components/form-data/form-data-report-dialog.tsx b/components/form-data/form-data-report-dialog.tsx
index 5ddc5e0c..deb0873b 100644
--- a/components/form-data/form-data-report-dialog.tsx
+++ b/components/form-data/form-data-report-dialog.tsx
@@ -348,7 +348,7 @@ const importReportData: ImportReportData = async (
const objKey = label.split(" ").join("_");
- reportValueMapping[objKey] = reportValue[key];
+ reportValueMapping[objKey] = reportValue?.[key] ?? "";
});
const doc = await createDocument(reportFileBlob, {
diff --git a/components/form-data/form-data-table.tsx b/components/form-data/form-data-table.tsx
index e3c5af8f..9feaf3b2 100644
--- a/components/form-data/form-data-table.tsx
+++ b/components/form-data/form-data-table.tsx
@@ -23,6 +23,7 @@ import ExcelJS from "exceljs";
import { saveAs } from "file-saver";
import { FormDataReportTempUploadDialog } from "./form-data-report-temp-upload-dialog";
import { FormDataReportDialog } from "./form-data-report-dialog";
+import { FormDataReportBatchDialog } from "./form-data-report-batch-dialog";
interface GenericData {
[key: string]: any;
@@ -57,6 +58,7 @@ export default function DynamicTable({
const [isSaving, setIsSaving] = React.useState(false);
const [tempUpDialog, setTempUpDialog] = React.useState(false);
const [reportData, setReportData] = React.useState<GenericData[]>([]);
+ const [batchDownDialog, setBatchDownDialog] = React.useState(false);
// Reference to the table instance
const tableRef = React.useRef(null);
@@ -527,6 +529,13 @@ export default function DynamicTable({
<Button
variant="default"
size="sm"
+ onClick={() => setBatchDownDialog(true)}
+ >
+ Report Batch
+ </Button>
+ <Button
+ variant="default"
+ size="sm"
onClick={() => setTempUpDialog(true)}
>
Temp Upload
@@ -621,6 +630,20 @@ export default function DynamicTable({
formId={formId}
/>
)}
+
+ {batchDownDialog && (
+ <FormDataReportBatchDialog
+ open={batchDownDialog}
+ setOpen={setBatchDownDialog}
+ columnsJSON={columnsJSON}
+ reportData={tableData}
+ packageId={contractItemId}
+ formCode={formCode}
+ formId={formId}
+ />
+ )}
</>
);
}
+
+
diff --git a/db/migrations/meta/_journal.json b/db/migrations/meta/_journal.json
index a84b0a28..f2725ef7 100644
--- a/db/migrations/meta/_journal.json
+++ b/db/migrations/meta/_journal.json
@@ -659,6 +659,6 @@
"when": 1742834014376,
"tag": "0093_young_the_hunter",
"breakpoints": true
- }
+ }
]
} \ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index e0a4ffee..d41582f4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -18,6 +18,7 @@
"@mui/material": "^6.2.1",
"@mui/x-data-grid-premium": "^7.23.3",
"@mui/x-tree-view": "^7.23.6",
+ "@pdftron/pdfnet-node": "^11.3.0",
"@pdftron/webviewer": "^11.3.0",
"@radix-ui/primitive": "^1.1.1",
"@radix-ui/react-accordion": "^1.2.2",
@@ -52,6 +53,7 @@
"@t3-oss/env-nextjs": "^0.11.1",
"@tanstack/react-table": "^8.20.6",
"@types/docusign-esign": "^5.19.8",
+ "@types/formidable": "^3.4.5",
"accept-language": "^3.0.20",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
@@ -63,6 +65,7 @@
"embla-carousel-react": "^8.5.1",
"exceljs": "^4.4.0",
"file-saver": "^2.0.5",
+ "formidable": "^3.5.2",
"handlebars": "^4.7.8",
"i18n-iso-countries": "^7.13.0",
"i18next": "^24.1.2",
@@ -2122,6 +2125,60 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@mapbox/node-pre-gyp": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
+ "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==",
+ "dependencies": {
+ "detect-libc": "^2.0.0",
+ "https-proxy-agent": "^5.0.0",
+ "make-dir": "^3.1.0",
+ "node-fetch": "^2.6.7",
+ "nopt": "^5.0.0",
+ "npmlog": "^5.0.1",
+ "rimraf": "^3.0.2",
+ "semver": "^7.3.5",
+ "tar": "^6.1.11"
+ },
+ "bin": {
+ "node-pre-gyp": "bin/node-pre-gyp"
+ }
+ },
+ "node_modules/@mapbox/node-pre-gyp/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@mapbox/node-pre-gyp/node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "deprecated": "Rimraf versions prior to v4 are no longer supported",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/@mui/core-downloads-tracker": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.2.1.tgz",
@@ -2741,6 +2798,20 @@
"url": "https://github.com/sponsors/panva"
}
},
+ "node_modules/@pdftron/pdfnet-node": {
+ "version": "11.3.0",
+ "resolved": "https://registry.npmjs.org/@pdftron/pdfnet-node/-/pdfnet-node-11.3.0.tgz",
+ "integrity": "sha512-FhZD9Z6S/m6VUV23fFc2wtCOt50taV78rbM01+dotlb1FXu87el470EZ1SnRbdcCWegk16IfGeLIGKCuSn+oOw==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@mapbox/node-pre-gyp": "^1.0.10",
+ "underscore": "^1.13.6",
+ "xhr2": "^0.2.1"
+ },
+ "engines": {
+ "node": ">=8 <=22"
+ }
+ },
"node_modules/@pdftron/webviewer": {
"version": "11.3.0",
"resolved": "https://registry.npmjs.org/@pdftron/webviewer/-/webviewer-11.3.0.tgz",
@@ -4303,6 +4374,14 @@
"integrity": "sha512-xrCYOdHh5zA3LUrn6CvspYwlzSWxPso11Lx32WnAG6KvLCRecKZ/Rh21PLXUkzUFsQmrGcx/traJAFjR6dVS5Q==",
"license": "MIT"
},
+ "node_modules/@types/formidable": {
+ "version": "3.4.5",
+ "resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-3.4.5.tgz",
+ "integrity": "sha512-s7YPsNVfnsng5L8sKnG/Gbb2tiwwJTY1conOkJzTMRvJAlLFW1nEua+ADsJQu8N1c0oTHx9+d5nqg10WuT9gHQ==",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/hoist-non-react-statics": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz",
@@ -4706,6 +4785,11 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
+ "node_modules/abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
+ },
"node_modules/accept-language": {
"version": "3.0.20",
"resolved": "https://registry.npmjs.org/accept-language/-/accept-language-3.0.20.tgz",
@@ -4751,6 +4835,17 @@
"node": ">=0.4.0"
}
},
+ "node_modules/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -4814,6 +4909,11 @@
"node": ">= 8"
}
},
+ "node_modules/aproba": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
+ "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ=="
+ },
"node_modules/archiver": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz",
@@ -4910,6 +5010,19 @@
"safe-buffer": "~5.1.0"
}
},
+ "node_modules/are-we-there-yet": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
+ "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
+ "deprecated": "This package is no longer supported.",
+ "dependencies": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^3.6.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/arg": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
@@ -5102,6 +5215,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="
+ },
"node_modules/ast-types-flow": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
@@ -5544,6 +5662,14 @@
"node": ">= 6"
}
},
+ "node_modules/chownr": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/class-variance-authority": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
@@ -5630,6 +5756,14 @@
"simple-swizzle": "^0.2.2"
}
},
+ "node_modules/color-support": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
+ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
+ "bin": {
+ "color-support": "bin.js"
+ }
+ },
"node_modules/colorette": {
"version": "2.0.20",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
@@ -5678,6 +5812,11 @@
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"license": "MIT"
},
+ "node_modules/console-control-strings": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+ "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="
+ },
"node_modules/convert-source-map": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
@@ -6099,12 +6238,16 @@
"node": ">=0.4.0"
}
},
+ "node_modules/delegates": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="
+ },
"node_modules/detect-libc": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
"integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
"license": "Apache-2.0",
- "optional": true,
"engines": {
"node": ">=8"
}
@@ -6115,6 +6258,15 @@
"integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
"license": "MIT"
},
+ "node_modules/dezalgo": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
+ "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
+ "dependencies": {
+ "asap": "^2.0.0",
+ "wrappy": "1"
+ }
+ },
"node_modules/diacritics": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/diacritics/-/diacritics-1.3.0.tgz",
@@ -7456,12 +7608,47 @@
"node": ">= 6"
}
},
+ "node_modules/formidable": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.2.tgz",
+ "integrity": "sha512-Jqc1btCy3QzRbJaICGwKcBfGWuLADRerLzDqi2NwSt/UkXLsHJw2TVResiaoBufHVHy9aSgClOHCeJsSsFLTbg==",
+ "dependencies": {
+ "dezalgo": "^1.0.4",
+ "hexoid": "^2.0.0",
+ "once": "^1.4.0"
+ },
+ "funding": {
+ "url": "https://ko-fi.com/tunnckoCore/commissions"
+ }
+ },
"node_modules/fs-constants": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
"license": "MIT"
},
+ "node_modules/fs-minipass": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/fs-minipass/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -7537,6 +7724,68 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/gauge": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
+ "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
+ "deprecated": "This package is no longer supported.",
+ "dependencies": {
+ "aproba": "^1.0.3 || ^2.0.0",
+ "color-support": "^1.1.2",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.1",
+ "object-assign": "^4.1.1",
+ "signal-exit": "^3.0.0",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1",
+ "wide-align": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/gauge/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/gauge/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
+ "node_modules/gauge/node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
+ },
+ "node_modules/gauge/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/gauge/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/get-intrinsic": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz",
@@ -7809,6 +8058,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/has-unicode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+ "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="
+ },
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
@@ -7827,6 +8081,14 @@
"integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==",
"license": "MIT"
},
+ "node_modules/hexoid": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-2.0.0.tgz",
+ "integrity": "sha512-qlspKUK7IlSQv2o+5I7yhUd7TxlOG2Vr5LTa3ve2XSNVKAL/n/u/7KLvKmFNimomDIKvZFXWHv0T12mv7rT8Aw==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
@@ -7845,6 +8107,18 @@
"void-elements": "3.1.0"
}
},
+ "node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/i18n-iso-countries": {
"version": "7.13.0",
"resolved": "https://registry.npmjs.org/i18n-iso-countries/-/i18n-iso-countries-7.13.0.tgz",
@@ -9020,6 +9294,28 @@
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc"
}
},
+ "node_modules/make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "dependencies": {
+ "semver": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/make-dir/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
@@ -9109,6 +9405,29 @@
"node": ">=16 || 14 >=14.17"
}
},
+ "node_modules/minizlib": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+ "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+ "dependencies": {
+ "minipass": "^3.0.0",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minizlib/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/mitt": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
@@ -9391,6 +9710,20 @@
"node": ">=6.0.0"
}
},
+ "node_modules/nopt": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
+ "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
+ "dependencies": {
+ "abbrev": "1"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@@ -9400,6 +9733,18 @@
"node": ">=0.10.0"
}
},
+ "node_modules/npmlog": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
+ "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
+ "deprecated": "This package is no longer supported.",
+ "dependencies": {
+ "are-we-there-yet": "^2.0.0",
+ "console-control-strings": "^1.1.0",
+ "gauge": "^3.0.0",
+ "set-blocking": "^2.0.0"
+ }
+ },
"node_modules/nuqs": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/nuqs/-/nuqs-2.2.3.tgz",
@@ -10970,6 +11315,11 @@
"node": ">=10"
}
},
+ "node_modules/set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
+ },
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
@@ -11663,6 +12013,22 @@
"node": ">=6"
}
},
+ "node_modules/tar": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
+ "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
+ "dependencies": {
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "minipass": "^5.0.0",
+ "minizlib": "^2.1.1",
+ "mkdirp": "^1.0.3",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/tar-stream": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
@@ -11679,6 +12045,25 @@
"node": ">=6"
}
},
+ "node_modules/tar/node_modules/minipass": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
+ "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tar/node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/thenify": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
@@ -12434,6 +12819,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/underscore": {
+ "version": "1.13.7",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz",
+ "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g=="
+ },
"node_modules/undici-types": {
"version": "6.19.8",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
@@ -12742,6 +13132,51 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/wide-align": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
+ "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
+ "dependencies": {
+ "string-width": "^1.0.2 || 2 || 3 || 4"
+ }
+ },
+ "node_modules/wide-align/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wide-align/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
+ "node_modules/wide-align/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wide-align/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/word-wrap": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
@@ -12852,6 +13287,14 @@
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"license": "ISC"
},
+ "node_modules/xhr2": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.2.1.tgz",
+ "integrity": "sha512-sID0rrVCqkVNUn8t6xuv9+6FViXjUVXq8H5rWOH2rz9fDNQEd4g0EA2XlcEdJXRz5BMEn4O1pJFdT+z4YHhoWw==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/xmlchars": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
diff --git a/package.json b/package.json
index c5306242..af0efae7 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
"@mui/material": "^6.2.1",
"@mui/x-data-grid-premium": "^7.23.3",
"@mui/x-tree-view": "^7.23.6",
+ "@pdftron/pdfnet-node": "^11.3.0",
"@pdftron/webviewer": "^11.3.0",
"@radix-ui/primitive": "^1.1.1",
"@radix-ui/react-accordion": "^1.2.2",
@@ -54,6 +55,7 @@
"@t3-oss/env-nextjs": "^0.11.1",
"@tanstack/react-table": "^8.20.6",
"@types/docusign-esign": "^5.19.8",
+ "@types/formidable": "^3.4.5",
"accept-language": "^3.0.20",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
@@ -65,6 +67,7 @@
"embla-carousel-react": "^8.5.1",
"exceljs": "^4.4.0",
"file-saver": "^2.0.5",
+ "formidable": "^3.5.2",
"handlebars": "^4.7.8",
"i18n-iso-countries": "^7.13.0",
"i18next": "^24.1.2",
diff --git a/pages/api/pdftron/createVendorDataReports.ts b/pages/api/pdftron/createVendorDataReports.ts
new file mode 100644
index 00000000..47f6055d
--- /dev/null
+++ b/pages/api/pdftron/createVendorDataReports.ts
@@ -0,0 +1,36 @@
+import type { NextApiRequest, NextApiResponse } from "next";
+import formidable from "formidable";
+
+export const config = {
+ api: {
+ bodyParser: false, // ✅ 이게 false면 안 됨!
+ },
+};
+
+export default async function handler(
+ req: NextApiRequest,
+ res: NextApiResponse
+) {
+ if (req.method !== "POST") {
+ return res.status(405).end();
+ }
+
+ const form = formidable({ multiples: true });
+
+ form.parse(req, async (err, fields, files) => {
+ if (err) {
+ console.error(err);
+ return res.status(500).json({ error: "Error parsing form" });
+ }
+
+ try {
+ const additionalData = JSON.parse((fields?.additionalData ?? "") as string);
+ console.log("📦 additionalData:", additionalData);
+ console.log("📎 files:", files.files); // files.files는 array or single file
+
+ return res.status(200).json({ success: true });
+ } catch (e) {
+ return res.status(400).json({ error: "Invalid additionalData" });
+ }
+ });
+}