489fa50d11
- 검색 폼 정합성: wace JSP `<!-- 주석처리된 검색필터 -->` 블록까지 잘못 이식했던 부분 정정 - 견적: 11→7개 (제품구분/국내해외/유무상/요청납기 제거) - 주문: 13→9개 (제품구분/국내해외/유무상/견적환종 제거) - 매출: 10→11개 (출하지시상태 제거 + 제품구분·국내/해외 추가, JSP 순서로 재배치) - 판매: 변경 없음 (원본 그대로 일치) - 매출 백엔드: SaleListFilter에 productType/nation 추가, getRevenueList에 partObjId/serialNo/orderDate/productType/nation 5개 필터 처리 - 공통 UX - 초기화 버튼을 4개 메뉴 동일하게 통일 (variant=ghost, 버튼 영역 끝) - <Input type="date">는 빈 값 placeholder 숨김 + 캘린더 아이콘 숨김 + 영역 클릭으로 picker 자동(showPicker) - 신규 공통 컴포넌트: CommCodeSelect/CustomerSelect/CustomerSearchDialog/PartSelect/ItemSearchDialog + backend salesCommonRoutes - 문서: 01/02/04 검색 폼 표를 활성/비활성 분리 형식으로 정정, README에 8. 공통 UX 규칙 섹션 신설 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
83 lines
2.4 KiB
TypeScript
83 lines
2.4 KiB
TypeScript
"use client";
|
|
|
|
import React, { useEffect, useState } from "react";
|
|
import { SmartSelect, SmartSelectOption } from "@/components/common/SmartSelect";
|
|
import { apiClient } from "@/lib/api/client";
|
|
|
|
/**
|
|
* 영업관리 4개 메뉴 공통: wace_plm comm_code 그룹키 단위 옵션 셀렉트.
|
|
*
|
|
* group_id (parent_code_id) 별 알려진 키:
|
|
* - 0000167: 주문유형 (category_cd)
|
|
* - 0000001: 제품구분 (product)
|
|
* - 0001219: 국내/해외 (area_cd)
|
|
* - 0000156: 유/무상 (paid_type, code_id 0000157=유상, 0000158=무상)
|
|
* - 0000963: 수주상태 (contract_result)
|
|
* - 0001533: 환종 (contract_currency)
|
|
* - 0900207: 판매상태
|
|
* - 0900215: 과세구분 (tax_type)
|
|
*/
|
|
|
|
interface CommCodeSelectProps {
|
|
groupId: string;
|
|
value: string;
|
|
onValueChange: (value: string) => void;
|
|
placeholder?: string;
|
|
/** "전체" 옵션을 맨 앞에 추가 (기본 true) */
|
|
withAll?: boolean;
|
|
disabled?: boolean;
|
|
className?: string;
|
|
}
|
|
|
|
const cache = new Map<string, SmartSelectOption[]>();
|
|
const inflight = new Map<string, Promise<SmartSelectOption[]>>();
|
|
|
|
const fetchGroup = async (groupId: string): Promise<SmartSelectOption[]> => {
|
|
if (cache.has(groupId)) return cache.get(groupId)!;
|
|
if (inflight.has(groupId)) return inflight.get(groupId)!;
|
|
const p = (async () => {
|
|
const res = await apiClient.get(`/sales/codes/${groupId}`);
|
|
const rows = (res.data?.data ?? []) as Array<{ code: string; label: string }>;
|
|
const opts = rows
|
|
.filter((r) => r.code)
|
|
.map((r) => ({ code: r.code, label: r.label || r.code }));
|
|
cache.set(groupId, opts);
|
|
return opts;
|
|
})();
|
|
inflight.set(groupId, p);
|
|
try {
|
|
return await p;
|
|
} finally {
|
|
inflight.delete(groupId);
|
|
}
|
|
};
|
|
|
|
export function CommCodeSelect({
|
|
groupId, value, onValueChange,
|
|
placeholder = "전체",
|
|
withAll = true,
|
|
disabled, className,
|
|
}: CommCodeSelectProps) {
|
|
const [options, setOptions] = useState<SmartSelectOption[]>(cache.get(groupId) ?? []);
|
|
|
|
useEffect(() => {
|
|
let alive = true;
|
|
fetchGroup(groupId)
|
|
.then((opts) => { if (alive) setOptions(opts); })
|
|
.catch(() => {});
|
|
return () => { alive = false; };
|
|
}, [groupId]);
|
|
|
|
// SmartSelect 자체는 빈 string value 처리 못함 → withAll은 placeholder로 표현
|
|
return (
|
|
<SmartSelect
|
|
options={options}
|
|
value={value}
|
|
onValueChange={onValueChange}
|
|
placeholder={placeholder}
|
|
disabled={disabled}
|
|
className={className}
|
|
/>
|
|
);
|
|
}
|