refactor(WEB): SearchableSelectionModal 공통화 및 actions lookup 통합

- SearchableSelectionModal<T> 제네릭 컴포넌트 추출 (organisms)
- 검색 모달 5개 리팩토링: SupplierSearch, QuotationSelect, SalesOrderSelect, OrderSelect, ItemSearch
- shared-lookups API 유틸 추가 (거래처/품목/수주 등 공통 조회)
- create-crud-service 확장 (lookup, search 메서드)
- actions.ts 20+개 파일 lookup 패턴 통일
- 공통 페이지 패턴 가이드 문서 추가
- CLAUDE.md Common Component Usage Rules 추가

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
유병철
2026-02-10 16:01:23 +09:00
parent 0643d56194
commit 437d5f6834
42 changed files with 1683 additions and 1144 deletions

View File

@@ -12,20 +12,13 @@
import { executeServerAction, type ActionResult } from '@/lib/api/execute-server-action';
import { isNextRedirectError } from '@/lib/utils/redirect-error';
import type { PaginatedApiResponse } from '@/lib/api/types';
import type { ReferenceRecord, ApprovalType, DocumentStatus } from './types';
// ============================================
// API 응답 타입 정의
// ============================================
interface PaginatedResponse<T> {
current_page: number;
data: T[];
total: number;
per_page: number;
last_page: number;
}
interface ReferenceApiData {
id: number;
document_number: string;
@@ -108,7 +101,7 @@ export async function getReferences(params?: {
if (params?.sort_by) searchParams.set('sort_by', params.sort_by);
if (params?.sort_dir) searchParams.set('sort_dir', params.sort_dir);
const result = await executeServerAction<PaginatedResponse<ReferenceApiData>>({
const result = await executeServerAction<PaginatedApiResponse<ReferenceApiData>>({
url: `${API_URL}/api/v1/approvals/reference?${searchParams.toString()}`,
errorMessage: '참조 목록 조회에 실패했습니다.',
});