feat: [inspection] Phase 3 TemplateInspectionContent API 연동
- getInspectionConfig Server Action 추가 - InspectionConfigData/Item/GapPoint 타입 정의 - TemplateInspectionContent API 연동 - inspectionConfig state + useEffect로 API 호출 - bendingProducts: API 우선 → buildBendingProducts fallback - bending_info에서 dimension 보조 데이터 추출
This commit is contained in:
@@ -773,6 +773,52 @@ export async function saveInspectionData(
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 검사 설정 조회 (공정 판별 + 구성품 목록) =====
|
||||
export interface InspectionConfigGapPoint {
|
||||
point: string;
|
||||
design_value: string;
|
||||
}
|
||||
|
||||
export interface InspectionConfigItem {
|
||||
id: string;
|
||||
name: string;
|
||||
gap_points: InspectionConfigGapPoint[];
|
||||
}
|
||||
|
||||
export interface InspectionConfigData {
|
||||
work_order_id: number;
|
||||
process_type: string;
|
||||
product_code: string | null;
|
||||
template_id: number | null;
|
||||
items: InspectionConfigItem[];
|
||||
}
|
||||
|
||||
export async function getInspectionConfig(
|
||||
workOrderId: string | number
|
||||
): Promise<{ success: boolean; data?: InspectionConfigData; error?: string }> {
|
||||
try {
|
||||
const { response, error } = await serverFetch(
|
||||
buildApiUrl(`/api/v1/work-orders/${workOrderId}/inspection-config`),
|
||||
{ method: 'GET' }
|
||||
);
|
||||
|
||||
if (error || !response) {
|
||||
return { success: false, error: error?.message || 'API 요청 실패' };
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
if (!response.ok || !result.success) {
|
||||
return { success: false, error: result.message || '검사 설정을 불러올 수 없습니다.' };
|
||||
}
|
||||
|
||||
return { success: true, data: result.data };
|
||||
} catch (error) {
|
||||
if (isNextRedirectError(error)) throw error;
|
||||
console.error('[WorkOrderActions] getInspectionConfig error:', error);
|
||||
return { success: false, error: '서버 오류가 발생했습니다.' };
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 검사 문서 템플릿 조회 (document_template 기반) =====
|
||||
import type { InspectionTemplateData } from '@/components/production/WorkerScreen/types';
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@ import {
|
||||
} from './inspection-shared';
|
||||
import { formatNumber } from '@/lib/utils/amount';
|
||||
import type { BendingInfoExtended } from './bending/types';
|
||||
import { getInspectionConfig } from '../actions';
|
||||
import type { InspectionConfigData } from '../actions';
|
||||
|
||||
export type { InspectionContentRef };
|
||||
|
||||
@@ -375,10 +377,60 @@ export const TemplateInspectionContent = forwardRef<InspectionContentRef, Templa
|
||||
)?.id ?? null;
|
||||
}, [isBending, template.columns]);
|
||||
|
||||
// ===== inspection-config API 연동 =====
|
||||
const [inspectionConfig, setInspectionConfig] = useState<InspectionConfigData | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isBending || !order.id) return;
|
||||
let cancelled = false;
|
||||
getInspectionConfig(order.id).then(result => {
|
||||
if (!cancelled && result.success && result.data) {
|
||||
setInspectionConfig(result.data);
|
||||
}
|
||||
});
|
||||
return () => { cancelled = true; };
|
||||
}, [isBending, order.id]);
|
||||
|
||||
const bendingProducts = useMemo(() => {
|
||||
if (!isBending) return [];
|
||||
|
||||
// API 응답이 있고 items가 있으면 API 기반 구성품 사용
|
||||
if (inspectionConfig?.items?.length) {
|
||||
const productCode = inspectionConfig.product_code || '';
|
||||
// bending_info에서 dimension 보조 데이터 추출
|
||||
const bi = order.bendingInfo as BendingInfoExtended | undefined;
|
||||
const wallLen = bi?.guideRail?.wall?.lengthData?.[0]?.length;
|
||||
const sideLen = bi?.guideRail?.side?.lengthData?.[0]?.length;
|
||||
|
||||
return inspectionConfig.items.map((item): BendingProduct => {
|
||||
// API id → 표시용 매핑 (이름, 타입, 치수)
|
||||
const displayMap: Record<string, { name: string; type: string; len: string; wid: string }> = {
|
||||
guide_rail_wall: { name: '가이드레일', type: '벽면형', len: String(wallLen || 3500), wid: 'N/A' },
|
||||
guide_rail_side: { name: '가이드레일', type: '측면형', len: String(sideLen || 3000), wid: 'N/A' },
|
||||
bottom_bar: { name: '하단마감재', type: '60×40', len: '3000', wid: 'N/A' },
|
||||
case_box: { name: '케이스', type: '양면', len: '3000', wid: 'N/A' },
|
||||
smoke_w50: { name: '연기차단재', type: '화이바 W50\n가이드레일용', len: '-', wid: '50' },
|
||||
smoke_w80: { name: '연기차단재', type: '화이바 W80\n케이스용', len: '-', wid: '80' },
|
||||
};
|
||||
const d = displayMap[item.id] || { name: item.name, type: '', len: '-', wid: 'N/A' };
|
||||
return {
|
||||
id: item.id,
|
||||
category: productCode,
|
||||
productName: d.name,
|
||||
productType: d.type,
|
||||
lengthDesign: d.len,
|
||||
widthDesign: d.wid,
|
||||
gapPoints: item.gap_points.map(gp => ({
|
||||
point: gp.point,
|
||||
designValue: gp.design_value,
|
||||
})),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// fallback: 기존 프론트 로직 사용
|
||||
return buildBendingProducts(order);
|
||||
}, [isBending, order]);
|
||||
}, [isBending, order, inspectionConfig]);
|
||||
|
||||
const bendingExpandedRows = useMemo(() => {
|
||||
if (!isBending) return [];
|
||||
|
||||
Reference in New Issue
Block a user