[as] feat: AI 수동 검증 버튼 추가
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
import { client } from "@/shared/api";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
|
||||
import type {
|
||||
AiAutoPrcsLatestResponseDto,
|
||||
AiAutoPrcsMngService,
|
||||
} from "../model/ai-auto-prcs-mng-interface";
|
||||
|
||||
const BASE = ENDPOINT.AS_SERVICE.AI_AUTO_PRCS_MNG;
|
||||
|
||||
async function findLatestPerAutoSeByFnrsDocNo(
|
||||
fnrsCnsltnDocNo: string,
|
||||
atmtnSeComCd?: string,
|
||||
): Promise<AiAutoPrcsLatestResponseDto[]> {
|
||||
const response = await client.get<AiAutoPrcsLatestResponseDto[]>(
|
||||
`${BASE}/fnrs/${fnrsCnsltnDocNo}/latest`,
|
||||
{ params: atmtnSeComCd ? { atmtnSeComCd } : undefined },
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export const aiAutoPrcsMngService = {
|
||||
findLatestPerAutoSeByFnrsDocNo,
|
||||
} satisfies AiAutoPrcsMngService;
|
||||
@@ -0,0 +1,30 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
|
||||
import { aiAutoPrcsMngService } from "./ai-auto-prcs-mng-service";
|
||||
|
||||
export const aiAutoPrcsMngKeys = {
|
||||
all: [ENDPOINT.AS_SERVICE.AI_AUTO_PRCS_MNG] as const,
|
||||
latest: (fnrsCnsltnDocNo: string, atmtnSeComCd?: string) =>
|
||||
[...aiAutoPrcsMngKeys.all, "latest", fnrsCnsltnDocNo, atmtnSeComCd ?? "all"] as const,
|
||||
};
|
||||
|
||||
interface UseAiAutoPrcsLatestOptions {
|
||||
enabled?: boolean;
|
||||
atmtnSeComCd?: string;
|
||||
}
|
||||
|
||||
export function useAiAutoPrcsLatest(
|
||||
fnrsCnsltnDocNo: string | null | undefined,
|
||||
options: UseAiAutoPrcsLatestOptions = {},
|
||||
) {
|
||||
const { enabled = true, atmtnSeComCd } = options;
|
||||
|
||||
return useQuery({
|
||||
queryKey: aiAutoPrcsMngKeys.latest(fnrsCnsltnDocNo!, atmtnSeComCd),
|
||||
queryFn: () =>
|
||||
aiAutoPrcsMngService.findLatestPerAutoSeByFnrsDocNo(fnrsCnsltnDocNo!, atmtnSeComCd),
|
||||
enabled: Boolean(fnrsCnsltnDocNo) && enabled,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export { aiAutoPrcsMngService } from "./api/ai-auto-prcs-mng-service";
|
||||
export { aiAutoPrcsMngKeys, useAiAutoPrcsLatest } from "./api/queries";
|
||||
export type {
|
||||
AiAutoPrcsLatestResponseDto,
|
||||
AiAutoPrcsMngService,
|
||||
AiAutoSeComCd,
|
||||
} from "./model/ai-auto-prcs-mng-interface";
|
||||
export { AI_AUTO_SE } from "./model/ai-auto-prcs-mng-interface";
|
||||
@@ -0,0 +1,44 @@
|
||||
/** 자동화구분 공통코드 (AIAUTOSE) */
|
||||
export const AI_AUTO_SE = {
|
||||
FILE_VRFC: "FILE_VRFC",
|
||||
DRAFT_GEN: "DRAFT_GEN",
|
||||
COST_VRFC: "COST_VRFC",
|
||||
} as const;
|
||||
|
||||
export type AiAutoSeComCd = (typeof AI_AUTO_SE)[keyof typeof AI_AUTO_SE];
|
||||
|
||||
/** 백엔드 AiAutoPrcsLatestResponseDto */
|
||||
export interface AiAutoPrcsLatestResponseDto {
|
||||
atmtnPrcsUuid?: string;
|
||||
fnrsCnsltnDocNo?: string;
|
||||
pwrkCnsltnDocNo?: string;
|
||||
crtDmndUuid?: string;
|
||||
atmtnSeComCd?: string;
|
||||
atmtnSeComNm?: string;
|
||||
bfrDocSttsComCd?: string;
|
||||
bfrDocSttsComNm?: string;
|
||||
aftrDocSttsComCd?: string;
|
||||
aftrDocSttsComNm?: string;
|
||||
atmtnPrcsSttsComCd?: string;
|
||||
atmtnPrcsSttsComNm?: string;
|
||||
dmndDt?: string;
|
||||
dmndSysId?: string;
|
||||
rplyDt?: string;
|
||||
rplyRsltComCd?: string;
|
||||
prcsErrCn?: string | null;
|
||||
lastSttsInqDt?: string;
|
||||
sttsInqRsltComCd?: string;
|
||||
rtrsmCtpvNmtm?: number;
|
||||
lastRtrsmDt?: string;
|
||||
lastFrcSttsChgYn?: string;
|
||||
isFailed?: boolean;
|
||||
isRetryable?: boolean;
|
||||
}
|
||||
|
||||
/** Controller public 메서드명·시그니처와 동일 */
|
||||
export interface AiAutoPrcsMngService {
|
||||
findLatestPerAutoSeByFnrsDocNo(
|
||||
fnrsCnsltnDocNo: string,
|
||||
atmtnSeComCd?: string,
|
||||
): Promise<AiAutoPrcsLatestResponseDto[]>;
|
||||
}
|
||||
@@ -46,9 +46,40 @@ async function requestCostVerification(
|
||||
return response.data;
|
||||
}
|
||||
|
||||
async function reTransferDocument(
|
||||
body: DcRagDocumentTransferRequestDto,
|
||||
): Promise<DcRagCommonResponseDto> {
|
||||
const response = await client.post<DcRagCommonResponseDto>(
|
||||
`${BASE}/documents/re-transfer`,
|
||||
body,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
async function reGenerateDraft(
|
||||
body: DcRagDraftGenerateRequestDto,
|
||||
): Promise<DcRagDraftGenerateResponseDto> {
|
||||
const response = await client.post<DcRagDraftGenerateResponseDto>(
|
||||
`${BASE}/documents/draft/re-generate`,
|
||||
body,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
async function reVerifyCost(body: DcRagCostVerifyRequestDto): Promise<DcRagCommonResponseDto> {
|
||||
const response = await client.post<DcRagCommonResponseDto>(
|
||||
`${BASE}/documents/cost/re-verify`,
|
||||
body,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export const dcRagApiToService = {
|
||||
requestDocumentTransfer,
|
||||
requestDraftGeneration,
|
||||
getDraftGenerationStatus,
|
||||
requestCostVerification,
|
||||
reTransferDocument,
|
||||
reGenerateDraft,
|
||||
reVerifyCost,
|
||||
} satisfies DcRagApiToService;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { useMutationWrapper } from "@/shared/lib";
|
||||
import { aiAutoPrcsMngKeys } from "@/entities/ai-auto-prcs-mng";
|
||||
import { fnrsCnsltnKeys } from "@/entities/fnrs-cnsltn";
|
||||
|
||||
import type { DcRagDraftStatusResponseDto } from "../model/dcrag-to-interface";
|
||||
import type {
|
||||
@@ -21,6 +24,18 @@ function isDraftGenerationSettled(data: DcRagDraftStatusResponseDto | undefined)
|
||||
return data.events?.some((event) => event.eventType === "COMPLETED") ?? false;
|
||||
}
|
||||
|
||||
function invalidateAfterAiRetry(
|
||||
queryClient: ReturnType<typeof useQueryClient>,
|
||||
fnrsCnsltnDocNo?: string,
|
||||
) {
|
||||
queryClient.invalidateQueries({ queryKey: dcRagApiToBaseKey });
|
||||
queryClient.invalidateQueries({ queryKey: aiAutoPrcsMngKeys.all });
|
||||
if (fnrsCnsltnDocNo) {
|
||||
queryClient.invalidateQueries({ queryKey: fnrsCnsltnKeys.detail(fnrsCnsltnDocNo) });
|
||||
queryClient.invalidateQueries({ queryKey: fnrsCnsltnKeys.all });
|
||||
}
|
||||
}
|
||||
|
||||
export function useDraftGenerationStatus(crtDmndUuid: string | null | undefined) {
|
||||
return useQuery({
|
||||
queryKey: [...dcRagApiToBaseKey, "getDraftGenerationStatus", crtDmndUuid],
|
||||
@@ -68,3 +83,39 @@ export function useRequestCostVerification() {
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useReTransferDocument() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutationWrapper({
|
||||
mutationFn: (body: DcRagDocumentTransferRequestDto) =>
|
||||
dcRagApiToService.reTransferDocument(body),
|
||||
onSuccess: (_data, body) => {
|
||||
invalidateAfterAiRetry(queryClient, body.fnrsCnsltnDocNo);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useReGenerateDraft() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutationWrapper({
|
||||
mutationFn: (body: DcRagDraftGenerateRequestDto) => dcRagApiToService.reGenerateDraft(body),
|
||||
onSuccess: (_data, body) => {
|
||||
invalidateAfterAiRetry(queryClient, body.fnrsCnsltnDocNo);
|
||||
if (body.crtDmndUuid) {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [...dcRagApiToBaseKey, "getDraftGenerationStatus", body.crtDmndUuid],
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useReVerifyCost() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutationWrapper({
|
||||
mutationFn: (body: DcRagCostVerifyRequestDto) => dcRagApiToService.reVerifyCost(body),
|
||||
onSuccess: (_data, body) => {
|
||||
invalidateAfterAiRetry(queryClient, body.fnrsCnsltnDocNo);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,9 +2,12 @@ export { dcRagApiToService } from "./api/dcrag-to-service";
|
||||
export { dcRagApiToBaseKey } from "./api/queries";
|
||||
export {
|
||||
useDraftGenerationStatus,
|
||||
useReGenerateDraft,
|
||||
useRequestCostVerification,
|
||||
useRequestDocumentTransfer,
|
||||
useRequestDraftGeneration,
|
||||
useReTransferDocument,
|
||||
useReVerifyCost,
|
||||
} from "./api/queries";
|
||||
export type {
|
||||
DcRagApiToService,
|
||||
|
||||
@@ -49,4 +49,7 @@ export interface DcRagApiToService {
|
||||
): Promise<DcRagDraftGenerateResponseDto>;
|
||||
getDraftGenerationStatus(crtDmndUuid: string): Promise<DcRagDraftStatusResponseDto>;
|
||||
requestCostVerification(body: DcRagCostVerifyRequestDto): Promise<DcRagCommonResponseDto>;
|
||||
reTransferDocument(body: DcRagDocumentTransferRequestDto): Promise<DcRagCommonResponseDto>;
|
||||
reGenerateDraft(body: DcRagDraftGenerateRequestDto): Promise<DcRagDraftGenerateResponseDto>;
|
||||
reVerifyCost(body: DcRagCostVerifyRequestDto): Promise<DcRagCommonResponseDto>;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ export const FNRS_CNSLTN_VIEW_BUTTON_ACTION = {
|
||||
rvwOpnnRply: "rvwOpnnRply",
|
||||
rqstTechRvw: "rqstTechRvw",
|
||||
fileSplmnt: "fileSplmnt",
|
||||
fileVrfc: "fileVrfc",
|
||||
dsgntRvwr: "dsgntRvwr",
|
||||
pwrkCnsltnDocCrt: "pwrkCnsltnDocCrt",
|
||||
pwrkCnsltnDocMng: "pwrkCnsltnDocMng",
|
||||
@@ -20,6 +21,7 @@ export const FNRS_CNSLTN_VIEW_BUTTON_ACTION = {
|
||||
atrzRply: "atrzRply",
|
||||
actnCmptn: "actnCmptn",
|
||||
rqstActnRvw: "rqstActnRvw",
|
||||
costVrfc: "costVrfc",
|
||||
} as const;
|
||||
|
||||
export type FnrsCnsltnViewButtonAction =
|
||||
@@ -80,7 +82,11 @@ const ROLE_USER01_ATRZ_STATUS_ACTIONS: Record<
|
||||
Record<string, FnrsCnsltnViewButtonAction[]>
|
||||
> = {
|
||||
ER: {
|
||||
ATRZ01: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.fileSplmnt, FNRS_CNSLTN_VIEW_BUTTON_ACTION.dsgntRvwr],
|
||||
ATRZ01: [
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.fileSplmnt,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.fileVrfc,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.dsgntRvwr,
|
||||
],
|
||||
},
|
||||
SL: {
|
||||
ATRZ01: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
@@ -136,7 +142,10 @@ const ROLE_USER01_ATRZ_STATUS_ACTIONS: Record<
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.dsgntRvwr,
|
||||
],
|
||||
ATRZ02: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ02: [
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.costVrfc,
|
||||
],
|
||||
ATRZ03: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ99: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
},
|
||||
@@ -183,6 +192,9 @@ function resolveButtonConfigs(actions: FnrsCnsltnViewButtonAction[]): FnrsCnsltn
|
||||
interface GetButtonConfigsOptions {
|
||||
hasPendingApprovalRequest?: boolean;
|
||||
hasCompletedDraft?: boolean;
|
||||
canRetryFileVrfc?: boolean;
|
||||
canRetryDraftGen?: boolean;
|
||||
canRetryCostVrfc?: boolean;
|
||||
}
|
||||
|
||||
const PENDING_APPROVAL_ACTIONS = new Set<FnrsCnsltnViewButtonAction>([
|
||||
@@ -220,6 +232,16 @@ function resolveRoleUser01AtrzButtonActions(
|
||||
const needsPendingApproval = PENDING_APPROVAL_ACTIONS.has(action);
|
||||
if (needsPendingApproval && options?.hasPendingApprovalRequest === false) return false;
|
||||
|
||||
if (action === FNRS_CNSLTN_VIEW_BUTTON_ACTION.fileVrfc) {
|
||||
return options?.canRetryFileVrfc === true;
|
||||
}
|
||||
if (action === FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocCrt) {
|
||||
return options?.canRetryDraftGen === true;
|
||||
}
|
||||
if (action === FNRS_CNSLTN_VIEW_BUTTON_ACTION.costVrfc) {
|
||||
return options?.canRetryCostVrfc === true;
|
||||
}
|
||||
|
||||
if (options?.hasCompletedDraft != null) {
|
||||
if (prgrsSttsComCd === "SL" || prgrsSttsComCd === "TE" || prgrsSttsComCd === "RK") {
|
||||
if (action === FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng) {
|
||||
@@ -230,9 +252,6 @@ function resolveRoleUser01AtrzButtonActions(
|
||||
if (action === FNRS_CNSLTN_VIEW_BUTTON_ACTION.rvwRsltInq) {
|
||||
return options.hasCompletedDraft;
|
||||
}
|
||||
if (action === FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocCrt) {
|
||||
return !options.hasCompletedDraft;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,12 @@ import { AxiosError } from "axios";
|
||||
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { useAlertStore, useUserStore } from "@/shared/lib";
|
||||
import {
|
||||
AI_AUTO_SE,
|
||||
type AiAutoPrcsLatestResponseDto,
|
||||
useAiAutoPrcsLatest,
|
||||
} from "@/entities/ai-auto-prcs-mng";
|
||||
import { useReGenerateDraft, useReTransferDocument, useReVerifyCost } from "@/entities/dcrag-to";
|
||||
import {
|
||||
buildElaprPrgrsSttsListFromAplnRows,
|
||||
ElaprApprovalDialog,
|
||||
@@ -64,6 +70,15 @@ import { FileVrfcSplmntDialog } from "./file-vrfc-splmnt-dialog";
|
||||
import { PwrkCnsltnDocMngDialog } from "./pwrk-cnsltn-doc-mng-dialog";
|
||||
import { PwrkCnsltnRvwRsltInqDialog } from "./pwrk-cnsltn-rvw-rslt-inq-dialog";
|
||||
|
||||
const AI_RETRY_PRGRS_STTS = new Set(["ER", "TE", "EV"]);
|
||||
|
||||
function findLatestByAutoSe(
|
||||
list: AiAutoPrcsLatestResponseDto[] | undefined,
|
||||
atmtnSeComCd: string,
|
||||
): AiAutoPrcsLatestResponseDto | undefined {
|
||||
return list?.find((item) => item.atmtnSeComCd === atmtnSeComCd);
|
||||
}
|
||||
|
||||
interface FloatingActionButtonsProps {
|
||||
data: FnrsCnsltnMngDetResponseDto;
|
||||
docSeComCd: string;
|
||||
@@ -118,7 +133,9 @@ function FloatingActionButtons({
|
||||
const needsPwrkDraftCheck =
|
||||
dtlInstCd === "ROLE_USER01" && ["SL", "TE", "RK"].includes(prgrsSttsComCd);
|
||||
const needsPwrkForRb = dtlInstCd === "ROLE_USER05" && prgrsSttsComCd === "RB";
|
||||
const needsPwrkLookup = needsPwrkDraftCheck || needsPwrkForRb;
|
||||
const needsPwrkForAiRetry = dtlInstCd === "ROLE_USER01" && ["TE", "EV"].includes(prgrsSttsComCd);
|
||||
const needsPwrkLookup = needsPwrkDraftCheck || needsPwrkForRb || needsPwrkForAiRetry;
|
||||
const needsAiAutoLatest = dtlInstCd === "ROLE_USER01" && AI_RETRY_PRGRS_STTS.has(prgrsSttsComCd);
|
||||
|
||||
const { data: elaprDocPrgrsList = [], isLoading: isElaprDocPrgrsLoading } =
|
||||
useElaprDocPrgrsByDocNo(needsElaprPrgrsCheck ? docNo : null);
|
||||
@@ -128,8 +145,31 @@ function FloatingActionButtons({
|
||||
needsPwrkLookup,
|
||||
);
|
||||
|
||||
const { data: aiAutoLatestList, isLoading: isAiAutoLatestLoading } = useAiAutoPrcsLatest(docNo, {
|
||||
enabled: needsAiAutoLatest,
|
||||
});
|
||||
|
||||
const fileVrfcLatest = findLatestByAutoSe(aiAutoLatestList, AI_AUTO_SE.FILE_VRFC);
|
||||
const draftGenLatest = findLatestByAutoSe(aiAutoLatestList, AI_AUTO_SE.DRAFT_GEN);
|
||||
const costVrfcLatest = findLatestByAutoSe(aiAutoLatestList, AI_AUTO_SE.COST_VRFC);
|
||||
const canRetryFileVrfc = fileVrfcLatest?.isRetryable === true;
|
||||
const canRetryDraftGen = draftGenLatest?.isRetryable === true;
|
||||
const canRetryCostVrfc = costVrfcLatest?.isRetryable === true;
|
||||
|
||||
const reTransferDocument = useReTransferDocument();
|
||||
const reGenerateDraft = useReGenerateDraft();
|
||||
const reVerifyCost = useReVerifyCost();
|
||||
const isBusy =
|
||||
isProcessing ||
|
||||
reTransferDocument.isPending ||
|
||||
reGenerateDraft.isPending ||
|
||||
reVerifyCost.isPending;
|
||||
|
||||
const hasCompletedDraft = Boolean(findCompletedPwrkDraft(pwrkCnsltnData));
|
||||
const pwrkCnsltnDocNo = pwrkCnsltnData?.pwrkCnsltnDocNo;
|
||||
const pwrkCnsltnDocNo =
|
||||
pwrkCnsltnData?.pwrkCnsltnDocNo ??
|
||||
draftGenLatest?.pwrkCnsltnDocNo ??
|
||||
costVrfcLatest?.pwrkCnsltnDocNo;
|
||||
|
||||
const elaprPrgrsForPending =
|
||||
prgrsSttsComCd === "RK"
|
||||
@@ -146,18 +186,27 @@ function FloatingActionButtons({
|
||||
if (needsAtrzResolve && isRvwLoginUserLoading) return [];
|
||||
if (needsElaprPrgrsCheck && isElaprDocPrgrsLoading) return [];
|
||||
if (needsPwrkDraftCheck && isPwrkCnsltnLoading) return [];
|
||||
if (needsAiAutoLatest && isAiAutoLatestLoading) return [];
|
||||
return getButtonConfigs(dtlInstCd, prgrsSttsComCd, atrzSeComCdList, {
|
||||
hasPendingApprovalRequest: needsElaprPrgrsCheck ? hasPendingApprovalRequest : undefined,
|
||||
hasCompletedDraft: needsPwrkDraftCheck ? hasCompletedDraft : undefined,
|
||||
canRetryFileVrfc: needsAiAutoLatest ? canRetryFileVrfc : undefined,
|
||||
canRetryDraftGen: needsAiAutoLatest ? canRetryDraftGen : undefined,
|
||||
canRetryCostVrfc: needsAiAutoLatest ? canRetryCostVrfc : undefined,
|
||||
});
|
||||
}, [
|
||||
atrzSeComCdList,
|
||||
canRetryCostVrfc,
|
||||
canRetryDraftGen,
|
||||
canRetryFileVrfc,
|
||||
dtlInstCd,
|
||||
hasCompletedDraft,
|
||||
hasPendingApprovalRequest,
|
||||
isAiAutoLatestLoading,
|
||||
isElaprDocPrgrsLoading,
|
||||
isPwrkCnsltnLoading,
|
||||
isRvwLoginUserLoading,
|
||||
needsAiAutoLatest,
|
||||
needsAtrzResolve,
|
||||
needsElaprPrgrsCheck,
|
||||
needsPwrkDraftCheck,
|
||||
@@ -544,17 +593,60 @@ function FloatingActionButtons({
|
||||
});
|
||||
}
|
||||
|
||||
function handleFileVrfcClick() {
|
||||
reTransferDocument.mutate(
|
||||
{ fnrsCnsltnDocNo: docNo },
|
||||
{ onSuccess: () => alert("파일 검증을 요청했습니다.") },
|
||||
);
|
||||
}
|
||||
|
||||
function handlePwrkCnsltnDocCrtClick() {
|
||||
if (!pwrkCnsltnDocNo) {
|
||||
alert("실무협의 문서번호를 찾을 수 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
reGenerateDraft.mutate(
|
||||
{
|
||||
fnrsCnsltnDocNo: docNo,
|
||||
pwrkCnsltnDocNo,
|
||||
crtDmndUuid: draftGenLatest?.crtDmndUuid,
|
||||
},
|
||||
{ onSuccess: () => alert("초안 생성을 요청했습니다.") },
|
||||
);
|
||||
}
|
||||
|
||||
function handleCostVrfcClick() {
|
||||
if (!pwrkCnsltnDocNo) {
|
||||
alert("실무협의 문서번호를 찾을 수 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
reVerifyCost.mutate(
|
||||
{
|
||||
fnrsCnsltnDocNo: docNo,
|
||||
pwrkCnsltnDocNo,
|
||||
},
|
||||
{ onSuccess: () => alert("금액 검증을 요청했습니다.") },
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="sticky bottom-0 z-40 !-mb-2 border-t bg-white pb-8 pt-6 shadow-[0_-4px_12px_rgba(0,0,0,0.06)]">
|
||||
<div className="mx-4 flex flex-wrap justify-center gap-3 sm:gap-4">
|
||||
<Button color="white" type="button" onClick={handleGoToList} disabled={isProcessing}>
|
||||
<Button color="white" type="button" onClick={handleGoToList} disabled={isBusy}>
|
||||
목록
|
||||
</Button>
|
||||
{!isAiPending && (
|
||||
<>
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocCrt) && (
|
||||
<Button color="orange" onClick={() => {}} disabled={isProcessing}>
|
||||
<Button
|
||||
color="orange"
|
||||
onClick={handlePwrkCnsltnDocCrtClick}
|
||||
disabled={isBusy}
|
||||
title={draftGenLatest?.prcsErrCn ?? undefined}
|
||||
>
|
||||
실무협의서 초안 생성
|
||||
</Button>
|
||||
)}
|
||||
@@ -562,85 +654,103 @@ function FloatingActionButtons({
|
||||
<Button
|
||||
color="orange"
|
||||
onClick={() => setActiveDialog("pwrkCnsltnDocMng")}
|
||||
disabled={isProcessing}
|
||||
disabled={isBusy}
|
||||
>
|
||||
실무협의서 관리
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{canEdit && (
|
||||
<Button color="gray" onClick={handleEdit} disabled={isProcessing}>
|
||||
<Button color="gray" onClick={handleEdit} disabled={isBusy}>
|
||||
수정
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.strg) && (
|
||||
<Button onClick={handleStrgClick} disabled={isProcessing}>
|
||||
<Button onClick={handleStrgClick} disabled={isBusy}>
|
||||
저장
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.aply) && (
|
||||
<Button color="green" onClick={handleAplyClick} disabled={isProcessing}>
|
||||
<Button color="green" onClick={handleAplyClick} disabled={isBusy}>
|
||||
신청 완료
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.del) && (
|
||||
<Button color="red" onClick={handleDelClick} disabled={isProcessing}>
|
||||
<Button color="red" onClick={handleDelClick} disabled={isBusy}>
|
||||
삭제
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.envoSbmsn) && (
|
||||
<Button onClick={handleEnvoSbmsnClick} disabled={isProcessing}>
|
||||
<Button onClick={handleEnvoSbmsnClick} disabled={isBusy}>
|
||||
환경청 제출
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.rjct) && (
|
||||
<Button color="red" onClick={handleRjctClick} disabled={isProcessing}>
|
||||
<Button color="red" onClick={handleRjctClick} disabled={isBusy}>
|
||||
반려
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.sncnAprv) && (
|
||||
<Button color="green" onClick={handleSncnAprvClick} disabled={isProcessing}>
|
||||
<Button color="green" onClick={handleSncnAprvClick} disabled={isBusy}>
|
||||
결과 회신
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.rvwOpnnRply) && (
|
||||
<Button onClick={handleRvwOpnnRplyClick} disabled={isProcessing}>
|
||||
<Button onClick={handleRvwOpnnRplyClick} disabled={isBusy}>
|
||||
검토 의견 회신
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.rvwRply) && (
|
||||
<Button color="green" onClick={handleRvwRplyClick} disabled={isProcessing}>
|
||||
<Button color="green" onClick={handleRvwRplyClick} disabled={isBusy}>
|
||||
검토 결과 회신
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.rqstTechRvw) && (
|
||||
<Button onClick={handleRqstTechRvwClick} disabled={isProcessing}>
|
||||
<Button onClick={handleRqstTechRvwClick} disabled={isBusy}>
|
||||
기술 검토 의뢰
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.rqstActnRvw) && (
|
||||
<Button onClick={handleRqstActnRvwClick} disabled={isProcessing}>
|
||||
<Button onClick={handleRqstActnRvwClick} disabled={isBusy}>
|
||||
조치 결과 검토 의뢰
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.fileSplmnt) && (
|
||||
<Button color="gray" onClick={handleFileSplmntClick} disabled={isProcessing}>
|
||||
<Button color="gray" onClick={handleFileSplmntClick} disabled={isBusy}>
|
||||
파일 보완 요청
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.fileVrfc) && (
|
||||
<Button
|
||||
onClick={handleFileVrfcClick}
|
||||
disabled={isBusy}
|
||||
title={fileVrfcLatest?.prcsErrCn ?? undefined}
|
||||
>
|
||||
파일 검증
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.dsgntRvwr) &&
|
||||
!isRagIndexingInProgress(prgrsSttsComCd, data.ragIndexingInfo) && (
|
||||
<Button
|
||||
onClick={() =>
|
||||
setActiveDialog(prgrsSttsComCd === "EV" ? "elaprDocPrgrs" : "elaprTmplt")
|
||||
}
|
||||
disabled={isProcessing}
|
||||
disabled={isBusy}
|
||||
>
|
||||
검토자 지정
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.costVrfc) && (
|
||||
<Button
|
||||
onClick={handleCostVrfcClick}
|
||||
disabled={isBusy}
|
||||
title={costVrfcLatest?.prcsErrCn ?? undefined}
|
||||
>
|
||||
금액 검증
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.actnCmptn) && (
|
||||
<Button color="green" onClick={handleActnCmptnClick} disabled={isProcessing}>
|
||||
<Button color="green" onClick={handleActnCmptnClick} disabled={isBusy}>
|
||||
조치 완료
|
||||
</Button>
|
||||
)}
|
||||
@@ -648,18 +758,18 @@ function FloatingActionButtons({
|
||||
<Button
|
||||
color="sky"
|
||||
onClick={() => setActiveDialog("rvwRsltInq")}
|
||||
disabled={isProcessing}
|
||||
disabled={isBusy}
|
||||
>
|
||||
검토 결과 조회
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.rvwStrg) && (
|
||||
<Button onClick={handleRvwStrgClick} disabled={isProcessing}>
|
||||
<Button onClick={handleRvwStrgClick} disabled={isBusy}>
|
||||
저장
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.rvwCmptn) && (
|
||||
<Button color="green" onClick={handleRvwCmptnClick} disabled={isProcessing}>
|
||||
<Button color="green" onClick={handleRvwCmptnClick} disabled={isBusy}>
|
||||
검토 완료
|
||||
</Button>
|
||||
)}
|
||||
@@ -667,18 +777,18 @@ function FloatingActionButtons({
|
||||
<Button
|
||||
color="gray"
|
||||
onClick={() => setActiveDialog("dmndSplmnt")}
|
||||
disabled={isProcessing}
|
||||
disabled={isBusy}
|
||||
>
|
||||
보완 요청
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.atrzAprv) && (
|
||||
<Button onClick={() => setActiveDialog("elaprApproval")} disabled={isProcessing}>
|
||||
<Button onClick={() => setActiveDialog("elaprApproval")} disabled={isBusy}>
|
||||
결재(승인)
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.atrzRply) && (
|
||||
<Button onClick={() => setActiveDialog("elaprApproval")} disabled={isProcessing}>
|
||||
<Button onClick={() => setActiveDialog("elaprApproval")} disabled={isBusy}>
|
||||
결재(회신)
|
||||
</Button>
|
||||
)}
|
||||
@@ -707,14 +817,14 @@ function FloatingActionButtons({
|
||||
splmntArtclUpCd="SPLMNTARTCL"
|
||||
open={activeDialog === "dmndSplmnt"}
|
||||
onOpenChange={() => setActiveDialog(null)}
|
||||
isSubmitting={isProcessing}
|
||||
isSubmitting={isBusy}
|
||||
onConfirm={handleDmndSplmntConfirm}
|
||||
/>
|
||||
|
||||
<FileVrfcSplmntDialog
|
||||
open={activeDialog === "fileSplmnt"}
|
||||
fnrsCnsltnDocNo={docNo}
|
||||
isSubmitting={isProcessing}
|
||||
isSubmitting={isBusy}
|
||||
onClose={() => setActiveDialog(null)}
|
||||
onConfirm={handleFileSplmntConfirm}
|
||||
/>
|
||||
@@ -748,7 +858,7 @@ function FloatingActionButtons({
|
||||
<PwrkCnsltnRvwRsltInqDialog
|
||||
open={activeDialog === "rvwRsltInq"}
|
||||
fnrsCnsltnDocNo={docNo}
|
||||
isSubmitting={isProcessing}
|
||||
isSubmitting={isBusy}
|
||||
onClose={() => setActiveDialog(null)}
|
||||
onConfirm={handleRvwRsltSplmntConfirm}
|
||||
/>
|
||||
@@ -883,6 +993,7 @@ const buttonActionHandlers: Record<FnrsCnsltnViewButtonAction, ActionHandler> =
|
||||
rvwOpnnRply: handleTechReview,
|
||||
rqstTechRvw: handleRequestExamine,
|
||||
fileSplmnt: handleDmndSplmnt,
|
||||
fileVrfc: () => Promise.resolve(),
|
||||
dsgntRvwr: handleDsgntRvwr,
|
||||
pwrkCnsltnDocCrt: () => Promise.resolve(),
|
||||
pwrkCnsltnDocMng: () => Promise.resolve(),
|
||||
@@ -894,6 +1005,7 @@ const buttonActionHandlers: Record<FnrsCnsltnViewButtonAction, ActionHandler> =
|
||||
atrzRply: () => Promise.resolve(),
|
||||
actnCmptn: handleActnCmptn,
|
||||
rqstActnRvw: handleRequestActnReview,
|
||||
costVrfc: () => Promise.resolve(),
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
||||
@@ -26,6 +26,7 @@ export const ENDPOINT = {
|
||||
SEWER_BSC_PLAN: "/as-service/api/v1/sewer-bsc-plans",
|
||||
DASHBOARD: "/as-service/api/v1/dashboard",
|
||||
DCRAG_TO: "/as-service/api/v1/dcrag-to",
|
||||
AI_AUTO_PRCS_MNG: "/as-service/api/v1/ai-auto-prcs-mng",
|
||||
PWRK_CNSLTN_MNG: "/as-service/api/v1/pwrk-cnsltn-mng",
|
||||
PWRK_CNSLTN_DOC_CRT_RSLT: "/as-service/api/v1/pwrk-cnsltn-doc-crt-rslt",
|
||||
PWRK_CNSLTN_DOC_PJTCO_AJMT_MNG: "/as-service/api/v1/pwrk-cnsltn-doc-pjtco-ajmt-mng",
|
||||
|
||||
Reference in New Issue
Block a user