[st] feat: 입력 저장/제출 로직 수정, 통계입력관리, 검토 반려/제출
This commit is contained in:
@@ -918,9 +918,17 @@ const DataGrid = ({
|
||||
rowIndicator: { visible: false },
|
||||
});
|
||||
|
||||
// footer가 있는 컬럼이 있으면 footer 높이 설정
|
||||
const hasFooter = columns.some((col) => col.footer);
|
||||
if (hasFooter) {
|
||||
const applyFooterSettings = (
|
||||
targetGridView: typeof gridView,
|
||||
) => {
|
||||
const hasFooter = columns.some((col) => col.footer);
|
||||
if (!hasFooter) return;
|
||||
|
||||
targetGridView.setOptions({
|
||||
summaryMode: "aggregate",
|
||||
footer: { visible: true },
|
||||
});
|
||||
|
||||
// footer가 배열이거나 multiRow가 true인 footer가 있으면 멀티푸터 설정 (여러 행)
|
||||
const hasArrayFooter = columns.some(
|
||||
(col) => col.footer && Array.isArray(col.footer),
|
||||
@@ -935,23 +943,24 @@ const DataGrid = ({
|
||||
);
|
||||
});
|
||||
if (hasArrayFooter || hasMultiRowFooter) {
|
||||
// footer 배열의 길이를 확인하여 행 수 결정
|
||||
const arrayFooterLengths = columns
|
||||
.filter((col) => col.footer && Array.isArray(col.footer))
|
||||
.map((col) => (col.footer as unknown[]).length);
|
||||
const maxFooterLength =
|
||||
arrayFooterLengths.length > 0
|
||||
? Math.max(...arrayFooterLengths)
|
||||
: 2; // 기본값 2
|
||||
: 2;
|
||||
const footerHeights = Array.from(
|
||||
{ length: maxFooterLength },
|
||||
() => ({ height: 40 }),
|
||||
);
|
||||
gridView.setFooters?.(footerHeights);
|
||||
targetGridView.setFooters?.(footerHeights);
|
||||
} else {
|
||||
gridView.footer.height = 40;
|
||||
targetGridView.footer.height = 40;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
applyFooterSettings(gridView);
|
||||
|
||||
// 고정 컬럼 설정
|
||||
if (fixedColumns !== undefined && fixedColumns > 0) {
|
||||
@@ -960,10 +969,6 @@ const DataGrid = ({
|
||||
});
|
||||
}
|
||||
|
||||
gridView.setOptions({
|
||||
summaryMode: "aggregate",
|
||||
});
|
||||
|
||||
// footerUserSpans가 있는 경우 setColumnLayout으로 설정
|
||||
const checkFooterUserSpans = (layout: unknown[]): boolean => {
|
||||
return layout.some((item) => {
|
||||
@@ -986,7 +991,9 @@ const DataGrid = ({
|
||||
});
|
||||
};
|
||||
|
||||
if (checkFooterUserSpans(columnLayout)) {
|
||||
const hasFooterUserSpans = checkFooterUserSpans(columnLayout);
|
||||
|
||||
if (hasFooterUserSpans) {
|
||||
// setColumnLayout은 그리드가 완전히 렌더링된 후 호출해야 함
|
||||
setTimeout(() => {
|
||||
if (gridRef.current?.gridView && columnLayout) {
|
||||
@@ -1049,6 +1056,10 @@ const DataGrid = ({
|
||||
(currentGridView as GridViewWithSetColumns).setColumns?.(
|
||||
columnsWithFooter,
|
||||
);
|
||||
applyFooterSettings(currentGridView);
|
||||
if (hasFooterUserSpans) {
|
||||
currentGridView.setColumnLayout?.(columnLayout);
|
||||
}
|
||||
|
||||
// setColumns 호출 후 footer 배열의 valueCallback을 다시 설정
|
||||
setTimeout(() => {
|
||||
@@ -1089,6 +1100,11 @@ const DataGrid = ({
|
||||
);
|
||||
}
|
||||
});
|
||||
applyFooterSettings(currentGridView);
|
||||
if (hasFooterUserSpans) {
|
||||
currentGridView.setColumnLayout?.(columnLayout);
|
||||
}
|
||||
currentGridView.refresh?.();
|
||||
}, 50);
|
||||
} catch (e) {
|
||||
console.warn("Failed to set columns with footer array:", e);
|
||||
|
||||
@@ -109,6 +109,8 @@ export interface VerificationResultDialogProps {
|
||||
queryContext?: VerificationResultDialogQueryContext | null;
|
||||
title?: string;
|
||||
emptyMessage?: string;
|
||||
/** 예외 제출 API 성공 후 부모(입력 화면)에서 메인 데이터를 다시 조회할 때 사용 */
|
||||
onExceptionSubmitted?: () => void | Promise<void>;
|
||||
}
|
||||
|
||||
export function VerificationResultDialog({
|
||||
@@ -117,6 +119,7 @@ export function VerificationResultDialog({
|
||||
queryContext,
|
||||
title = "검증 결과",
|
||||
emptyMessage = "표시할 검증 결과가 없습니다.",
|
||||
onExceptionSubmitted,
|
||||
}: VerificationResultDialogProps) {
|
||||
/** 부모가 매 렌더마다 새 객체를 넘기면 queryContext 참조만 바뀌어 loadInitial이 재실행되므로 필드 값 기준으로 안정화 */
|
||||
const stableQueryContext = useMemo((): VerificationResultDialogQueryContext | null => {
|
||||
@@ -385,6 +388,11 @@ export function VerificationResultDialog({
|
||||
});
|
||||
if (response.status === "success") {
|
||||
alert("예외 제출 처리되었습니다.");
|
||||
try {
|
||||
await onExceptionSubmitted?.();
|
||||
} catch {
|
||||
alert("예외 제출은 완료되었으나 화면 데이터를 다시 불러오지 못했습니다. 조회로 새로고침 해주세요.");
|
||||
}
|
||||
onOpenChange(false);
|
||||
} else {
|
||||
alert(response.message ?? "예외 제출 처리 중 오류가 발생했습니다.");
|
||||
@@ -396,9 +404,10 @@ export function VerificationResultDialog({
|
||||
alert,
|
||||
imrCheckedIndices,
|
||||
imrRows,
|
||||
loadInitial,
|
||||
normalCheckedIndices,
|
||||
normalRows,
|
||||
onExceptionSubmitted,
|
||||
onOpenChange,
|
||||
stableQueryContext,
|
||||
]);
|
||||
|
||||
|
||||
@@ -24,12 +24,12 @@ import { VerificationResultHistoryPagination } from "@/components/module/Verific
|
||||
import type { CellStyleCallbackParams, ColumnInfo } from "@/components/type/DataGrid.type";
|
||||
|
||||
type VerificationResultGridRow = Record<string, string | number>;
|
||||
type VerificationHistoryTabKey = "NV" | "IMR" | "HR";
|
||||
type VerificationHistoryTabKey = "NV" | "IMR" | "HB";
|
||||
|
||||
const verificationHistoryTabs: { value: VerificationHistoryTabKey; label: string }[] = [
|
||||
{ value: "NV", label: "일반검증 내역" },
|
||||
{ value: "IMR", label: "I-MR 검증내역" },
|
||||
{ value: "HR", label: "HR 검증내역" },
|
||||
{ value: "HB", label: "HB 검증내역" },
|
||||
];
|
||||
|
||||
function prcsYnCodeToNumber(raw: string | number | undefined): number | undefined {
|
||||
@@ -90,32 +90,32 @@ export function VerificationResultHistoryDialog({
|
||||
const [activeTab, setActiveTab] = useState<VerificationHistoryTabKey>("NV");
|
||||
const [normalEntries, setNormalEntries] = useState<VerificationResultReportItem[]>([]);
|
||||
const [imrEntries, setImrEntries] = useState<VerificationResultReportItem[]>([]);
|
||||
const [hrEntries, setHrEntries] = useState<VerificationResultReportItem[]>([]);
|
||||
const [hbEntries, setHbEntries] = useState<VerificationResultReportItem[]>([]);
|
||||
const [normalPageIndex, setNormalPageIndex] = useState(0);
|
||||
const [imrPageIndex, setImrPageIndex] = useState(0);
|
||||
const [hrPageIndex, setHrPageIndex] = useState(0);
|
||||
const [hbPageIndex, setHbPageIndex] = useState(0);
|
||||
const [normalPageCount, setNormalPageCount] = useState(1);
|
||||
const [imrPageCount, setImrPageCount] = useState(1);
|
||||
const [hrPageCount, setHrPageCount] = useState(1);
|
||||
const [hbPageCount, setHbPageCount] = useState(1);
|
||||
const [normalLoading, setNormalLoading] = useState(false);
|
||||
const [imrLoading, setImrLoading] = useState(false);
|
||||
const [hrLoading, setHrLoading] = useState(false);
|
||||
const [hbLoading, setHbLoading] = useState(false);
|
||||
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
||||
|
||||
const resetState = useCallback(() => {
|
||||
setActiveTab("NV");
|
||||
setNormalEntries([]);
|
||||
setImrEntries([]);
|
||||
setHrEntries([]);
|
||||
setHbEntries([]);
|
||||
setNormalPageIndex(0);
|
||||
setImrPageIndex(0);
|
||||
setHrPageIndex(0);
|
||||
setHbPageIndex(0);
|
||||
setNormalPageCount(1);
|
||||
setImrPageCount(1);
|
||||
setHrPageCount(1);
|
||||
setHbPageCount(1);
|
||||
setNormalLoading(false);
|
||||
setImrLoading(false);
|
||||
setHrLoading(false);
|
||||
setHbLoading(false);
|
||||
setErrorMessage(null);
|
||||
}, []);
|
||||
|
||||
@@ -147,34 +147,34 @@ export function VerificationResultHistoryDialog({
|
||||
setErrorMessage(null);
|
||||
setNormalLoading(true);
|
||||
setImrLoading(true);
|
||||
setHrLoading(true);
|
||||
setHbLoading(true);
|
||||
setNormalPageIndex(0);
|
||||
setImrPageIndex(0);
|
||||
setHrPageIndex(0);
|
||||
setHbPageIndex(0);
|
||||
try {
|
||||
const [nvRes, imrRes, hrRes] = await Promise.all([
|
||||
const [nvRes, imrRes, hbRes] = await Promise.all([
|
||||
fetchVerificationResultPage("NV", 0),
|
||||
fetchVerificationResultPage("IMR", 0),
|
||||
fetchVerificationResultPage("HR", 0),
|
||||
fetchVerificationResultPage("HB", 0),
|
||||
]);
|
||||
setNormalEntries(nvRes?.data?.verifyResultList ?? []);
|
||||
setImrEntries(imrRes?.data?.verifyResultList ?? []);
|
||||
setHrEntries(hrRes?.data?.verifyResultList ?? []);
|
||||
setHbEntries(hbRes?.data?.verifyResultList ?? []);
|
||||
setNormalPageCount(nvRes?.data?.pageInfo?.totalPages ?? 1);
|
||||
setImrPageCount(imrRes?.data?.pageInfo?.totalPages ?? 1);
|
||||
setHrPageCount(hrRes?.data?.pageInfo?.totalPages ?? 1);
|
||||
setHbPageCount(hbRes?.data?.pageInfo?.totalPages ?? 1);
|
||||
} catch {
|
||||
setNormalEntries([]);
|
||||
setImrEntries([]);
|
||||
setHrEntries([]);
|
||||
setHbEntries([]);
|
||||
setNormalPageCount(1);
|
||||
setImrPageCount(1);
|
||||
setHrPageCount(1);
|
||||
setHbPageCount(1);
|
||||
setErrorMessage("검증 결과 내역 조회 중 오류가 발생했습니다.");
|
||||
} finally {
|
||||
setNormalLoading(false);
|
||||
setImrLoading(false);
|
||||
setHrLoading(false);
|
||||
setHbLoading(false);
|
||||
}
|
||||
}, [fetchVerificationResultPage, queryContext]);
|
||||
|
||||
@@ -216,23 +216,23 @@ export function VerificationResultHistoryDialog({
|
||||
[fetchVerificationResultPage, imrPageIndex, queryContext],
|
||||
);
|
||||
|
||||
const handleHrPageChange = useCallback(
|
||||
const handleHbPageChange = useCallback(
|
||||
async (pageIndex: number) => {
|
||||
if (pageIndex === hrPageIndex || !queryContext) return;
|
||||
if (pageIndex === hbPageIndex || !queryContext) return;
|
||||
setErrorMessage(null);
|
||||
setHrLoading(true);
|
||||
setHbLoading(true);
|
||||
try {
|
||||
const response = await fetchVerificationResultPage("HR", pageIndex);
|
||||
setHrEntries(response?.data?.verifyResultList ?? []);
|
||||
setHrPageCount(response?.data?.pageInfo?.totalPages ?? 1);
|
||||
setHrPageIndex(pageIndex);
|
||||
const response = await fetchVerificationResultPage("HB", pageIndex);
|
||||
setHbEntries(response?.data?.verifyResultList ?? []);
|
||||
setHbPageCount(response?.data?.pageInfo?.totalPages ?? 1);
|
||||
setHbPageIndex(pageIndex);
|
||||
} catch {
|
||||
setErrorMessage("HR 검증내역 조회 중 오류가 발생했습니다.");
|
||||
setErrorMessage("HB 검증내역 조회 중 오류가 발생했습니다.");
|
||||
} finally {
|
||||
setHrLoading(false);
|
||||
setHbLoading(false);
|
||||
}
|
||||
},
|
||||
[fetchVerificationResultPage, hrPageIndex, queryContext],
|
||||
[fetchVerificationResultPage, hbPageIndex, queryContext],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -260,7 +260,7 @@ export function VerificationResultHistoryDialog({
|
||||
|
||||
const normalRows = useMemo(() => mapRows(normalEntries), [normalEntries]);
|
||||
const imrRows = useMemo(() => mapRows(imrEntries), [imrEntries]);
|
||||
const hrRows = useMemo(() => mapRows(hrEntries), [hrEntries]);
|
||||
const hbRows = useMemo(() => mapRows(hbEntries), [hbEntries]);
|
||||
|
||||
const noopSetRows = ((_: SetStateAction<Record<string, string | number>[]>) => {}) as Dispatch<
|
||||
SetStateAction<Record<string, string | number>[]>
|
||||
@@ -332,8 +332,8 @@ export function VerificationResultHistoryDialog({
|
||||
<TabsContent value="IMR" className="rounded-md border border-border">
|
||||
{renderGrid(imrRows, imrPageIndex, imrPageCount, handleImrPageChange, imrLoading)}
|
||||
</TabsContent>
|
||||
<TabsContent value="HR" className="rounded-md border border-border">
|
||||
{renderGrid(hrRows, hrPageIndex, hrPageCount, handleHrPageChange, hrLoading)}
|
||||
<TabsContent value="HB" className="rounded-md border border-border">
|
||||
{renderGrid(hbRows, hbPageIndex, hbPageCount, handleHbPageChange, hbLoading)}
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user