dm: 수요처 등록 수정 중

This commit is contained in:
2026-05-06 16:29:47 +09:00
parent ab170a2b92
commit a644e80191
8 changed files with 30 additions and 15 deletions
+1 -1
View File
@@ -18,7 +18,7 @@ NEXT_PUBLIC_CS_TUS_UPLOAD = /attach-service/api/v1/tus/upload
NEXT_PUBLIC_NGII_URL = https://map.ngii.go.kr
NEXT_PUBLIC_NGII_PARAM = 04trYP9_xwLAfALjwZ-B8g&service=WMTS&request=GetTile&version=1.0.0&format=image/png&layer=korean_map&style=korean&tilematrixset=korean&tilematrix={z}&tilecol={x}&tilerow={y}
NEXT_PUBLIC_GATEWAY_URL=http://con.mind-one.co.kr:11083 # 개발 서버 API
# NEXT_PUBLIC_GATEWAY_URL=http://localhost:8883 # 개발 서버 API # 박이정
# NEXT_PUBLIC_GATEWAY_URL=http://localhost:8883 # 개발 서버 API
NEXT_PUBLIC_FINDADRESS_URL=https://business.juso.go.kr/addrlink/addrLinkApi.do
+13 -6
View File
@@ -1,3 +1,6 @@
/**
* 수요처 등록/수정
*/
"use client";
import { useEffect, useMemo, useRef, useState, type ReactNode, type RefObject } from "react";
@@ -15,6 +18,7 @@ type SessionUser = {
dmdCoNm?: string;
zip?: string;
daddr?: string;
daddr2?: string;
telno?: string;
ctpvCd?: string;
sggCd?: string;
@@ -170,7 +174,7 @@ export default function DemandPlaceRegisterPage() {
const [company, setCompany] = useState("");
const [bizNo, setBizNo] = useState("");
const [workerNo, setWorkerNo] = useState("");
const [noWorkerNo, setNoWorkerNo] = useState(false);
const [noWorkerNo, setNoWorkerNo] = useState(true); // 종사업자번호 해당없음 default 선택으로 설정
const [zip, setZip] = useState("");
const [addr1, setAddr1] = useState("");
@@ -218,7 +222,7 @@ export default function DemandPlaceRegisterPage() {
setCompany(String(user.dmdCoNm ?? ""));
setZip(String(user.zip ?? ""));
setAddr1(String(user.daddr ?? ""));
setAddr2("");
setAddr2(String(user.daddr2 ?? ""));
setTel(formatKoreanPhoneNumber(String(user.telno ?? "")));
setSido(String(user.ctpvCd ?? ""));
setSigungu(String(user.sggCd ?? ""));
@@ -305,9 +309,11 @@ export default function DemandPlaceRegisterPage() {
}
}
const mergedAddress = [addr1.trim(), addr2.trim()].filter(Boolean).join(" ");
if (!mergedAddress) return alert("사업자주소를 입력해 주세요.");
if (mergedAddress.length > 40) return alert("주소는 40자 이내로 입력해주세요.");
const baseAddress = addr1.trim();
const detailAddress = addr2.trim();
if (!baseAddress && !detailAddress) return alert("사업자주소를 입력해 주세요.");
if (baseAddress.length > 40) return alert("주소는 40자 이내로 입력해주세요.");
if (detailAddress.length > 40) return alert("상세 주소는 40자 이내로 입력해주세요.");
if (!telDigits) return alert("전화번호를 입력해 주세요.");
if (!/^\d{8,11}$/.test(telDigits)) {
@@ -341,7 +347,8 @@ export default function DemandPlaceRegisterPage() {
dmdInfoId: fullDmdInfoId,
bzmnNo: bizDigits,
zip: zip.trim(),
daddr: mergedAddress,
daddr: baseAddress,
daddr2: detailAddress,
telno: telDigits,
rgtr: (sessionUser?.rgtr as string) || myUUID,
};
@@ -278,12 +278,12 @@ export default function RainStatusSection() {
<Hr className="my-11" />
{/* 2) 빗물이용시설의 용도별 분포 (2023년 기준) */}
{/* 2) 빗물이용시설의 용도별 분포 (xxxx년 기준) */}
<section
id="status-rain-purpose-distribution"
className="scroll-mt-[120px]"
>
<SectionTitle>빗물이용시설의 용도별 분포 (2023년 기준)</SectionTitle>
<SectionTitle>빗물이용시설의 용도별 분포 ({selectYear}년 기준)</SectionTitle>
<div className="mt-8">
<div className={tableStyles.container}>
+1 -1
View File
@@ -16,7 +16,7 @@ const menus: BusinessSubNavMenu[] = [
},
{
id: "status-rain-purpose-distribution",
label: "빗물이용시설의 용도별 분포 (2023년 기준)",
label: "빗물이용시설의 용도별 분포",
},
{
id: "status-rain-purpose-usage",
+2 -2
View File
@@ -257,9 +257,9 @@ export function extractSearchInputFromRoadAddr(roadAddr: string): string {
* @returns 최대 5개의 "도로명 건물본번" 자동완성 문자열 목록
*/
export async function fetchPostcodeSuggestions(input: string): Promise<string[]> {
const normalized = input.replace(/\s+/g, " ").trim();
const normalized = input.replace(/\s+/g, " ").trim(); // space가 여러개일 때, 하나만 남김
const parts = normalized.split(" ");
const tail = parts.at(-1) ?? "";
const tail = parts.at(-1) ?? ""; // 마지막 요소
const roadNm =
/^\d+(?:-\d+)?$/.test(tail) && parts.length > 1
? parts.slice(0, -1).join(" ").trim()
+1 -1
View File
@@ -326,7 +326,7 @@ export default function LoginModal({ open, onClose, onSuccess }: LoginModalProps
<button
type="button"
onClick={() => router.push(REGISTER_HREF)}
onClick={() => {onClose(); router.push(REGISTER_HREF);}}
className="shrink-0 rounded-[4px] h-[48px] px-10 bg-[#004A94] text-white text-[18px] hover:opacity-95"
>
수요처등록
+9 -2
View File
@@ -38,6 +38,7 @@ export default function PostcodeModal({ open, onClose, onSelect }: Props) {
const [total, setTotal] = useState(0);
const [loading, setLoading] = useState(false);
const [searchMessage, setSearchMessage] = useState("");
const [isInputFocused, setIsInputFocused] = useState(false);
const inputRef = useRef<HTMLInputElement | null>(null);
@@ -51,6 +52,7 @@ export default function PostcodeModal({ open, onClose, onSelect }: Props) {
setTotal(0);
setLoading(false);
setSearchMessage("");
setIsInputFocused(false);
}, [open]);
useEffect(() => {
@@ -59,7 +61,7 @@ export default function PostcodeModal({ open, onClose, onSelect }: Props) {
const prevOverflow = document.body.style.overflow;
document.body.style.overflow = "hidden";
setTimeout(() => inputRef.current?.focus(), 50);
setTimeout(() => inputRef.current?.focus(), 50); // 주소입력란에 focus()
const onKeyDown = (e: KeyboardEvent) => {
if (e.key === "Escape") onClose();
@@ -149,7 +151,7 @@ export default function PostcodeModal({ open, onClose, onSelect }: Props) {
};
}, [dq, open]);
const showSuggest = open && q.trim().length >= 1 && suggestions.length > 0;
const showSuggest = open && isInputFocused && q.trim().length >= 1 && suggestions.length > 0;
if (!mounted || !open) return null;
@@ -190,6 +192,10 @@ export default function PostcodeModal({ open, onClose, onSelect }: Props) {
ref={inputRef}
value={q}
onChange={(e) => setQ(e.target.value)}
onFocus={() => setIsInputFocused(true)}
onBlur={() => {
setTimeout(() => setIsInputFocused(false), 100);
}}
placeholder="예) 테헤란로 152-1"
className={[
"w-full rounded-md border px-4 py-3 pr-12 text-[14px] outline-none",
@@ -226,6 +232,7 @@ export default function PostcodeModal({ open, onClose, onSelect }: Props) {
key={s}
type="button"
className="flex w-full items-center justify-between px-4 py-3 text-left text-[14px] hover:bg-slate-50"
onMouseDown={(e) => e.preventDefault()}
onClick={() => {
// ✅ 추천 클릭 → 입력값 채우고 드롭다운 닫기 + 포커스 유지
setQ(s);
@@ -15,6 +15,7 @@ export type DemandCompType = {
bzmnNo: string | "";
dmdCoNm: string | "";
daddr: string | "";
daddr2: string | "";
telno: string | "";
rgtr: string | "";
mdfr?: string;