From d3078c7f4a48dc46305054ed386b493f96d48d87 Mon Sep 17 00:00:00 2001 From: pro Date: Fri, 23 Jan 2026 12:34:25 +0900 Subject: [PATCH] =?UTF-8?q?feat:=EA=B3=84=EC=A0=95=EA=B3=BC=EB=AA=A9=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D=EC=97=90=20=EA=B2=80=EC=83=89=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 단순 select를 검색 가능한 커스텀 드롭다운으로 변경 - 코드 또는 이름으로 실시간 검색 - 선택값 초기화(X) 버튼 추가 - 외부 클릭 시 드롭다운 닫힘 Co-Authored-By: Claude Opus 4.5 --- .../views/barobill/eaccount/index.blade.php | 133 +++++++++++++++--- 1 file changed, 117 insertions(+), 16 deletions(-) diff --git a/resources/views/barobill/eaccount/index.blade.php b/resources/views/barobill/eaccount/index.blade.php index e2191cf4..96a9bbee 100644 --- a/resources/views/barobill/eaccount/index.blade.php +++ b/resources/views/barobill/eaccount/index.blade.php @@ -154,22 +154,123 @@ className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${ ); - // AccountCodeSelect Component - const AccountCodeSelect = ({ value, onChange, accountCodes }) => ( - - ); + // AccountCodeSelect Component (검색 가능한 드롭다운) + const AccountCodeSelect = ({ value, onChange, accountCodes }) => { + const [isOpen, setIsOpen] = useState(false); + const [search, setSearch] = useState(''); + const containerRef = useRef(null); + + // 선택된 값의 표시 텍스트 + const selectedItem = accountCodes.find(c => c.code === value); + const displayText = selectedItem ? `${selectedItem.code} ${selectedItem.name}` : ''; + + // 검색 필터링 + const filteredCodes = accountCodes.filter(code => { + if (!search) return true; + const searchLower = search.toLowerCase(); + return code.code.toLowerCase().includes(searchLower) || + code.name.toLowerCase().includes(searchLower); + }); + + // 외부 클릭 시 닫기 + useEffect(() => { + const handleClickOutside = (e) => { + if (containerRef.current && !containerRef.current.contains(e.target)) { + setIsOpen(false); + setSearch(''); + } + }; + document.addEventListener('mousedown', handleClickOutside); + return () => document.removeEventListener('mousedown', handleClickOutside); + }, []); + + const handleSelect = (code) => { + const selected = accountCodes.find(c => c.code === code.code); + onChange(code.code, selected?.name || ''); + setIsOpen(false); + setSearch(''); + }; + + const handleClear = (e) => { + e.stopPropagation(); + onChange('', ''); + setSearch(''); + }; + + return ( +
+ {/* 선택 버튼 */} +
setIsOpen(!isOpen)} + className={`w-full px-2 py-1 text-xs border rounded cursor-pointer flex items-center justify-between gap-1 ${ + isOpen ? 'border-emerald-500 ring-2 ring-emerald-500' : 'border-stone-200' + } bg-white`} + > + + {displayText || '선택'} + +
+ {value && ( + + )} + + + +
+
+ + {/* 드롭다운 */} + {isOpen && ( +
+ {/* 검색 입력 */} +
+ setSearch(e.target.value)} + placeholder="코드 또는 이름 검색..." + className="w-full px-2 py-1 text-xs border border-stone-200 rounded focus:ring-1 focus:ring-emerald-500 outline-none" + autoFocus + /> +
+ {/* 옵션 목록 */} +
+ {filteredCodes.length === 0 ? ( +
+ 검색 결과 없음 +
+ ) : ( + filteredCodes.slice(0, 50).map(code => ( +
handleSelect(code)} + className={`px-3 py-1.5 text-xs cursor-pointer hover:bg-emerald-50 ${ + value === code.code ? 'bg-emerald-100 text-emerald-700' : 'text-stone-700' + }`} + > + {code.code} + {code.name} +
+ )) + )} + {filteredCodes.length > 50 && ( +
+ +{filteredCodes.length - 50}개 더 있음 +
+ )} +
+
+ )} +
+ ); + }; // AccountCodeSettingsModal Component const AccountCodeSettingsModal = ({ isOpen, onClose, onUpdate }) => {