dm: 수요신청현황 시도,시군구
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import Gis from "@common/business_components/ui/map/Gis";
|
||||
import "@/app/commonOrigin.css";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { mapService } from "../service";
|
||||
import GisApp from "@common/business_components/ui/map/lib/gis.core";
|
||||
|
||||
@@ -22,32 +22,36 @@ export default function SelectedFcltList({
|
||||
|
||||
const TableContent = (
|
||||
<>
|
||||
<thead className="bg-gray-100 text-gray-600 text-[11px] font-medium border-b border-cyan-800">
|
||||
<thead className="bg-gray-100 text-gray-700 text-[13px]">
|
||||
<tr>
|
||||
<th className="px-2 py-1.5 text-left w-1/3">시설명</th>
|
||||
<th className="px-2 py-1.5 text-right whitespace-nowrap">
|
||||
처리량(㎥/일)
|
||||
<th className="px-3 py-2 text-left border-b">시설명</th>
|
||||
<th className="px-3 py-2 text-right border-b">
|
||||
하수처리량
|
||||
<br />
|
||||
(㎥/일)
|
||||
</th>
|
||||
<th className="px-2 py-1.5 text-right whitespace-nowrap">
|
||||
재이용량(㎥/일)
|
||||
<th className="px-3 py-2 text-right border-b">
|
||||
재이용량
|
||||
<br />
|
||||
(㎥/일)
|
||||
</th>
|
||||
<th className="px-2 py-1.5 text-center w-10">삭제</th>
|
||||
<th className="px-3 py-2 border-b">삭제</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{data.map((item) => (
|
||||
<tr key={item.pbnstRuseFcltId} className="border-b border-gray-100 last:border-none hover:bg-gray-50/50">
|
||||
<td className="px-2 py-1.5 text-[11px] font-medium text-gray-800 break-keep">{item.ruseUtztnFcltNm}</td>
|
||||
<td className="px-2 py-1.5 text-right text-[11px] text-gray-600">
|
||||
<tr key={item.pbnstRuseFcltId} className="border-b last:border-none">
|
||||
<td className="px-3 py-2 text-[12px]">{item.ruseUtztnFcltNm}</td>
|
||||
<td className="px-3 py-2 text-right text-[12px]">
|
||||
{Number(item.splyExtraCpct || 0).toLocaleString()}
|
||||
</td>
|
||||
<td className="px-2 py-1.5 text-right text-[11px] text-gray-600">
|
||||
<td className="px-3 py-2 text-right text-[12px]">
|
||||
{Number(item.ruseCpct || 0).toLocaleString()}
|
||||
</td>
|
||||
<td className="px-2 py-1.5 text-center">
|
||||
<td className="px-3 py-2 text-center">
|
||||
<button
|
||||
onClick={() => handleDelete(item.pbnstRuseFcltId)}
|
||||
className="text-gray-400 hover:text-red-500 text-[11px] font-bold transition-colors"
|
||||
className="text-red-500 hover:text-red-700 text-sm font-bold"
|
||||
aria-label="삭제"
|
||||
title="삭제"
|
||||
>
|
||||
@@ -61,12 +65,12 @@ export default function SelectedFcltList({
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="fixed right-20 top-[3.5rem] w-[22rem] max-h-[80vh] overflow-hidden bg-white/95 backdrop-blur-sm shadow-[0_4px_12px_rgba(0,0,0,0.1)] rounded-lg border border-gray-200 z-50 flex flex-col">
|
||||
<h3 className="bg-cyan-700 text-white text-[13px] font-semibold p-2">
|
||||
<div className="fixed right-40 top-[8rem] w-[40rem] max-h-[130rem] overflow-auto bg-white shadow-lg rounded p-4 border border-gray-300 z-50">
|
||||
<h3 className="bg-cyan-700 text-white text-xl font-bold mb-2 p-2">
|
||||
선택된 시설
|
||||
</h3>
|
||||
<div className="overflow-y-auto w-full">
|
||||
<table className="w-full text-sm text-gray-800 border-t border-gray-200 table-fixed">
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full text-sm text-gray-800 border border-gray-200">
|
||||
{TableContent}
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -455,7 +455,7 @@ export default function DemandPlaceRegisterPage() {
|
||||
}
|
||||
|
||||
alert("수요처 등록 완료!");
|
||||
router.push("/apply/register");
|
||||
router.push("/apply/dmdinfo"); // 수요정보등록
|
||||
}
|
||||
|
||||
setPw("");
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// app/(with-layout)/apply/register/page.tsx
|
||||
/**
|
||||
* 수요정보등록(수정) 화면
|
||||
*
|
||||
@@ -126,7 +126,7 @@ function DateInput({
|
||||
}
|
||||
|
||||
export default function DemandStatusPage() {
|
||||
const { getSdmInfoStatusList, updateSdmInfoData, Sdm, Common } = useDmStore((state) => state);
|
||||
const { getSdmInfoStatusList, updateSdmInfoData, Sdm, Common, initializeCommonData } = useDmStore((state) => state);
|
||||
const { successLogin, sdmInfoStatusList } = Sdm;
|
||||
const { selectSidoData, selectSigunData } = Common;
|
||||
|
||||
@@ -154,8 +154,9 @@ export default function DemandStatusPage() {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
getUseTypesData();
|
||||
}, [getUseTypesData]);
|
||||
getUseTypesData(); // 용도코드 조회
|
||||
initializeCommonData(); // 시도, 시군구 조회
|
||||
}, [getUseTypesData, initializeCommonData]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!successLogin && !isLoginStorageInfo) return;
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
// apps/dm/app/(landing)/reuse/page.tsx
|
||||
/**
|
||||
* 대민 메인 페이지(첫페이지)
|
||||
*/
|
||||
"use client";
|
||||
|
||||
import { useMemo } from "react";
|
||||
import { useEffect, useMemo } from "react";
|
||||
import TopNav from "@/components/TopNav";
|
||||
import { removeCookie } from "@/src/shared/lib";
|
||||
import SideIndicator from "./SideIndicator";
|
||||
import { useScrollSpy } from "./_hooks/useScrollSpy";
|
||||
|
||||
@@ -11,6 +14,9 @@ import IntroCards from "./_sections/IntroCards";
|
||||
import Cases from "./_sections/Cases";
|
||||
import ProcessFlow from "./_sections/ProcessFlow";
|
||||
|
||||
const CLAIM_NAME = "Authorization";
|
||||
const AUTH_USER_ID = "token-id";
|
||||
|
||||
const LANDING_SECTIONS = [
|
||||
{ id: "main", label: "Main" },
|
||||
{
|
||||
@@ -34,6 +40,11 @@ export default function ReuseLandingPage() {
|
||||
const sectionIds = useMemo(() => LANDING_SECTIONS.map((s) => s.id), []);
|
||||
const activeId = useScrollSpy(sectionIds);
|
||||
|
||||
useEffect(() => {
|
||||
removeCookie(CLAIM_NAME);
|
||||
removeCookie(AUTH_USER_ID);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<main className="bg-white">
|
||||
|
||||
|
||||
@@ -496,7 +496,7 @@ export const CommonReducer:(set:any)=>CommonAction=(set: any) => {
|
||||
}
|
||||
})
|
||||
)},
|
||||
fetchAnonymousMenu: async (siteId = REUSE_SITE_ID) => fetchAnonymousMenu(siteId)
|
||||
fetchAnonymousMenu: async (siteId = REUSE_SITE_ID) => fetchAnonymousMenu(siteId),
|
||||
}
|
||||
}
|
||||
export type CommonStore = CommonType & CommonAction;
|
||||
|
||||
@@ -759,7 +759,7 @@ export const SdmReducer = (set: any): SdmActions => {
|
||||
}
|
||||
}))
|
||||
},
|
||||
|
||||
// 용도 코드 조회 (WR018 : 하수재이용장외용도)
|
||||
getUseTypesData: async () => {
|
||||
//http://dev.onasys.co.kr:3000/server/cms-service/api/v1/lwpo-cds?lwpoCdNm=&sort=regDt,desc&upCd=WR018&page=0&size=10
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ type Props = {
|
||||
|
||||
const defaultMenus: LnbMenu[] = [
|
||||
{ label: "수요처", href: "/apply/dmdco" },
|
||||
{ label: "수요정보등록", href: "/apply/register" },
|
||||
{ label: "수요정보등록", href: "/apply/dmdinfo" },
|
||||
{ label: "수요신청현황", href: "/apply/status" },
|
||||
];
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/**
|
||||
* 로그인 modal
|
||||
*/
|
||||
"use client";
|
||||
|
||||
import { useEffect, useId, useState } from "react";
|
||||
@@ -42,6 +45,16 @@ export default function LoginModal({ open, onClose, onSuccess }: LoginModalProps
|
||||
const [touched, setTouched] = useState<Partial<Record<FieldKey, boolean>>>({});
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
|
||||
const resetForm = () => {
|
||||
setBizNo("");
|
||||
setWorkerNo("");
|
||||
setNoWorker(true);
|
||||
setPw("");
|
||||
setErrors({});
|
||||
setTouched({});
|
||||
setSubmitting(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
const onKeyDown = (e: KeyboardEvent) => {
|
||||
@@ -53,13 +66,10 @@ export default function LoginModal({ open, onClose, onSuccess }: LoginModalProps
|
||||
const prev = document.body.style.overflow;
|
||||
document.body.style.overflow = "hidden"; // 모달 오픈 시 배경 스크롤 방지
|
||||
|
||||
// 모달 오픈 시 에러/터치 초기화
|
||||
setErrors({});
|
||||
setTouched({});
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("keydown", onKeyDown);
|
||||
document.body.style.overflow = prev;
|
||||
resetForm();
|
||||
};
|
||||
}, [open, onClose]);
|
||||
|
||||
@@ -142,7 +152,7 @@ export default function LoginModal({ open, onClose, onSuccess }: LoginModalProps
|
||||
const parsed = JSON.parse(sessionUser) as { dmdCoNm?: string };
|
||||
onSuccess?.({ userName: parsed.dmdCoNm ?? "수요처" });
|
||||
onClose();
|
||||
router.refresh();
|
||||
router.push("/apply/status");
|
||||
}
|
||||
} finally {
|
||||
setSubmitting(false);
|
||||
|
||||
@@ -94,7 +94,7 @@ export default function SearchInputText({
|
||||
value={textValue || ""}
|
||||
onChange={handleInputChange}
|
||||
onKeyDown={handleKeyDown}
|
||||
className="w-full h-8 text-xs pl-2 pr-2 text-gray-600 border border-gray-300 rounded focus:outline-none focus:ring-1 focus:ring-blue-500"
|
||||
className="w-full h-[3.2rem] !text-xl pl-3 text-gray-600 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder={`${label}을(를) 입력하세요`}
|
||||
onClick={() => {
|
||||
setTextValue("");
|
||||
@@ -109,10 +109,10 @@ export default function SearchInputText({
|
||||
searchList.map((item, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={`w-full cursor-pointer px-3 py-2 text-left text-xs ${
|
||||
className={`w-full cursor-pointer overflow-auto px-5 py-3 text-left !text-xl ${
|
||||
highlightIndex === index
|
||||
? "bg-blue-50"
|
||||
: "hover:bg-gray-50"
|
||||
? "bg-blue-100"
|
||||
: "hover:bg-gray-100"
|
||||
}`}
|
||||
onClick={() => handleSuggestionClick(item.bscFctNm)}
|
||||
role="button"
|
||||
@@ -127,7 +127,7 @@ export default function SearchInputText({
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="text-xs w-full px-3 py-2 hover:bg-gray-50 cursor-pointer text-gray-500">
|
||||
<div className="!text-xl w-full px-5 py-3 hover:bg-gray-100 cursor-pointer overflow-auto">
|
||||
검색 결과가 없습니다.
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -62,51 +62,50 @@ export function SearchBar({
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex justify-center w-full px-4 py-2">
|
||||
<div className="flex items-center w-auto shadow-md px-4 py-2 space-x-2 bg-white/95 backdrop-blur-sm rounded-lg text-sm border border-gray-200">
|
||||
<div className="flex justify-center w-full px-4 py-3">
|
||||
<div className="flex items-center w-full max-w-screen-lg rounded-xl bg-white shadow-md px-6 py-4 space-x-3">
|
||||
<SelectBox
|
||||
labelClass="w-[50px] text-xs font-medium text-gray-700"
|
||||
className="w-[110px]"
|
||||
labelClass="w-[40px]"
|
||||
className="w-[200px]"
|
||||
label="시도"
|
||||
selectClass="rounded bg-white text-xs h-8"
|
||||
selectClass="rounded-lg bg-white"
|
||||
selectArray={Common.selectSidoData || []}
|
||||
onSelectValue={(val) => onSelectValue(val.toString(), "ctpvCd")}
|
||||
value={sidoValue || Common.selectSidoData[0]?.val || ""}
|
||||
/>
|
||||
<SelectBox
|
||||
labelClass="w-[70px] text-xs font-medium text-gray-700"
|
||||
className="w-[110px]"
|
||||
labelClass="w-[65px]"
|
||||
className="w-[200px]"
|
||||
label="시군구"
|
||||
selectClass="rounded bg-white text-xs h-8"
|
||||
selectClass="rounded-lg bg-white"
|
||||
selectArray={filteredSigunData || []}
|
||||
onSelectValue={(val) => onSelectValue(val.toString(), "sggCd")}
|
||||
value={sigunValue}
|
||||
/>
|
||||
<Label className="text-gray-700 text-xs font-medium pl-2 pr-1">하수재이용시설</Label>
|
||||
<div className="w-[180px]">
|
||||
<SearchInputText
|
||||
label="시설명 입력"
|
||||
initValue={undefined}
|
||||
setValue={(searchNm?: string) => {
|
||||
let sggOrCity = "";
|
||||
if (searchNm) {
|
||||
if (sigunValue === "0" || sigunValue === "") {
|
||||
sggOrCity = sidoValue;
|
||||
} else {
|
||||
sggOrCity = sigunValue;
|
||||
}
|
||||
findRuseFclt(sggOrCity, searchNm);
|
||||
<Label className="text-gray-600">하수재이용시설</Label>
|
||||
<SearchInputText
|
||||
label="시설명"
|
||||
initValue={undefined}
|
||||
setValue={(searchNm?: string) => {
|
||||
let sggOrCity = "";
|
||||
if (searchNm) {
|
||||
if (sigunValue === "0" || sigunValue === "") {
|
||||
sggOrCity = sidoValue;
|
||||
} else {
|
||||
sggOrCity = sigunValue;
|
||||
}
|
||||
}}
|
||||
setRtnData={(rtnData: any) => {
|
||||
setHasuPk(rtnData);
|
||||
}}
|
||||
searchList={map.ruseFcltList || []}
|
||||
/>
|
||||
</div>
|
||||
findRuseFclt(sggOrCity, searchNm);
|
||||
}
|
||||
}}
|
||||
setRtnData={(rtnData: any) => {
|
||||
setHasuPk(rtnData);
|
||||
}}
|
||||
searchList={map.ruseFcltList || []}
|
||||
/>
|
||||
<Button
|
||||
color="sky"
|
||||
className="ml-2 text-white !h-8 !py-0 !px-3 !text-xs font-semibold rounded"
|
||||
className="ml-2 text-white"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
onApply();
|
||||
}}
|
||||
|
||||
@@ -8,7 +8,7 @@ const serverApiUrl = process.env.NEXT_PUBLIC_CS_SERVER_API_URL;
|
||||
const GEOSERVER_URL = process.env.NEXT_PUBLIC_GEOSERVER_URL || "";
|
||||
const LX_GEOSERVER_URL = process.env.NEXT_PUBLIC_LX_GEOSERVER_URL || "";
|
||||
const GATEWAY_URL = process.env.NEXT_PUBLIC_GATEWAY_URL || "";
|
||||
const SEWERAGE_API_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || "";
|
||||
// const SEWERAGE_API_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || "";
|
||||
const BUSINESS_JUSO_API_URL = process.env.NEXT_PUBLIC_FINDADRESS_URL || "";
|
||||
const AdressKey = process.env.NEXT_PRIVATE_WR_ADDRESS_KEY || "";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user