dm_new: 우편번호 검색 수정

This commit is contained in:
dongsilove
2026-02-24 22:37:52 +09:00
parent 4cfe33bdc7
commit f812e021b4
3 changed files with 203 additions and 11 deletions
+65 -6
View File
@@ -4,6 +4,7 @@ import { useEffect, useRef, useState } from "react";
import { createPortal } from "react-dom";
import {
fetchPostcode,
fetchPostcodeSuggestions,
parsePostcodeInput,
type AddrItem,
type PostcodeSearchResult,
@@ -33,6 +34,7 @@ export default function PostcodeModal({ open, onClose, onSelect }: Props) {
const dq = useDebouncedValue(q, 250);
const [items, setItems] = useState<AddrItem[]>([]);
const [suggestions, setSuggestions] = useState<string[]>([]);
const [total, setTotal] = useState(0);
const [loading, setLoading] = useState(false);
const [searchMessage, setSearchMessage] = useState("");
@@ -41,6 +43,16 @@ export default function PostcodeModal({ open, onClose, onSelect }: Props) {
useEffect(() => setMounted(true), []);
useEffect(() => {
if (open) return;
setQ("");
setItems([]);
setSuggestions([]);
setTotal(0);
setLoading(false);
setSearchMessage("");
}, [open]);
useEffect(() => {
if (!open) return;
@@ -60,6 +72,32 @@ export default function PostcodeModal({ open, onClose, onSelect }: Props) {
};
}, [open, onClose]);
useEffect(() => {
if (!open) return;
const keyword = dq.trim();
if (!keyword) {
setSuggestions([]);
return;
}
let alive = true;
(async () => {
try {
const nextSuggestions = await fetchPostcodeSuggestions(keyword);
if (!alive) return;
setSuggestions(nextSuggestions);
} catch {
if (!alive) return;
setSuggestions([]);
}
})();
return () => {
alive = false;
};
}, [dq, open]);
useEffect(() => {
if (!open) return;
@@ -99,7 +137,10 @@ export default function PostcodeModal({ open, onClose, onSelect }: Props) {
setTotal(0);
setSearchMessage("우편번호 검색 중 오류가 발생했습니다.");
} finally {
if (alive) setLoading(false);
if (alive) {
setLoading(false);
setSuggestions([]);
}
}
})();
@@ -108,6 +149,8 @@ export default function PostcodeModal({ open, onClose, onSelect }: Props) {
};
}, [dq, open]);
const showSuggest = open && q.trim().length >= 1 && suggestions.length > 0;
if (!mounted || !open) return null;
return createPortal(
@@ -175,11 +218,27 @@ export default function PostcodeModal({ open, onClose, onSelect }: Props) {
</svg>
</button>
{/* suggestions dropdown
<div className="absolute left-0 right-0 top-[calc(100%+6px)] z-10 overflow-hidden rounded-md border border-slate-200 bg-white shadow-lg">
이후 다른 API 연동 예정
</div>
*/}
{/* suggestions dropdown */}
{showSuggest && (
<div className="absolute left-0 right-0 top-[calc(100%+6px)] z-10 overflow-hidden rounded-md border border-slate-200 bg-white shadow-lg">
{suggestions.map((s) => (
<button
key={s}
type="button"
className="flex w-full items-center justify-between px-4 py-3 text-left text-[14px] hover:bg-slate-50"
onClick={() => {
// ✅ 추천 클릭 → 입력값 채우고 드롭다운 닫기 + 포커스 유지
setQ(s);
setSuggestions([]);
requestAnimationFrame(() => inputRef.current?.focus());
}}
>
<span className="truncate text-slate-800">{s}</span>
<span className="ml-4 text-slate-400">↵</span>
</button>
))}
</div>
)}
</div>
</div>