[as instl] 기타 파일 삭제시 실제 첨부 파일에 대해서 삭제여부 Y로 변경 처리 로직 추가
This commit is contained in:
@@ -8,6 +8,7 @@ import axios from "axios";
|
||||
import { type HttpResponse, Upload } from "tus-js-client";
|
||||
|
||||
import { AUTH_USER_ID, CLAIM_NAME, ENDPOINT, PROXY_HOST } from "@/shared/config";
|
||||
import { deleteAttachment } from "@/shared/lib/attach";
|
||||
import { getCookie, setCookie, useAlertStore, useUserStore } from "@/shared/lib";
|
||||
|
||||
import type { AcntgSeMngTreeDto } from "@/entities/acntg";
|
||||
@@ -236,6 +237,28 @@ function CnfmRegistPage() {
|
||||
upload.start();
|
||||
};
|
||||
|
||||
/** 기타첨부파일 삭제 핸들러: 백엔드에 DELETE 요청을 보내 소프트삭제 처리 후 상태 갱신 */
|
||||
const handleDeleteEtcFile = async (fileId: string, atflId: string) => {
|
||||
try {
|
||||
if (atflId) {
|
||||
await deleteAttachment(atflId);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("기타 첨부파일 삭제 실패", error);
|
||||
alert("파일 삭제 중 오류가 발생했습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
setEtcFiles((prev) => {
|
||||
const next = prev.filter((x) => x.id !== fileId);
|
||||
if (next.length === 0) {
|
||||
setEtcFileGroupId("");
|
||||
etcFileGroupIdRef.current = "";
|
||||
}
|
||||
return next;
|
||||
});
|
||||
};
|
||||
|
||||
const handleRequiredFileChange = (key: RequiredAttachKey, e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const file = e.target.files?.[0];
|
||||
if (!file) return;
|
||||
@@ -286,7 +309,7 @@ function CnfmRegistPage() {
|
||||
name: file.name,
|
||||
ext,
|
||||
size: toFileSizeText(file.size),
|
||||
uploader: "(로그인 사용자)",
|
||||
uploader: userInfo?.userName ?? "알 수 없음",
|
||||
atflCd: uploadedAtflCd,
|
||||
atflId: uploadedAtflId,
|
||||
});
|
||||
@@ -747,7 +770,7 @@ function CnfmRegistPage() {
|
||||
<table className="cnfm-form-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th className="text-center align-middle">
|
||||
<th style={{ textAlign: "center" }}>
|
||||
<span className="text-red-500">*</span> 사업명
|
||||
</th>
|
||||
<td>
|
||||
@@ -761,7 +784,7 @@ function CnfmRegistPage() {
|
||||
<button className="cnfm-btn-search whitespace-nowrap">🔍 사업찾기</button>
|
||||
</div>
|
||||
</td>
|
||||
<th className="text-center align-middle">
|
||||
<th style={{ textAlign: "center" }}>
|
||||
<span className="text-red-500">*</span> 사업기간
|
||||
</th>
|
||||
<td>
|
||||
@@ -783,7 +806,7 @@ function CnfmRegistPage() {
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th className="text-center align-middle">
|
||||
<th style={{ textAlign: "center" }}>
|
||||
<span className="text-red-500">*</span> 사업내용
|
||||
</th>
|
||||
<td colSpan={3}>
|
||||
@@ -796,12 +819,12 @@ function CnfmRegistPage() {
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th className="text-center align-middle">구분</th>
|
||||
<th style={{ textAlign: "center" }}>구분</th>
|
||||
<td>
|
||||
<div className="flex gap-4 text-[1.3rem]">{taskSeComCdNm}</div>
|
||||
<input type="hidden" name="taskSeComCd" value={taskSeComCd} />
|
||||
</td>
|
||||
<th className="text-center align-middle">신청 지자체</th>
|
||||
<th style={{ textAlign: "center" }}>신청 지자체</th>
|
||||
<td>
|
||||
<span className="inline-block min-w-[16rem] whitespace-nowrap text-[1.3rem] text-gray-500">
|
||||
{userInfo?.enoNm ?? "\u00A0"}
|
||||
@@ -809,7 +832,7 @@ function CnfmRegistPage() {
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th className="text-center align-middle">사업구분</th>
|
||||
<th style={{ textAlign: "center" }}><span className="text-red-500">*</span>사업구분</th>
|
||||
<td colSpan={3}>
|
||||
<div className="flex gap-4 text-[1.3rem]">
|
||||
{[
|
||||
@@ -841,31 +864,31 @@ function CnfmRegistPage() {
|
||||
<table className="cnfm-form-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th rowSpan={2} className="text-center align-middle w-[6.5rem]">신청자</th>
|
||||
<th className="text-center align-middle">이름</th>
|
||||
<th rowSpan={2} style={{ textAlign: "center" }} className="text-center align-middle w-[6.5rem]">신청자</th>
|
||||
<th style={{ textAlign: "center" }}>이름</th>
|
||||
<td>
|
||||
<span className="inline-block min-w-[16rem] whitespace-nowrap text-[1.3rem] text-gray-500">{userInfo?.userName ?? "\u00A0"}</span>
|
||||
</td>
|
||||
<th className="text-center align-middle">전화번호</th>
|
||||
<th style={{ textAlign: "center" }}>전화번호</th>
|
||||
<td>
|
||||
<span className="inline-block min-w-[16rem] whitespace-nowrap text-[1.3rem] text-gray-500">{userInfo?.mphn ?? userInfo?.telno ?? "\u00A0"}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th className="text-center align-middle">부서</th>
|
||||
<th style={{ textAlign: "center" }}>부서</th>
|
||||
<td>
|
||||
<span className="text-[1.3rem] text-gray-500">{userInfo?.instSeNm ?? "\u00A0"}</span>
|
||||
</td>
|
||||
|
||||
<th className="text-center align-middle">이메일</th>
|
||||
<th style={{ textAlign: "center" }}>이메일</th>
|
||||
<td>
|
||||
<span className="text-[1.3rem] text-gray-500">{userInfo?.email ?? "\u00A0"}</span>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th rowSpan={2} className="text-center align-middle">설계자</th>
|
||||
<th className="text-center align-middle">이름</th>
|
||||
<th rowSpan={2} style={{ textAlign: "center" }}>설계자</th>
|
||||
<th style={{ textAlign: "center" }}>이름</th>
|
||||
<td>
|
||||
<Input
|
||||
placeholder="설계자 성명"
|
||||
@@ -874,7 +897,7 @@ function CnfmRegistPage() {
|
||||
onChange={(e) => setDsgnrNm(e.target.value)}
|
||||
/>
|
||||
</td>
|
||||
<th className="text-center align-middle">전화번호</th>
|
||||
<th style={{ textAlign: "center" }}>전화번호</th>
|
||||
<td>
|
||||
<Input
|
||||
placeholder="설계자 전화번호"
|
||||
@@ -885,7 +908,7 @@ function CnfmRegistPage() {
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th className="text-center align-middle">소속</th>
|
||||
<th style={{ textAlign: "center" }}>소속</th>
|
||||
<td>
|
||||
<Input
|
||||
placeholder="소속명"
|
||||
@@ -895,7 +918,7 @@ function CnfmRegistPage() {
|
||||
/>
|
||||
</td>
|
||||
|
||||
<th className="text-center align-middle">이메일</th>
|
||||
<th style={{ textAlign: "center" }}>이메일</th>
|
||||
<td>
|
||||
<Input
|
||||
placeholder="설계자 이메일"
|
||||
@@ -912,19 +935,37 @@ function CnfmRegistPage() {
|
||||
{/* ── 개인정보 동의 ── */}
|
||||
<div className="cnfm-card p-4">
|
||||
<h3 className="mb-3 border-b pb-2 text-[1.5rem] font-bold text-gray-700">개인정보 동의</h3>
|
||||
<div className="mb-3 rounded border bg-gray-50 p-3 text-[1.25rem] leading-relaxed text-gray-600">
|
||||
<p className="mb-1 font-semibold">[개인정보 수집·이용 목적]</p>
|
||||
<ul className="ml-4 list-disc space-y-1">
|
||||
<li>수집항목: 소속기관, 성명, 전화번호, 이메일, IP Address, 접속 기기 정보</li>
|
||||
<li>수집목적: 하수도 시설물 설치인가 신청 및 처리 목적</li>
|
||||
<li>보유기간: 관련 법령에 따른 의무 보유 기간 준수</li>
|
||||
</ul>
|
||||
<p className="mt-2 text-[1.2rem] text-gray-500">
|
||||
※ 개인정보 제공에 동의하지 않을 수 있으나, 미동의 시 서비스 이용이 제한될 수 있습니다.
|
||||
</p>
|
||||
<div className="mb-3 rounded border bg-gray-50 p-3 text-[1.25rem] leading-relaxed text-gray-600 max-h-80 overflow-auto whitespace-pre-wrap pr-2">
|
||||
<p className="mb-1 font-semibold">[ 개인정보 수집항목 ]</p>
|
||||
<div>
|
||||
* 필수항목 : 소속기관, 소속부서, 담당자, 직급, 사무실 번호, FAX 번호<br />
|
||||
․ 선택항목 : 휴대폰 번호, 이메일 주소<br />
|
||||
․ 기타항목 : IP Address, 쿠키, 시스템 접속 및 이용 기록<br />
|
||||
※ 시스템 이용과정에서 기타 항목의 정보들이 자동으로 생성되어 수집될 수 있습니다.
|
||||
</div>
|
||||
|
||||
<p className="mt-4 font-semibold">[ 개인정보 이용목적 ]</p>
|
||||
<div>
|
||||
․ 국가하수도정보시스템 웹서비스 이용에 따른 본인 확인 절차에 이용<br />
|
||||
․ 국가하수도정보시스템 사용에 필요한 권한 부여<br />
|
||||
․ 사용자별 맞춤 컨텐츠 (처리시설의 운영 데이터 조회, 수질현황 데이터 조회, 예산 편성 / 예산편성 등) 제공에 이용
|
||||
</div>
|
||||
|
||||
<div className="tit mt-4">● 개인정보의 보유 및 이용기간</div>
|
||||
<div>
|
||||
․ 수집된 고객의 개인정보는 2년 동안 보유하며 그 이후에는 문서를 파쇄합니다.<br />
|
||||
․ 정보제공자가 개인정보 파쇄를 요청할 경우 즉시 파쇄합니다.
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<div className="tit">● 개인정보 제공 거부에 따른 제한사항</div>
|
||||
<div>
|
||||
․ 귀하는 개인정보 제공 동의를 거부할 권리가 있으나, 동의 거부 시 국가하수도정보시스템 이용 서비스에 제한이 있을 수 있습니다.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-6 text-[1.3rem]">
|
||||
<label className="flex cursor-pointer items-center gap-2 font-semibold text-blue-600">
|
||||
<label className="flex cursor-pointer items-center gap-2 font-semibold">
|
||||
<input
|
||||
type="radio"
|
||||
name="privacyAgree"
|
||||
@@ -1361,16 +1402,7 @@ function CnfmRegistPage() {
|
||||
<button
|
||||
type="button"
|
||||
className="text-[1.2rem] text-red-500 hover:text-red-700"
|
||||
onClick={() =>
|
||||
setEtcFiles((prev) => {
|
||||
const next = prev.filter((x) => x.id !== f.id);
|
||||
if (next.length === 0) {
|
||||
setEtcFileGroupId("");
|
||||
etcFileGroupIdRef.current = "";
|
||||
}
|
||||
return next;
|
||||
})
|
||||
}
|
||||
onClick={() => void handleDeleteEtcFile(f.id, f.atflId)}
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import { getCookie } from "@/shared/lib";
|
||||
import { CLAIM_NAME, AUTH_USER_ID } from "@/shared/config/env";
|
||||
import axios from "axios";
|
||||
import { PROXY_HOST, ENDPOINT } from "@/shared/config";
|
||||
|
||||
/**
|
||||
* Common helper to delete attachment using cookies for auth headers.
|
||||
*/
|
||||
export async function deleteAttachment(atflId: string): Promise<void> {
|
||||
if (!atflId) return;
|
||||
const headers: Record<string, string> = {
|
||||
[CLAIM_NAME]: getCookie(CLAIM_NAME) ?? "",
|
||||
[AUTH_USER_ID]: getCookie(AUTH_USER_ID) ?? "",
|
||||
};
|
||||
const url = `${PROXY_HOST}${ENDPOINT.ATTACH_SERVICE.ATTACHMENTS}/${atflId}`;
|
||||
await axios.delete(url, { headers });
|
||||
}
|
||||
Reference in New Issue
Block a user