diff --git a/apps/dm/app/(base-layout)/pages/sdmMng/sdmInsert/page.tsx b/apps/dm/app/(base-layout)/pages/sdmMng/sdmInsert/page.tsx index a75b3acd7..79eb07830 100644 --- a/apps/dm/app/(base-layout)/pages/sdmMng/sdmInsert/page.tsx +++ b/apps/dm/app/(base-layout)/pages/sdmMng/sdmInsert/page.tsx @@ -58,7 +58,7 @@ export default function MyForm() { dataList={demandCompList} rtnValue={callback} rtnInputData={handleInsertSdmData} - openNetwork={false} + openNetwork={true} /> diff --git a/apps/dm/middleware.ts b/apps/dm/middleware.ts index ee26a9767..0b2b21fbb 100644 --- a/apps/dm/middleware.ts +++ b/apps/dm/middleware.ts @@ -42,9 +42,8 @@ export function middleware(req: NextRequest) { .map(([key, value]) => `${key}=${decodeURIComponent(value)}`) .join("&"); - const newUrl = `${serverApiUrl}${pathname.replace("/server", "")}${ - decodedParams ? `?${decodedParams}` : "" - }`; + const newUrl = `${serverApiUrl}${pathname.replace("/server", "")}${decodedParams ? `?${decodedParams}` : "" + }`; return NextResponse.rewrite(new URL(newUrl)); } @@ -55,33 +54,25 @@ export function middleware(req: NextRequest) { if (pathname.startsWith("/attach-service")) { const requestHeaders = new Headers(req.headers); - // const token = - // "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhMGVjN2EwNy03NTJhLTRmN2YtODlhNi04NTRlNjNkMmUzYTAiLCJhdXRob3JpdGllcyI6IlJPTEVfQURNSU4sUk9MRV9BTk9OWU1PVVMiLCJtbmdyWW4iOiJZIiwiZXhwIjoxNzUyMTM1OTk3fQ.itGY6M6mC2iwKvEpXw2KS6354T_B_OFz4hD26ResIgwJhpwiDJCMuSXD-rZ3AarmAIKd0udpCuJR7UlvFMN2ww"; - // const userId = "a0ec7a07-752a-4f7f-89a6-854e63d2e3a0"; const token = req.cookies.get(CLAIM_NAME)?.value; const userId = req.cookies.get(AUTH_USER_ID)?.value; const newUrl = `${serverApiUrl}${pathname}`; - - //wr:dev: pathname /attach-service/api/v1/tus/upload/5e60b70a-956e-40c3-be5a-cdd3100bf8ad - //http://dev.onasys.co.kr:8000/attach-service/api/v1/tus/upload/5e60b70a-956e-40c3-be5a-cdd3100bf8ad if (token) requestHeaders.set(CLAIM_NAME, token); if (userId) requestHeaders.set(AUTH_USER_ID, userId); - console.log( - `[Middleware] Rewriting from '/attach-service' path to: ${newUrl}` - ); + console.log(`[Middleware] Rewriting from '/attach-service' path to: ${newUrl}`); return NextResponse.rewrite(new URL(newUrl), { headers: requestHeaders, }); } - if (pathname.startsWith("/user-service")) { + if (pathname.startsWith("/user-service") + || pathname.startsWith("/cms-service")) { + let queryParams = searchParams.toString(); const requestHeaders = new Headers(req.headers); - const newUrl = `${serverApiUrl}${pathname}`; + const newUrl = `${serverApiUrl}${pathname}${queryParams ? `?${queryParams}` : ""}`; - console.log( - `[Middleware] Rewriting from '/user-service' path to: ${newUrl}` - ); + console.log(`[Middleware] Rewriting from '/user-service' path to: ${newUrl}`); return NextResponse.rewrite(new URL(newUrl), { headers: requestHeaders, }); @@ -130,27 +121,24 @@ export function middleware(req: NextRequest) { if (pathname.startsWith("/reuse-service")) { const queryParams = searchParams.toString(); - const newUrl = `${SERVER_API_WR_URL}${pathname.replace("/reuse-service", "")}${ - queryParams ? `?${queryParams}` : "" - }`; + const newUrl = `${SERVER_API_WR_URL}${pathname.replace("/reuse-service", "")}${queryParams ? `?${queryParams}` : "" + }`; console.log(`[Middleware] Rewriting from '/reuse-service' path to: ${newUrl}`); return NextResponse.rewrite(new URL(newUrl)); } if (pathname.startsWith("/operation-service")) { const queryParams = searchParams.toString(); - const newUrl = `${SERVER_API_FO_URL}${pathname.replace("/operation-service", "")}${ - queryParams ? `?${queryParams}` : "" - }`; + const newUrl = `${SERVER_API_FO_URL}${pathname.replace("/operation-service", "")}${queryParams ? `?${queryParams}` : "" + }`; console.log(`[Middleware] Rewriting from '/operation-service' path to: ${newUrl}`); return NextResponse.rewrite(new URL(newUrl)); } if (pathname.startsWith("/sewerage-service")) { const queryParams = searchParams.toString(); - const newUrl = `${SEWERAGE_API_URL}${pathname.replace("/sewerage-service", "")}${ - queryParams ? `?${queryParams}` : "" - }`; + const newUrl = `${SEWERAGE_API_URL}${pathname.replace("/sewerage-service", "")}${queryParams ? `?${queryParams}` : "" + }`; console.log(`[Middleware] Rewriting from '/sewerage-service' path to: ${newUrl}`); return NextResponse.rewrite(new URL(newUrl)); } @@ -174,9 +162,7 @@ export function middleware(req: NextRequest) { const newUrl = `${BUSINESS_JUSO_API_URL}?${params.toString()}`; console.log(`[Middleware] Request to business.juso.go.kr`); console.log(req.url); - console.log( - `[Middleware] Rewriting from '/business.juso.go.kr' path to: ${newUrl}` - ); + console.log(`[Middleware] Rewriting from '/business.juso.go.kr' path to: ${newUrl}`); return NextResponse.rewrite(new URL(newUrl)); } @@ -187,6 +173,7 @@ export const config = { matcher: [ "/server/:path*", "/user-service/:path*", + "/cms-service/:path*", "/attach-service/:path*", "/geoserver/:path*", "/operation-service/:path*", diff --git a/apps/wr/app/(with-layout)/matMng/coMng/coSttn/page.tsx b/apps/wr/app/(with-layout)/matMng/coMng/coSttn/page.tsx index 957130910..c2a7d875f 100644 --- a/apps/wr/app/(with-layout)/matMng/coMng/coSttn/page.tsx +++ b/apps/wr/app/(with-layout)/matMng/coMng/coSttn/page.tsx @@ -302,7 +302,7 @@ export default function CoSttn() { { @@ -350,7 +350,7 @@ export default function CoSttn() { }} bodyClassNm={"w-full mx-auto bg-white rounded-lg shadow-md p-6"} updateList={updateData} - openNetwork={false} + openNetwork={true} > } > diff --git a/apps/wr/components/ui/form/fcltReg/pbnstReg/buseReg/bugRegForm.tsx b/apps/wr/components/ui/form/fcltReg/pbnstReg/buseReg/bugRegForm.tsx index e669a85f7..614a6a7a3 100644 --- a/apps/wr/components/ui/form/fcltReg/pbnstReg/buseReg/bugRegForm.tsx +++ b/apps/wr/components/ui/form/fcltReg/pbnstReg/buseReg/bugRegForm.tsx @@ -766,7 +766,7 @@ export function PbnstBuseForm({ > { setIsDmdModal({ isMoal: false, data: {} as DemandCompType }); @@ -787,9 +787,10 @@ export function PbnstBuseForm({ }); }} bodyClassNm={"w-full mx-auto bg-white rounded-lg shadow-md p-6"} - openNetwork={false} + openNetwork={true} > } + noFooterYn={"Y"} > ) : ( diff --git a/apps/wr/middleware.ts b/apps/wr/middleware.ts index a5956ee0b..d1e96dacc 100644 --- a/apps/wr/middleware.ts +++ b/apps/wr/middleware.ts @@ -60,7 +60,8 @@ export function middleware(req: NextRequest) { } if (pathname.startsWith("/cms-service")) { - const newUrl = `${serverApiUrl}${pathname}`; + let queryParams = searchParams.toString(); + const newUrl = `${serverApiUrl}${pathname}${queryParams ? `?${queryParams}` : ""}`; console.log(`[Middleware] Rewriting from '/cms-service' path to: ${newUrl}`); const rewriteRequest = rewriteWith(newUrl, req, true); return rewriteRequest; diff --git a/packages/common/business_components/src/ui/dialog_ui/index.tsx b/packages/common/business_components/src/ui/dialog_ui/index.tsx index 4201cbdfa..67b2a3c53 100644 --- a/packages/common/business_components/src/ui/dialog_ui/index.tsx +++ b/packages/common/business_components/src/ui/dialog_ui/index.tsx @@ -31,19 +31,21 @@ export function UiModal({ <> - {noHeaderYn === 'N' && ( - - - {headerTitle} - - - )} - {(open && body) ? - useDirectRender - ? body - : <>{body}> - : <>> - } + {noHeaderYn === 'N' && ( + + + {headerTitle} + + + )} + + {(open && body) ? + useDirectRender + ? body + : <>{body}> + : <>> + } + {noFooterYn === 'N' && ( {footerContent} diff --git a/packages/common/business_components/src/ui/index.ts b/packages/common/business_components/src/ui/index.ts index 4686e3a99..db1132b58 100644 --- a/packages/common/business_components/src/ui/index.ts +++ b/packages/common/business_components/src/ui/index.ts @@ -14,7 +14,7 @@ export * from "./search_form_left"; export * from "./search_form_right"; export * from "./search_input"; export * from "./search_input_select"; -export * from "./search_input_address"; +// export * from "./search_input_address"; export * from "./select"; export * from "./tab"; export * from "./table"; diff --git a/packages/common/business_components/src/ui/sdmInsertForm/form.tsx b/packages/common/business_components/src/ui/sdmInsertForm/form.tsx index 6d4bf8acf..2883413c2 100644 --- a/packages/common/business_components/src/ui/sdmInsertForm/form.tsx +++ b/packages/common/business_components/src/ui/sdmInsertForm/form.tsx @@ -1,4 +1,4 @@ -import { Input } from "@common/components"; +import { Button, Input, Label } from "@common/components"; import { AsYouType } from "libphonenumber-js"; import React, { useCallback, useEffect, useState } from "react"; import type { ControllerRenderProps, UseFormReturn } from "react-hook-form"; @@ -6,8 +6,10 @@ import { FormField } from "../form"; import { FormUi } from "../form_ui"; import { SelectBox } from "../select"; import { SdmSearchForm } from "./sdmNameBox"; -import SearchInputAddress from "../search_input_address"; -import type { addressType } from "../search_input_address/findAddress"; +import { UiModal, UiTable } from '../../ui'; +import type { Zip, ZipSearchParams } from "../search_input_address/zipService"; +import { findAddress } from "../search_input_address/findAddress"; +import { cn } from "@common/components"; // 수요처 정보 export type DemandCompType = { @@ -18,7 +20,7 @@ export type DemandCompType = { daddr: string | ""; telno: string | ""; rgtr: string | ""; - mdfr?:string ; + mdfr?: string; useUsgCd: string | ""; ctpvCd: string | ""; sggCd: string | ""; @@ -89,6 +91,7 @@ export function SdmRegForm({ readOnly, openNetwork, }: SdmRegFormProps) { + const PAGE_SIZE = 10; const [sidoValue, setSidoValue] = useState(""); const [sigunValue, setSigunValue] = useState(""); const [filteredSigunData, setFilteredSigunData] = useState([ @@ -97,6 +100,34 @@ export function SdmRegForm({ const [isBznmTotNoDisabled, setIsBznmTotNoDisabled] = useState(true); const [orgBznmNo, setOrgBznmNo] = useState(""); const [updateCoNm, setUpdateNm] = useState(""); + const [isZipModalOpen, setIsZipModalOpen] = useState(false); + const [zipId, setZipId] = useState(undefined); + const [address, setAddress] = useState(""); + const [detailedAddress, setDetailedAddress] = useState(""); + const [curPage, setCurPage] = useState(1); + // 우편번호 검색 관련 상태 + const [zipSearchResults, setZipSearchResults] = useState([]); + const [zipTotalElements, setZipTotalElements] = useState(-1); + const [searchQuery, setSearchQuery] = useState({ + roadNm: "", + bldgNoMno: null, + bldgNoSno: null, + page: curPage, + size: PAGE_SIZE + }); + const [isResetPage, setIsResetPage] = useState(false); + const [isResetSelection, setIsResetSelection] = useState(false); + const [selectedRowIndex, setSelectedRowIndex] = useState(undefined); + const [selectedZip, setSelectedZip] = useState(); + const [isSelectedZip, setIsSelectedZip] = useState(false); + + const handleCellClick = (index: any, headId: any) => { + console.log('index', index); + console.log('headId', headId); + setSelectedZip(zipSearchResults[index]); + setIsSelectedZip(true); + console.log('selectedZip', zipSearchResults[index]); + }; const formatPhoneNumber = (value: string) => { const input = value; @@ -262,6 +293,17 @@ export function SdmRegForm({ [orgBznmNo, setIsDuplicate], ); + // 우편번호 선택 함수 + const handleSelectAddress = () => { + setZipId(selectedZip?.zipId); + setAddress(selectedZip?.zipAddr || ""); + setDetailedAddress(""); + setIsZipModalOpen(false); + setSelectedZip(undefined); + setIsSelectedZip(false); + setSelectedRowIndex(undefined); + }; + useEffect(() => { if (updateList?.dmdInfoId) { form.reset(updateList); @@ -283,199 +325,344 @@ export function SdmRegForm({ console.log("form.formState.errors ", form.formState.errors); }, [form.formState.errors]); + useEffect(() => { + console.log("curPage ", curPage); + searchQuery.page = curPage - 1; + const fetchAddress = async () => { + const result = await findAddress(searchQuery); + setZipSearchResults(result?.content); + }; + fetchAddress(); + }, [curPage]); + + // 폼 제출 전에 주소 합치기 + useEffect(() => { + // address와 detailedAddress를 합쳐서 daddr에 설정 + if (address) { + const fullAddress = `${address || ""} ${detailedAddress || ""}`.trim(); + form.setValue("daddr", fullAddress, {shouldValidate: true }); + } + }, [address, detailedAddress, form]); + + const renderBody = () => ( + <> + { + e.preventDefault(); + e.stopPropagation(); + const result = await findAddress(searchQuery); + setZipSearchResults(result?.content); + setZipTotalElements(result?.totalElements); + }} + className="mb-4 space-y-2" + > + {/* 검색 조건 부분 */} + + + + 도로명 + + setSearchQuery({ + ...searchQuery, + roadNm: e.target.value, + }) + } + placeholder="예: 테헤란로" + className="!text-[1.3rem]" + /> + + + + 건물본번 + { + const value = e.target.value + ? parseInt(e.target.value) + : null; + setSearchQuery({ + ...searchQuery, + bldgNoMno: value, + }); + }} + placeholder="예: 123" + className="!text-[1.3rem]" + /> + + + + 건물부번 + { + const value = e.target.value + ? parseInt(e.target.value) + : null; + setSearchQuery({ + ...searchQuery, + bldgNoSno: value, + }); + }} + placeholder="예: 45" + className="!text-[1.3rem]" + /> + + + + + 검색 + + + + + {/* 검색 결과 부분 */} + {zipTotalElements > 0 && ( + + )} + {zipTotalElements === 0 && ( + + + 조회된 데이터가 없습니다. + + )} + > + ); + + const formFields: Array<{ name: keyof FormSchema; label: string; component: FieldComponent; }> = [ - { - name: "ctpvCd", - label: "시도", - component: (field) => - updateList?.dmdInfoId ? ( - { - field.onChange(e.target.value); - }} - value={ - selectSidoData.find((item) => item.val === field.value?.trim()) - ?.text ?? "" - } - readOnly={!!updateList?.dmdInfoId} - /> - ) : ( - - onSelectValue(val.toString(), "ctpvCd", field ?? "") - } - className="" - value={sidoValue} + { + name: "ctpvCd", + label: "시도", + component: (field) => + updateList?.dmdInfoId ? ( + { + field.onChange(e.target.value); + }} + value={ + selectSidoData.find((item) => item.val === field.value?.trim()) + ?.text ?? "" + } + readOnly={!!updateList?.dmdInfoId} + /> + ) : ( + + onSelectValue(val.toString(), "ctpvCd", field ?? "") + } + className="" + value={sidoValue} + /> + ), + }, + { + name: "sggCd", + label: "시군구", + component: (field) => + updateList?.dmdInfoId ? ( + { + field.onChange(e.target.value); + }} + value={ + selectSigunData.find((item) => item.val === field.value?.trim()) + ?.text ?? "" + } + readOnly={!!updateList?.dmdInfoId} + /> + ) : ( + + onSelectValue(val.toString(), "sggCd", field) + } + className="" + value={sigunValue} + /> + ), + }, + { + name: "dmdCoNm", + label: "회사명", + component: (field) => ( + ), - }, - { - name: "sggCd", - label: "시군구", - component: (field) => - updateList?.dmdInfoId ? ( + }, + { + name: "dmdInfoId", + label: "사업자등록번호", + component: (field) => ( { - field.onChange(e.target.value); - }} - value={ - selectSigunData.find((item) => item.val === field.value?.trim()) - ?.text ?? "" - } + onChange={(e) => bznNoChange(e, "dmdInfoId", field)} + value={formatBusinessNumber(field.value ?? "")} readOnly={!!updateList?.dmdInfoId} /> - ) : ( - - onSelectValue(val.toString(), "sggCd", field) - } - className="" - value={sigunValue} - /> ), - }, - { - name: "dmdCoNm", - label: "회사명", - component: (field) => ( - - ), - }, - { - name: "dmdInfoId", - label: "사업자등록번호", - component: (field) => ( - bznNoChange(e, "dmdInfoId", field)} - value={formatBusinessNumber(field.value ?? "")} - readOnly={!!updateList?.dmdInfoId} - /> - ), - }, - { - name: "bznmTotNo", - label: "", - component: (field) => ( - + }, + { + name: "bznmTotNo", + label: "", + component: (field) => ( + + bznNoChange(e, "bznmTotNo", field)} + // {...field} + value={field.value ?? ""} + readOnly={!!updateList?.dmdInfoId} + /> + + ), + }, + { + name: "daddr", + label: "사업자주소", + component: (field) => + openNetwork ? ( + + + {/* 우편번호 */} + + setIsZipModalOpen(true)}>우편번호 검색 + + {/* 주소 */} + + {/* 상세 주소 */} + { + const value = e.target.value; + setDetailedAddress(value); + }} + value={detailedAddress ?? ""} + /> + + ) : ( + + ), + }, + { + name: "telno", + label: "전화번호", + component: (field) => { + const formattedValue = formatPhoneNumber(field.value ?? ""); // 초기 렌더링 시에도 포맷 적용 + + return ( + { + const value = e.target.value.replace(/\D/g, ""); // 숫자만 저장 + field.onChange(value); + }} + /> + ); + }, + }, + + { + name: "dmdAplyPswd", + label: "패스워드", + component: (field) => ( bznNoChange(e, "bznmTotNo", field)} - // {...field} - value={field.value ?? ""} - readOnly={!!updateList?.dmdInfoId} - /> - - ), - }, - { - name: "daddr", - label: "사업자주소", - component: (field) => - openNetwork ? ( - { - field.onChange(rtnData.roadAddrPart1); - }} - /> - ) : ( - ), - }, - { - name: "telno", - label: "전화번호", - component: (field) => { - const formattedValue = formatPhoneNumber(field.value ?? ""); // 초기 렌더링 시에도 포맷 적용 - - return ( - { - const value = e.target.value.replace(/\D/g, ""); // 숫자만 저장 - field.onChange(value); - }} - /> - ); }, - }, - - { - name: "dmdAplyPswd", - label: "패스워드", - component: (field) => ( - - ), - }, - { - name: "dmdAplyPswdConfirm", - label: "패스워드확인", - component: (field) => ( - - ), - }, - ]; + { + name: "dmdAplyPswdConfirm", + label: "패스워드확인", + component: (field) => ( + + ), + }, + ]; return ( <> @@ -538,6 +725,36 @@ export function SdmRegForm({ /> ); })} + -1 ? 'h-[80vh]' : 'h-[30vh]'} + w-[30vw] + min-w-[500px] + max-w-[90vw] + max-h-[85vh] + overflow-y-auto + !fixed + !top-[50%] + !left-[50%] + !-translate-x-1/2 + !-translate-y-1/2 + z-[101] + flex + flex-col + `} + body={renderBody()} + footerContent={ + + 선택 + setIsZipModalOpen(false)}>취소 + + } + useDirectRender={true} + /> > ); } diff --git a/packages/common/business_components/src/ui/sdmInsertForm/index.tsx b/packages/common/business_components/src/ui/sdmInsertForm/index.tsx index 1b9aed0a0..ef9dbeed2 100644 --- a/packages/common/business_components/src/ui/sdmInsertForm/index.tsx +++ b/packages/common/business_components/src/ui/sdmInsertForm/index.tsx @@ -39,7 +39,7 @@ const createFormSchema = (isBznmTotNoDisabled: boolean, isDuplicate: boolean ,up .refine(() => !isDuplicate, "이미 등록된 사업자등록번호입니다"), daddr: z.string() .min(1, "주소를 입력해주세요") - .min(6, "주소는 6자 이상 입력해주세요") + // .min(6, "주소는 6자 이상 입력해주세요") .max(40, "주소는 40자 이내로 입력해주세요"), telno: z.string() .min(8, "전화번호는 8자 이상 입력해주세요") diff --git a/packages/common/business_components/src/ui/search_input_address/findAddress.ts b/packages/common/business_components/src/ui/search_input_address/findAddress.ts index c458b80c4..33cd14d13 100644 --- a/packages/common/business_components/src/ui/search_input_address/findAddress.ts +++ b/packages/common/business_components/src/ui/search_input_address/findAddress.ts @@ -2,11 +2,13 @@ // const Key = 'U01TX0FVVEgyMDI1MDgyODE0MTAxNzExNjEyMjA' // const addresssKey = 'devU01TX0FVVEgyMDI1MDgyNTEwMzkwNDExNjEwNTM='; //인증키 만료일은 2025-11-23 +import type { Zip, ZipSearchParams } from "./zipService"; + /** * 주소 API 응답 타입 * https://business.juso.go.kr/addrlink/main.do 해당 사이트 참조 */ -export type AddressApiResponse ={ +export type AddressApiResponse = { results: { common: { errorMessage: string; @@ -19,7 +21,7 @@ export type AddressApiResponse ={ }; } -export type addressType ={ +export type addressType = { detBdNmList: string; engAddr: string; rn: string; @@ -46,79 +48,70 @@ export type addressType ={ buldSlno: string; } - - - - /** * 주소에 따른 검색 * @param search : 검색어 * @returns addressType[] 주소 배열 */ -export const findAddress = async (search: string) => { - if (!search) { - return []; - } - const params = new URLSearchParams({ - currentPage: "1", // 원하는 페이지 - countPerPage: "5", // 페이지당 결과 수 - keyword: search, // 검색어(주소) - confmKey: '', // 인증키 인터넷용 패쇄망용은 따로 발급 필요 즉 middleware에서 치환해서 사용해야할듯 - resultType: "json", // 결과 형식 기본은 xml - }); - // const url = `https://business.juso.go.kr/addrlink/addrLinkApi.do?${params.toString()}`; - const url = `/bussiness-juso-service/addrlink/addrLinkApi.do?${params.toString()}`; - try { - const response = await fetch(url); - if (!response.ok) { - throw new Error('Network response was not ok'); - } - const data = await response.json(); - if (data.results && data.results.juso) { - return data.results.juso as addressType[]; - } else { - return []; - } +export const findAddress = async (searchQuery: ZipSearchParams): Promise => { + if (!searchQuery) return []; + + // 쿼리 파라미터 생성 + const params = new URLSearchParams(); + if (searchQuery.roadNm) params.append('roadNm', searchQuery.roadNm); + if (searchQuery.bldgNoMno != null) params.append('bldgNoMno', searchQuery.bldgNoMno.toString()); + if (searchQuery.bldgNoSno != null) params.append('bldgNoSno', searchQuery.bldgNoSno.toString()); + if (searchQuery.page != null) params.append('page', searchQuery.page.toString()); + if (searchQuery.size != null) params.append('size', searchQuery.size.toString()); + + const url = `/cms-service/api/v1/zips?${params.toString()}`; + try { + const response = await fetch(url); + if (!response.ok) throw new Error('Network response was not ok'); + + const data = await response.json(); + if (data) return data + else return []; } catch (error) { - console.error('Error fetching address data:', error); - return []; + console.error('Error fetching address data:', error); + return []; } } -export const searchFilter=(search:string)=>{ +export const searchFilter = (search: string) => { - if(search.length >0){ - //특수문자 제거 - const expText = /[%=><]/ ; - if(expText.test(search) == true){ - alert("특수문자를 입력 할수 없습니다.") ; - search = search.split(expText).join(""); - return false; - } - - //특정문자열(sql예약어의 앞뒤공백포함) 제거 - const sqlArray = [ - //sql 예약어 - "OR", "SELECT", "INSERT", "DELETE", "UPDATE", "CREATE", "DROP", "EXEC", - "UNION", "FETCH", "DECLARE", "TRUNCATE" + if (search.length > 0) { + //특수문자 제거 + const expText = /[%=><]/; + if (expText.test(search) == true) { + alert("특수문자를 입력 할수 없습니다."); + search = search.split(expText).join(""); + return false; + } + + //특정문자열(sql예약어의 앞뒤공백포함) 제거 + const sqlArray = [ + //sql 예약어 + "OR", "SELECT", "INSERT", "DELETE", "UPDATE", "CREATE", "DROP", "EXEC", + "UNION", "FETCH", "DECLARE", "TRUNCATE" ] - - let regex; - for(let i=0; i void; - readonly?: boolean; -}; +// type thisProps = { +// initValue: string | undefined; +// setRtnData: (rtnData: addressType) => void; +// readonly?: boolean; +// }; -/** - * - * @param initValue : 초기값 ? - * @returns setRtnData => 선택된 주소 데이터 반환 - */ -export default function SearchInputAddress({ - initValue, - setRtnData = () => {}, - readonly = false, -}: thisProps) { - const [isOpen, setIsOpen] = useState(false); - const [textValue, setTextValue] = useState(initValue || ""); - const [searchList, setSearchList] = useState([]); +// /** +// * +// * @param initValue : 초기값 ? +// * @returns setRtnData => 선택된 주소 데이터 반환 +// */ +// export default function SearchInputAddress({ +// initValue, +// setRtnData = () => {}, +// readonly = false, +// }: thisProps) { +// const [isOpen, setIsOpen] = useState(false); +// const [textValue, setTextValue] = useState(initValue || ""); +// const [searchList, setSearchList] = useState([]); - useEffect(() => { - if ( - initValue !== textValue && - initValue !== undefined && - initValue !== null && - initValue !== "" - ) { - setTextValue(initValue); - } - }, [initValue]); - const wrapperRef = useRef(null); +// useEffect(() => { +// if ( +// initValue !== textValue && +// initValue !== undefined && +// initValue !== null && +// initValue !== "" +// ) { +// setTextValue(initValue); +// } +// }, [initValue]); +// const wrapperRef = useRef(null); - const handleInputChange = useCallback( - (e: React.ChangeEvent) => { - const value = e.target.value; +// const handleInputChange = useCallback( +// (e: React.ChangeEvent) => { +// const value = e.target.value; - if (searchFilter(value)) { - setTextValue(value); - findAddress(value).then((data) => { - setSearchList(data); - }); - }else{ - setTextValue(""); - setSearchList([]); - } - if (value) { - setIsOpen(true); - } else { - setIsOpen(false); - } - }, - [setSearchList], - ); +// if (searchFilter(value)) { +// setTextValue(value); +// findAddress(value).then((data) => { +// setSearchList(data); +// }); +// }else{ +// setTextValue(""); +// setSearchList([]); +// } +// if (value) { +// setIsOpen(true); +// } else { +// setIsOpen(false); +// } +// }, +// [setSearchList], +// ); - const handleSuggestionClick = useCallback( - (roadAddrPart1: string) => { - setTextValue(roadAddrPart1); - setIsOpen(false); - setRtnData( - searchList?.find((item) => item.roadAddrPart1 === roadAddrPart1) || - ({} as addressType), - ); - }, - [searchList, setRtnData], - ); +// const handleSuggestionClick = useCallback( +// (roadAddrPart1: string) => { +// setTextValue(roadAddrPart1); +// setIsOpen(false); +// setRtnData( +// searchList?.find((item) => item.roadAddrPart1 === roadAddrPart1) || +// ({} as addressType), +// ); +// }, +// [searchList, setRtnData], +// ); - useEffect(() => { - const handleClickOutside = (event: MouseEvent) => { - if ( - wrapperRef.current && - !wrapperRef.current.contains(event.target as Node) - ) { - setIsOpen(false); - } - }; +// useEffect(() => { +// const handleClickOutside = (event: MouseEvent) => { +// if ( +// wrapperRef.current && +// !wrapperRef.current.contains(event.target as Node) +// ) { +// setIsOpen(false); +// } +// }; - document.addEventListener("mousedown", handleClickOutside); - return () => { - document.removeEventListener("mousedown", handleClickOutside); - }; - }, []); +// document.addEventListener("mousedown", handleClickOutside); +// return () => { +// document.removeEventListener("mousedown", handleClickOutside); +// }; +// }, []); - return ( - - setIsOpen(true)} */ - className="h-[3.2rem] w-full rounded-md border border-gray-300 pl-3 !text-xl text-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500" - placeholder={`주소를 입력하세요`} - readOnly={readonly} - /> - {isOpen && ( - - - {searchList && searchList.length > 0 ? ( - searchList.map((item: addressType, index: number) => ( - handleSuggestionClick(item.roadAddrPart1)} - role="button" - tabIndex={0} - onKeyDown={(e) => { - if (e.key === "Enter" || e.key === " ") { - handleSuggestionClick(item.roadAddrPart1); - } - }} - > - {item.zipNo} - {item.roadAddrPart1} - - )) - ) : ( - - 검색 결과가 없습니다. - - )} - - - )} - - ); -} +// return ( +// +// setIsOpen(true)} */ +// className="h-[3.2rem] w-full rounded-md border border-gray-300 pl-3 !text-xl text-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500" +// placeholder={`주소를 입력하세요`} +// readOnly={readonly} +// /> +// {isOpen && ( +// +// +// {searchList && searchList.length > 0 ? ( +// searchList.map((item: addressType, index: number) => ( +// handleSuggestionClick(item.roadAddrPart1)} +// role="button" +// tabIndex={0} +// onKeyDown={(e) => { +// if (e.key === "Enter" || e.key === " ") { +// handleSuggestionClick(item.roadAddrPart1); +// } +// }} +// > +// {item.zipNo} +// {item.roadAddrPart1} +// +// )) +// ) : ( +// +// 검색 결과가 없습니다. +// +// )} +// +// +// )} +// +// ); +// } diff --git a/packages/common/business_components/src/ui/search_input_address/zipService.ts b/packages/common/business_components/src/ui/search_input_address/zipService.ts new file mode 100644 index 000000000..04f0b85b2 --- /dev/null +++ b/packages/common/business_components/src/ui/search_input_address/zipService.ts @@ -0,0 +1,66 @@ +interface SortConfig { + empty: boolean; + sorted: boolean; + unsorted: boolean; +} + +interface PageableConfig { + sort: SortConfig; + offset: number; + pageNumber: number; + pageSize: number; + paged: boolean; + unpaged: boolean; +} + +export interface PageableList { + content: T[]; + pageable: PageableConfig; + sort: SortConfig; + totalPages: number; + totalElements: number; + number: number; + numberOfElements: number; + size: number; + first: boolean; + last: boolean; + empty: boolean; +} + +export interface PageableParams { + page?: number; + size?: number; + sort?: string; +} + + +export interface ZipSearchParams extends PageableParams { + zoneNo?: string; // 구역번호 + ctpvNm?: string; // 시도명 + sggNm?: string; // 시군구명 + emdNm?: string; // 읍면동명 + roadNm?: string; // 도로명 + stdgNm?: string; // 법정동명 + dongNm?: string; // 행정동명 + bldgNoMno?: number | null; // 빌딩본번 + bldgNoSno?: number | null; // 빌딩딩부번 + lotnoMno?: number | null; // 지번본번 + lotnoSno?: number | null; // 지번부번 +} + +export interface Zip { + zipId: number; + zoneNo: string; + ctpvNm: string; + sggNm: string; + emdNm: string; + roadNm: string; + bldgNoMno: number; + bldgNoSno: number; + lotnoMno: number; + lotnoSno: number; + lotno: string; + zipAddr: string; +} + +export type ZipList = PageableList;