Merge commit 'a03359540a57d48b8bc1af7ca8ccc2a232e2d12a' into iipbs/wr/dev

This commit is contained in:
leedj312
2025-09-03 16:28:21 +09:00
2 changed files with 73 additions and 24 deletions
@@ -87,3 +87,41 @@ export const findAddress = async (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"
]
let regex;
for(let i=0; i<sqlArray.length; i++){
regex = new RegExp( sqlArray[i] as string,"gi") ;
if (regex.test(search) ) {
alert("\"" + sqlArray[i]+"\"와(과) 같은 특정문자로 검색할 수 없습니다.");
search =search.replace(regex, "");
return false;
}
}
}
return true ;
}
@@ -1,6 +1,6 @@
import { Input } from "@common/components/ui";
import React, { useCallback, useEffect, useRef, useState } from "react";
import { findAddress, type addressType } from "./findAddress";
import { findAddress, searchFilter, type addressType } from "./findAddress";
type thisProps = {
initValue: string | undefined;
@@ -9,52 +9,63 @@ type thisProps = {
};
/**
*
*
* @param initValue : 초기값 ?
* @returns setRtnData => 선택된 주소 데이터 반환
*/
export default function SearchInputAddress({
initValue ,
initValue,
setRtnData = () => {},
readonly=false
readonly = false,
}: thisProps) {
const [isOpen, setIsOpen] = useState(false);
const [textValue, setTextValue] = useState(initValue || "");
const [searchList, setSearchList] = useState<addressType[]>([]);
useEffect(()=>{
if(initValue !== textValue && initValue !== undefined && initValue !== null && initValue !== ''){
setTextValue(initValue)
}
},[initValue])
useEffect(() => {
if (
initValue !== textValue &&
initValue !== undefined &&
initValue !== null &&
initValue !== ""
) {
setTextValue(initValue);
}
}, [initValue]);
const wrapperRef = useRef<HTMLDivElement>(null);
const handleInputChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
setTextValue(value);
findAddress(value).then((data) => {
setSearchList(data);
})
if (searchFilter(value)) {
setTextValue(value);
findAddress(value).then((data) => {
setSearchList(data);
});
}else{
setTextValue("");
setSearchList([]);
}
if (value) {
setIsOpen(true);
} else {
setIsOpen(false);
}
},
[setSearchList]
[setSearchList],
);
const handleSuggestionClick = useCallback(
(roadAddrPart1: string) => {
setTextValue(roadAddrPart1);
setIsOpen(false);
setRtnData(searchList?.find((item) => item.roadAddrPart1 === roadAddrPart1) || ({} as addressType));
setRtnData(
searchList?.find((item) => item.roadAddrPart1 === roadAddrPart1) ||
({} as addressType),
);
},
[searchList, setRtnData]
[searchList, setRtnData],
);
useEffect(() => {
@@ -80,18 +91,18 @@ export default function SearchInputAddress({
value={textValue}
onChange={handleInputChange}
/* onFocus={() => setIsOpen(true)} */
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"
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 && (
<div className="absolute left-0 right-0 mt-2 bg-white border border-gray-300 rounded-md shadow-lg max-h-72 overflow-auto z-50">
<div className="absolute left-0 right-0 z-50 mt-2 max-h-72 overflow-auto rounded-md border border-gray-300 bg-white shadow-lg">
<div className="max-h-72">
{searchList && searchList.length > 0 ? (
searchList.map((item: addressType, index: number) => (
<div
key={index}
className="!text-xl w-full text-left px-5 py-3 hover:bg-gray-100 cursor-pointer overflow-auto"
className="w-full cursor-pointer overflow-auto px-5 py-3 text-left !text-xl hover:bg-gray-100"
onClick={() => handleSuggestionClick(item.roadAddrPart1)}
role="button"
tabIndex={0}
@@ -106,7 +117,7 @@ export default function SearchInputAddress({
</div>
))
) : (
<div className="!text-xl w-full px-5 py-3 hover:bg-gray-100 cursor-pointer overflow-auto">
<div className="w-full cursor-pointer overflow-auto px-5 py-3 !text-xl hover:bg-gray-100">
검색 결과가 없습니다.
</div>
)}