[as frontend] taskSeComCd 다중체크 처리 로직 구현

This commit is contained in:
2026-06-02 17:01:33 +09:00
parent 9a8350dae8
commit b2282accb1
2 changed files with 57 additions and 19 deletions
@@ -71,15 +71,15 @@ function CnfmListPage() {
const [pageIndex, setPageIndex] = useState(0);
const [pageSize, setPageSize] = useState(10);
const [taskDialogOpen, setTaskDialogOpen] = useState(false);
const [selectedTaskSeComCd, setSelectedTaskSeComCd] = useState("");
const [selectedTaskSeComCd, setSelectedTaskSeComCd] = useState<string[]>([]);
const { data: fnrsCodeList = [] } = useCodeList("INSTL");
useEffect(() => {
if (!taskDialogOpen) return;
if (selectedTaskSeComCd) return;
if (fnrsCodeList.length === 0) return;
setSelectedTaskSeComCd(fnrsCodeList[0].lwpoCd);
if (selectedTaskSeComCd.length) return;
if (fnrsCodeList.length === 0) return;
// setSelectedTaskSeComCd([fnrsCodeList[0].lwpoCd]);
}, [taskDialogOpen, selectedTaskSeComCd, fnrsCodeList]);
const query = useQuery({
@@ -108,20 +108,25 @@ function CnfmListPage() {
};
const handleOpenTaskDialog = () => {
setSelectedTaskSeComCd((prev) => prev || fnrsCodeList[0]?.lwpoCd || "");
//setSelectedTaskSeComCd((prev) => (prev && prev.length ? prev : [fnrsCodeList[0]?.lwpoCd || ""]));
setTaskDialogOpen(true);
};
const handleConfirmTaskDialog = () => {
const selected = fnrsCodeList.find((item) => item.lwpoCd === selectedTaskSeComCd);
if (!selected) return;
if (!selectedTaskSeComCd || selectedTaskSeComCd.length === 0) {
alert("하나 이상의 업무구분을 선택하세요.");
return;
}
// prepare arrays of selected codes and names
const selectedCodes = selectedTaskSeComCd;
const selectedNames = selectedTaskSeComCd.map((code) => fnrsCodeList.find((item) => item.lwpoCd === code)?.lwpoCdNm || "");
sessionStorage.setItem(
INSTL_SNCN_REGISTER_SELECTION_KEY,
JSON.stringify({
taskSeComCd: selected.lwpoCd,
taskSeComCdNm: selected.lwpoCdNm,
}),
taskSeComCdList: selectedCodes,
taskSeComCdNmList: selectedNames
})
);
setTaskDialogOpen(false);
router.push("/instl-sncn/register");
@@ -367,11 +372,15 @@ function CnfmListPage() {
{fnrsCodeList.map((item) => (
<label key={item.lwpoCd} className="flex cursor-pointer items-center gap-2">
<input
type="radio"
type="checkbox"
name="taskSeComCdSelect"
value={item.lwpoCd}
checked={selectedTaskSeComCd === item.lwpoCd}
onChange={() => setSelectedTaskSeComCd(item.lwpoCd)}
checked={selectedTaskSeComCd.includes(item.lwpoCd)}
onChange={() => {
setSelectedTaskSeComCd((prev) =>
prev.includes(item.lwpoCd) ? prev.filter((v) => v !== item.lwpoCd) : [...prev, item.lwpoCd],
);
}}
/>
{item.lwpoCdNm}
</label>
@@ -387,11 +396,11 @@ function CnfmListPage() {
>
취소
</button>
<button
<button
type="button"
className="rounded bg-blue-500 px-5 py-2 text-[1.3rem] font-semibold text-white hover:bg-blue-600 disabled:cursor-not-allowed disabled:bg-gray-300"
onClick={handleConfirmTaskDialog}
disabled={!selectedTaskSeComCd}
disabled={!selectedTaskSeComCd || selectedTaskSeComCd.length === 0}
>
확인
</button>
@@ -203,9 +203,13 @@ function CnfmRegistPage({ initialData }: { initialData?: any } = {}) {
if (!raw) return;
try {
const parsed = JSON.parse(raw) as { taskSeComCd?: string; taskSeComCdNm?: string };
setTaskSeComCd(parsed.taskSeComCd || "RE");
setTaskSeComCdNm(parsed.taskSeComCdNm || "재이용수");
const parsed = JSON.parse(raw) as {
taskSeComCdList?: string[];
taskSeComCdNmList?: string[];
};
setTaskSeComCd(parsed.taskSeComCdList?.join(",") || "RE");
setTaskSeComCdNm(parsed.taskSeComCdNmList?.join(",") || "재이용수");
} catch {
// noop
} finally {
@@ -603,13 +607,38 @@ function CnfmRegistPage({ initialData }: { initialData?: any } = {}) {
const { data: cklstTree = [] } = useQuery<CklstTreeNode[]>({
queryKey: ["cklstTree", docSeComCd, taskSeComCd],
queryFn: () => cklstMngService.findTree({ docSeComCd, taskSeComCd }),
queryFn: async () => {
// support comma-separated task codes (e.g. "RE,SP") by splitting
const raw = taskSeComCd ?? "";
const codes = raw
.split(",")
.map((s) => s.trim())
.filter(Boolean);
if (codes.length === 0) return [] as CklstTreeNode[];
if (codes.length === 1) {
return await cklstMngService.findTree({ docSeComCd, taskSeComCd: codes[0] });
}
const results = await Promise.all(
codes.map((code) => cklstMngService.findTree({ docSeComCd, taskSeComCd: code })),
);
const flat = results.flat();
// dedupe by cklstRvwSn, keep first occurrence
const map = new Map<number, CklstTreeNode>();
for (const row of flat) {
if (!map.has(row.cklstRvwSn)) map.set(row.cklstRvwSn, row);
}
return Array.from(map.values());
},
enabled: Boolean(docSeComCd) && Boolean(taskSeComCd),
staleTime: Infinity,
});
const cklstRows = useMemo(() => {
// bchckUseYn 필터 제거: 부모가 있는 자식 노드(bchckUseYn=N)도 트리에 포함
// cklstTree 내의 피드 taskSeComCd 에 따라서 그룹핑 되도록 해줘
const useRows = cklstTree;
if (useRows.length === 0) return [] as CklstTreeNode[];