dm: 수요정보 등록 유사사례 관련 주석 추가
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
// apps/dm/app/(landing)/reuse/apply/modal/SimilarCaseModal.tsx (유사사례 모달)
|
||||
/**
|
||||
* 유사사례 Modal
|
||||
*/
|
||||
"use client";
|
||||
|
||||
import { useEffect, useMemo, useState, useId } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
|
||||
type Criterion = "" | "supplyAmt" | "treatment" | "usePurpose";
|
||||
type Criterion = "" | "supplyAmt" | "treatment" | "usePurpose"; // 유사기준
|
||||
|
||||
export type SimilarCaseRow = {
|
||||
caseId: string;
|
||||
@@ -90,7 +92,7 @@ export default function SimilarCaseModal({
|
||||
// 모달 열릴 때 초기화
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
setCriterion("supplyAmt");
|
||||
setCriterion("supplyAmt"); // 요구수량(㎥/d)
|
||||
onSearch("supplyAmt");
|
||||
setSelectedCaseId("");
|
||||
}, [open]);
|
||||
|
||||
@@ -36,9 +36,9 @@ export default function DemandRegisterPage() {
|
||||
|
||||
// 기본정보
|
||||
const [reqDate, setReqDate] = useState<string>(today);
|
||||
const [reqQty, setReqQty] = useState<string>("");
|
||||
const [usePurpose, setUsePurpose] = useState<string>("");
|
||||
const [hopePrice, setHopePrice] = useState<string>("");
|
||||
const [reqQty, setReqQty] = useState<string>(""); // 요구수량(㎥/d)
|
||||
const [usePurpose, setUsePurpose] = useState<string>(""); // 사용용도
|
||||
const [hopePrice, setHopePrice] = useState<string>(""); // 희망단가
|
||||
|
||||
// 요구수질
|
||||
const [coliform, setColiform] = useState<string>(""); // 총대장균군수
|
||||
@@ -62,9 +62,9 @@ export default function DemandRegisterPage() {
|
||||
const [cand3, setCand3] = useState("");
|
||||
//const [candidateList, setCandidateList] = useState<SubsInfo[]>([]);
|
||||
|
||||
const useTypesData = useDmStore((state) => state.Sdm.useTypesData);
|
||||
const getUseTypesData = useDmStore((state) => state.getUseTypesData);
|
||||
const [openSimilar, setOpenSimilar] = useState(false);
|
||||
const useTypesData = useDmStore((state) => state.Sdm.useTypesData); // 사용용도
|
||||
const getUseTypesData = useDmStore((state) => state.getUseTypesData); // 사용용도 함수
|
||||
const [openSimilar, setOpenSimilar] = useState(false); // 유사사례 modal open
|
||||
|
||||
// 후보지 팝업 메시지 핸들러
|
||||
const candsRef = useRef<{ name: string; code: string }[]>([]);
|
||||
@@ -114,15 +114,16 @@ export default function DemandRegisterPage() {
|
||||
const getSimilarCaseList = useDmStore((state) => state.getSimilarCaseList);
|
||||
const [farmText, setFarmText] = useState("이하");
|
||||
|
||||
const insertSdmInfoData = useDmStore(
|
||||
(state) => state.insertSdmInfoData
|
||||
);
|
||||
const insertSdmInfoData = useDmStore( (state) => state.insertSdmInfoData ); // 수요정보등록
|
||||
|
||||
useEffect(() => {
|
||||
getUseTypesData();
|
||||
getUseTypesData(); // 사용용도 조회
|
||||
}, [getUseTypesData]);
|
||||
|
||||
// 후보지 선택 팝업이 window.postMessage로 넘긴 선택 결과를 받아
|
||||
// 현재 화면의 후보지 입력칸(cand1~3)에 반영한다.
|
||||
useEffect(() => {
|
||||
// message 이벤트의 payload를 읽어 후보지 목록 상태를 갱신하는 핸들러
|
||||
const handler = (event: MessageEvent) => {
|
||||
if (!event.data) return;
|
||||
|
||||
@@ -199,25 +200,26 @@ export default function DemandRegisterPage() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 유사사례
|
||||
const rows: SimilarCaseRow[] = similarCaseList.map((el, idx) => ({
|
||||
caseId: String(idx),
|
||||
projectName: el.ruseBizNm,
|
||||
period: `${el.bizBgngDate} ~ ${el.bizEndDate}`,
|
||||
projectName: el.ruseBizNm, // 사업명
|
||||
period: `${el.bizBgngDate} ~ ${el.bizEndDate}`, // 사업기간
|
||||
|
||||
supplyFacilityType: el.splyFcltKnd,
|
||||
supplyName: el.splyFcltNm,
|
||||
supplyCapacity: Number(el.splyFcltCpct),
|
||||
supplyFacilityType: el.splyFcltKnd, // 시설종류
|
||||
supplyName: el.splyFcltNm, // 공급처명
|
||||
supplyCapacity: Number(el.splyFcltCpct), // 공급처 시설용량
|
||||
|
||||
demandName: el.dmdFcltNm,
|
||||
demandAddress: el.dmdFcltAddr,
|
||||
demandName: el.dmdFcltNm, // 수요처명
|
||||
demandAddress: el.dmdFcltAddr, // 수요처 주소
|
||||
|
||||
facilityCapacity: Number(el.ruseFcltCpct),
|
||||
pipeKm: Number(el.ruseFcltPplLen),
|
||||
purpose: el.ruseFcltUsg,
|
||||
facilityCapacity: Number(el.ruseFcltCpct), // 재이용시설 시설용량
|
||||
pipeKm: Number(el.ruseFcltPplLen), // 재이용시설 관로길이
|
||||
purpose: el.ruseFcltUsg, // 재이용시설 용도
|
||||
|
||||
supplyAmt: Number(el.ruseFcltSplyCpct),
|
||||
treatment: el.ruseFcltPrcsMsrc,
|
||||
usePurpose: el.ruseFcltUsg,
|
||||
supplyAmt: Number(el.ruseFcltSplyCpct), // 재이용시설 공급(용)량
|
||||
treatment: el.ruseFcltPrcsMsrc, // 재이용시설 처리공법
|
||||
usePurpose: el.ruseFcltUsg, // 재이용시설 용도
|
||||
}));
|
||||
|
||||
const detailsByCaseId: Record<string, SimilarCaseDetail> = {};
|
||||
@@ -311,6 +313,7 @@ export default function DemandRegisterPage() {
|
||||
}
|
||||
}
|
||||
|
||||
// 후보지 조회 팝업 Open
|
||||
const searchCandidate = (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -327,28 +330,27 @@ export default function DemandRegisterPage() {
|
||||
window.open(url, "candidatePopup", popupOptions);
|
||||
};
|
||||
|
||||
// 유사기준
|
||||
const getCriterionCode = (criterion: string) => {
|
||||
switch (criterion) {
|
||||
case "supplyAmt":
|
||||
return "S";
|
||||
case "money":
|
||||
return "M";
|
||||
case "usePurpose":
|
||||
return "U";
|
||||
default:
|
||||
return "";
|
||||
case "supplyAmt": return "S"; // 공급량
|
||||
case "money": return "M"; // 단가?
|
||||
case "usePurpose": return "U"; // 이용용도
|
||||
default: return "";
|
||||
}
|
||||
};
|
||||
|
||||
// 유사사례 Modal Open
|
||||
const searchSimilarCase = async (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setOpenSimilar(true);
|
||||
};
|
||||
|
||||
// 수요정보 입력란 초기화
|
||||
const initQualityForm = () => {
|
||||
setColiform("");
|
||||
setNoDetect(false);
|
||||
setNoDetect(false); // 총대장균군수 불검출
|
||||
setTn("");
|
||||
setResidualCl("");
|
||||
setTp("");
|
||||
@@ -363,6 +365,7 @@ export default function DemandRegisterPage() {
|
||||
setFarmText("이하");
|
||||
}
|
||||
|
||||
// 사용용도별 초기화
|
||||
const fncSetOptionValue = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
const value = e.target.value;
|
||||
initQualityForm();
|
||||
@@ -640,19 +643,20 @@ export default function DemandRegisterPage() {
|
||||
{/* 후보지 선택 */}
|
||||
<div className="grid grid-cols-12">
|
||||
<LabelCell>
|
||||
공급처 후보지 선택
|
||||
<br />
|
||||
(필수아님)
|
||||
<span className="flex flex-col items-center leading-6">
|
||||
<span>공급처 후보지 선택</span>
|
||||
<span className="text-sm">(필수아님)</span>
|
||||
</span>
|
||||
</LabelCell>
|
||||
|
||||
<div className="col-span-12 md:col-span-10 p-6">
|
||||
<div className="flex flex-col gap-3 xl:flex-row xl:items-center xl:gap-4">
|
||||
<div className="flex flex-col gap-3 xl:flex-row xl:items-center xl:gap-4">
|
||||
<TextInput value={cand1} onChange={setCand1} className="max-w-[220px]" />
|
||||
<TextInput value={cand2} onChange={setCand2} className="max-w-[220px]" />
|
||||
<TextInput value={cand3} onChange={setCand3} className="max-w-[220px]" />
|
||||
|
||||
<div className="flex items-center gap-3 xl:ml-2">
|
||||
<button
|
||||
<button
|
||||
type="button"
|
||||
className="h-11 rounded-md bg-[#888] px-5 text-base text-white hover:bg-neutral-700"
|
||||
onClick={(e) => {
|
||||
@@ -660,22 +664,20 @@ export default function DemandRegisterPage() {
|
||||
|
||||
//splyList => 해당객체가 대민에서 선택한 후보처 리스트
|
||||
//setLastSub => 해당 스테이트가 선택한 마지막 후보처를 넣어야하는 스테이트
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
후보지 조회
|
||||
</button>
|
||||
</button>
|
||||
|
||||
<button
|
||||
<button
|
||||
type="button"
|
||||
className="h-11 rounded-md bg-[#888] px-5 text-base text-white hover:bg-neutral-600"
|
||||
onClick={(e) => {
|
||||
// TODO: 유사사례 연결
|
||||
searchSimilarCase(e);
|
||||
}}
|
||||
>
|
||||
onClick={(e) => searchSimilarCase(e)}
|
||||
>
|
||||
유사사례
|
||||
</button>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -703,7 +705,7 @@ export default function DemandRegisterPage() {
|
||||
rows={rows} // 실제 데이터
|
||||
detailsByCaseId={detailsByCaseId}
|
||||
onSearch={async (criterion) => {
|
||||
const code = getCriterionCode(criterion);
|
||||
const code = getCriterionCode(criterion); // 'S' 공급량, 'U' 사용용도
|
||||
if (!code) return;
|
||||
// 값은 상황에 맞게 (예시: usePurpose)
|
||||
console.log(code+' req: '+reqQty+' purpose :'+usePurpose);
|
||||
|
||||
@@ -6,12 +6,15 @@
|
||||
import { useDmStore } from "@/app/store";
|
||||
import type { DemandCompBizType } from "@/app/store/sdmMng";
|
||||
import SubPageHeader from "@/components/SubPageHeader";
|
||||
import UiPageNations from "@common/business_components/ui/table/uiPageNations";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
|
||||
type TopField = { label: string; key: string, value: string; required?: boolean };
|
||||
type PairField = { label: string; key: string, value: string };
|
||||
type SessionUser = { dmdInfoId?: string };
|
||||
|
||||
const PAGE_SIZE = 10;
|
||||
|
||||
const formatDate = (value: string | Date | "" | undefined) => {
|
||||
if (!value) return "-";
|
||||
const date = new Date(value);
|
||||
@@ -135,6 +138,7 @@ export default function DemandStatusPage() {
|
||||
const [isLoginStorageInfo, setIsLoginStorageInfo] = useState(false);
|
||||
const [selectedDmdInfoSn, setSelectedDmdInfoSn] = useState<number | "" | null>(null);
|
||||
const [transformedSdmInfoStatusList, setTransformedSdmInfoStatusList] = useState<DemandCompBizType[]>([]);
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
|
||||
// 수정 유무
|
||||
const [ isEditMode, setIsEditMode ] = useState(false);
|
||||
@@ -213,6 +217,18 @@ export default function DemandStatusPage() {
|
||||
);
|
||||
}, [transformedSdmInfoStatusList, selectedDmdInfoSn]);
|
||||
|
||||
const pagedSdmInfoStatusList = useMemo(() => {
|
||||
const startIndex = (currentPage - 1) * PAGE_SIZE;
|
||||
return transformedSdmInfoStatusList.slice(startIndex, startIndex + PAGE_SIZE);
|
||||
}, [currentPage, transformedSdmInfoStatusList]);
|
||||
|
||||
useEffect(() => {
|
||||
const totalPages = Math.max(1, Math.ceil(transformedSdmInfoStatusList.length / PAGE_SIZE));
|
||||
if (currentPage > totalPages) {
|
||||
setCurrentPage(totalPages);
|
||||
}
|
||||
}, [currentPage, transformedSdmInfoStatusList.length]);
|
||||
|
||||
const topFields: TopField[] = useMemo(() => {
|
||||
if (!selectedSdmInfoStatus) return [];
|
||||
|
||||
@@ -392,7 +408,7 @@ export default function DemandStatusPage() {
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
transformedSdmInfoStatusList.map((sdmInfoStatus, index) => {
|
||||
pagedSdmInfoStatusList.map((sdmInfoStatus, index) => {
|
||||
const active = sdmInfoStatus.dmdInfoSn === selectedSdmInfoStatus?.dmdInfoSn;
|
||||
return (
|
||||
<tr
|
||||
@@ -413,7 +429,9 @@ export default function DemandStatusPage() {
|
||||
].join(" ")}
|
||||
aria-selected={active}
|
||||
>
|
||||
<td className="px-3 py-3 text-center">{sdmInfoStatus.index || index + 1}</td>
|
||||
<td className="px-3 py-3 text-center">
|
||||
{sdmInfoStatus.index || (currentPage - 1) * PAGE_SIZE + index + 1}
|
||||
</td>
|
||||
<td className="px-3 py-3 text-center">{formatValue(sdmInfoStatus.ctpvCd)}</td>
|
||||
<td className="px-3 py-3 text-center">{formatValue(sdmInfoStatus.sggCd)}</td>
|
||||
<td className="px-3 py-3 text-center">{formatValue(sdmInfoStatus.dmdCoNm)}</td>
|
||||
@@ -432,6 +450,25 @@ export default function DemandStatusPage() {
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{transformedSdmInfoStatusList.length > 0 ? (
|
||||
<div
|
||||
className={[
|
||||
"mt-2 flex justify-center",
|
||||
"[&_nav]:mt-0 [&_nav]:text-sm",
|
||||
"[&_ul]:gap-0.5",
|
||||
"[&_a]:h-8 [&_a]:min-w-8 [&_a]:px-2 [&_a]:py-1 [&_a]:text-sm",
|
||||
"[&_svg]:h-4 [&_svg]:w-4",
|
||||
"[&_span]:text-sm",
|
||||
].join(" ")}
|
||||
>
|
||||
<UiPageNations
|
||||
total={transformedSdmInfoStatusList.length}
|
||||
cur={currentPage}
|
||||
pageSize={PAGE_SIZE}
|
||||
onPageChange={setCurrentPage}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
</section>
|
||||
|
||||
<section className="mt-10 pb-16" ref={detailRef}>
|
||||
|
||||
@@ -537,6 +537,8 @@ const getSdmInfoStatusList = async (dmdInfoId: string) => {
|
||||
// 유사사례 조회
|
||||
const fetchGetSimilarCaseList = async (part: string, value: number | string) => {
|
||||
try {
|
||||
// part : 'S' 요구수량 , 'U' 사용용도
|
||||
// default : part 'S' , value 10000 즉, part와 value값이 없으면 backend에서 default값으로 조회함.
|
||||
const url = '/reuseFc/pubFcRuseCase/dm/' + part + '/' + (value ? value : 0);
|
||||
const res = await getFetch(fetchType.WR, url);
|
||||
return res?.data || [];
|
||||
|
||||
Reference in New Issue
Block a user