[as instl] 기타 파일 그룹 ID 동일하게 업로드 하도록 변경함
This commit is contained in:
@@ -124,9 +124,20 @@ function CnfmRegistPage() {
|
||||
const [privacyAgree, setPrivacyAgree] = useState<"Y" | "N">("N");
|
||||
|
||||
/* ── 기타 첨부파일 ── */
|
||||
type EtcFile = { id: number; name: string; ext: string; size: string; uploader: string };
|
||||
type EtcFile = {
|
||||
id: string;
|
||||
name: string;
|
||||
ext: string;
|
||||
size: string;
|
||||
uploader: string;
|
||||
atflCd: string;
|
||||
atflId: string;
|
||||
};
|
||||
const [etcFiles, setEtcFiles] = useState<EtcFile[]>([]);
|
||||
const [etcNoticeOpen, setEtcNoticeOpen] = useState(true);
|
||||
const [etcFileGroupId, setEtcFileGroupId] = useState("");
|
||||
const [etcUploading, setEtcUploading] = useState(false);
|
||||
const etcFileGroupIdRef = useRef("");
|
||||
|
||||
/* ── 필수 첨부파일 ── */
|
||||
const { data: requiredAttachmentDefs = [] } = useQuery<EsntlAtchFileMngTreeResponseDto[]>({
|
||||
@@ -227,6 +238,93 @@ function CnfmRegistPage() {
|
||||
e.target.value = "";
|
||||
};
|
||||
|
||||
const toFileSizeText = (size: number): string =>
|
||||
size > 1024 * 1024 ? `${(size / 1024 / 1024).toFixed(1)}MB` : `${(size / 1024).toFixed(0)}KB`;
|
||||
|
||||
const uploadEtcFile = (file: File): Promise<EtcFile> =>
|
||||
new Promise((resolve, reject) => {
|
||||
let uploadedAtflCd = "";
|
||||
let uploadedAtflId = "";
|
||||
|
||||
const upload = new Upload(file, {
|
||||
endpoint: `${PROXY_HOST}${ENDPOINT.ATTACH_SERVICE.TUS_UPLOAD}`,
|
||||
chunkSize: 10 * 1024 * 1024,
|
||||
headers: {
|
||||
[CLAIM_NAME]: getCookie(CLAIM_NAME) ?? "",
|
||||
[AUTH_USER_ID]: getCookie(AUTH_USER_ID) ?? "",
|
||||
},
|
||||
metadata: {
|
||||
filename: file.name,
|
||||
filetype: file.type,
|
||||
atflCd: etcFileGroupIdRef.current || "",
|
||||
},
|
||||
onError(error: Error) {
|
||||
reject(error);
|
||||
},
|
||||
onAfterResponse(_req: unknown, res: HttpResponse) {
|
||||
const fileInfo = res.getHeader("X-File-Info");
|
||||
if (typeof fileInfo !== "string") return;
|
||||
|
||||
const parsed = JSON.parse(fileInfo) as { atflCd?: string; atflId?: string };
|
||||
uploadedAtflCd = parsed.atflCd ?? "";
|
||||
uploadedAtflId = parsed.atflId ?? "";
|
||||
|
||||
if (uploadedAtflCd) {
|
||||
etcFileGroupIdRef.current = uploadedAtflCd;
|
||||
setEtcFileGroupId((prev) => prev || uploadedAtflCd);
|
||||
}
|
||||
},
|
||||
onSuccess() {
|
||||
const ext = file.name.includes(".") ? file.name.split(".").pop() ?? "" : "";
|
||||
resolve({
|
||||
id: uploadedAtflId || `${Date.now()}_${Math.random()}`,
|
||||
name: file.name,
|
||||
ext,
|
||||
size: toFileSizeText(file.size),
|
||||
uploader: "(로그인 사용자)",
|
||||
atflCd: uploadedAtflCd,
|
||||
atflId: uploadedAtflId,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
upload.start();
|
||||
});
|
||||
|
||||
const handleEtcFilesChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const files = Array.from(e.target.files ?? []);
|
||||
if (files.length === 0) return;
|
||||
|
||||
setEtcUploading(true);
|
||||
const uploadedRows: EtcFile[] = [];
|
||||
const failedNames: string[] = [];
|
||||
|
||||
for (const file of files) {
|
||||
try {
|
||||
const uploaded = await uploadEtcFile(file);
|
||||
uploadedRows.push(uploaded);
|
||||
} catch (error) {
|
||||
console.error("기타 첨부파일 업로드 실패", error);
|
||||
failedNames.push(file.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (uploadedRows.length > 0) {
|
||||
setEtcFiles((prev) => [...prev, ...uploadedRows]);
|
||||
if (!etcFileGroupId && uploadedRows[0].atflCd) {
|
||||
setEtcFileGroupId(uploadedRows[0].atflCd);
|
||||
etcFileGroupIdRef.current = uploadedRows[0].atflCd;
|
||||
}
|
||||
}
|
||||
|
||||
if (failedNames.length > 0) {
|
||||
alert(`일부 파일 업로드에 실패했습니다. (${failedNames.join(", ")})`);
|
||||
}
|
||||
|
||||
setEtcUploading(false);
|
||||
e.target.value = "";
|
||||
};
|
||||
|
||||
/* ── 체크리스트 ── */
|
||||
type CheckResultVal = "Y" | "N" | null;
|
||||
const [checkResults, setCheckResults] = useState<Record<string, CheckResultVal>>({});
|
||||
@@ -560,7 +658,7 @@ function CnfmRegistPage() {
|
||||
dsgnrTelno,
|
||||
dsgnrOgdpNm: dsgnrPsitn,
|
||||
dsgnrEmlAddr,
|
||||
atchFileGroupId: "",
|
||||
atchFileGroupId: etcFileGroupId,
|
||||
prgrsSttsComCd,
|
||||
prgrsSttsCdNm: "",
|
||||
regDt: "",
|
||||
@@ -1202,29 +1300,23 @@ function CnfmRegistPage() {
|
||||
type="text"
|
||||
className="cnfm-input min-w-0 flex-1"
|
||||
placeholder="첨부문서를 등록해주세요"
|
||||
value={
|
||||
etcUploading
|
||||
? "업로드 중..."
|
||||
: etcFiles.length > 0
|
||||
? `${etcFiles.length}개 파일 등록됨`
|
||||
: ""
|
||||
}
|
||||
readOnly
|
||||
/>
|
||||
<label className="cnfm-btn-search shrink-0 cursor-pointer whitespace-nowrap text-[1.2rem]">
|
||||
첨부파일
|
||||
{etcUploading ? "업로드중" : "첨부파일"}
|
||||
<input
|
||||
type="file"
|
||||
className="hidden"
|
||||
multiple
|
||||
onChange={(e) => {
|
||||
const files = Array.from(e.target.files ?? []);
|
||||
const mapped: EtcFile[] = files.map((f, i) => ({
|
||||
id: Date.now() + i,
|
||||
name: f.name.replace(/\.[^.]+$/, ""),
|
||||
ext: f.name.split(".").pop() ?? "",
|
||||
size:
|
||||
f.size > 1024 * 1024
|
||||
? `${(f.size / 1024 / 1024).toFixed(1)}MB`
|
||||
: `${(f.size / 1024).toFixed(0)}KB`,
|
||||
uploader: "(로그인 사용자)",
|
||||
}));
|
||||
setEtcFiles((prev) => [...prev, ...mapped]);
|
||||
e.target.value = "";
|
||||
}}
|
||||
onChange={handleEtcFilesChange}
|
||||
disabled={etcUploading}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
@@ -1259,7 +1351,16 @@ function CnfmRegistPage() {
|
||||
<button
|
||||
type="button"
|
||||
className="text-[1.2rem] text-red-500 hover:text-red-700"
|
||||
onClick={() => setEtcFiles((prev) => prev.filter((x) => x.id !== f.id))}
|
||||
onClick={() =>
|
||||
setEtcFiles((prev) => {
|
||||
const next = prev.filter((x) => x.id !== f.id);
|
||||
if (next.length === 0) {
|
||||
setEtcFileGroupId("");
|
||||
etcFileGroupIdRef.current = "";
|
||||
}
|
||||
return next;
|
||||
})
|
||||
}
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user