dm_new: 우편번호 검색 수정
This commit is contained in:
@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user