fix(입고등록): 품목코드/발주처 검색 API 연동 및 최소 입력 조건 추가

- SearchableSelect에 서버 검색 모드 구현 (onSearch 콜백 + 디바운스 300ms)
- 최소 입력 조건: 한글 완성형 1자 또는 영문/숫자 2자 이상
- 조건 미충족 시 안내 메시지 표시, 옵션 목록 숨김
- ReceivingDetail에서 handleItemSearch/handleSupplierSearch로 API 호출 연동
- 초기 전체 로드 제거, 검색 시에만 API 호출
This commit is contained in:
2026-01-29 11:32:18 +09:00
parent 3e6cdb5ed5
commit 3dab72701e
2 changed files with 101 additions and 22 deletions

View File

@@ -90,23 +90,33 @@ export function ReceivingDetail({ id, mode = 'view' }: Props) {
// 수입검사 성적서 모달 상태
const [isInspectionModalOpen, setIsInspectionModalOpen] = useState(false);
// 품목/발주처 검색 옵션
// 품목/발주처 검색 옵션 및 로딩 상태
const [itemOptions, setItemOptions] = useState<SearchableSelectOption[]>([]);
const [supplierOptions, setSupplierOptions] = useState<SearchableSelectOption[]>([]);
const [isItemSearching, setIsItemSearching] = useState(false);
const [isSupplierSearching, setIsSupplierSearching] = useState(false);
// 품목/발주처 옵션 초기 로드
useEffect(() => {
if (!isNewMode && !isEditMode) return;
const loadOptions = async () => {
const [itemsResult, suppliersResult] = await Promise.all([
searchItems(),
searchSuppliers(),
]);
if (itemsResult.success) setItemOptions(itemsResult.data);
if (suppliersResult.success) setSupplierOptions(suppliersResult.data);
};
loadOptions();
}, [isNewMode, isEditMode]);
// 품목 검색 핸들러
const handleItemSearch = useCallback(async (query: string) => {
setIsItemSearching(true);
try {
const result = await searchItems(query);
if (result.success) setItemOptions(result.data);
} finally {
setIsItemSearching(false);
}
}, []);
// 발주처 검색 핸들러
const handleSupplierSearch = useCallback(async (query: string) => {
setIsSupplierSearching(true);
try {
const result = await searchSuppliers(query);
if (result.success) setSupplierOptions(result.data);
} finally {
setIsSupplierSearching(false);
}
}, []);
// API 데이터 로드
const loadData = useCallback(async () => {
@@ -322,6 +332,8 @@ export function ReceivingDetail({ id, mode = 'view' }: Props) {
unit: found?.unit ?? prev.unit ?? 'EA',
}));
}}
onSearch={handleItemSearch}
isLoading={isItemSearching}
placeholder="품목코드 검색 및 선택"
searchPlaceholder="품목코드 또는 품목명 검색..."
emptyText="검색 결과가 없습니다"
@@ -348,6 +360,8 @@ export function ReceivingDetail({ id, mode = 'view' }: Props) {
options={supplierOptions}
value={formData.supplier || ''}
onChange={(value) => handleInputChange('supplier', value)}
onSearch={handleSupplierSearch}
isLoading={isSupplierSearching}
placeholder="발주처 검색 및 선택"
searchPlaceholder="발주처명 검색..."
emptyText="검색 결과가 없습니다"