/* * SCR-M2 [모바일] 홀매니저 현장 검수 — 승인 도면 vs 현장 사진 비교 + AI 사전심사 플래그. * 검수 항목 [적합]/[부적합] 세그먼트 · 부적합 시 사진+메모 · 승인/시정 요청. * 모든 AI 플래그 "현장 확인함" 체크 전 승인 비활성(오조작 방지). */ import { Ionicons } from '@expo/vector-icons'; import { router } from 'expo-router'; import React, { useState } from 'react'; import { Alert, ScrollView, StyleSheet, Text, TextInput, View } from 'react-native'; import { AiImage } from '../components/AiImage'; import { Button } from '../components/Button'; import { Card } from '../components/Card'; import { useAuth } from '../context/AuthContext'; import { colors, radius, spacing, touch, type } from '../theme'; interface Flag { id: string; label: string; severity: 'block' | 'warn'; } const FLAGS: Flag[] = [ { id: 'f1', label: '장치물 높이 5.4m 초과', severity: 'block' }, { id: 'f2', label: '방염 확인서 누락', severity: 'warn' }, { id: 'f3', label: '리깅 구조계산서 미제출', severity: 'warn' }, ]; interface InspItem { id: string; label: string; } const ITEMS: InspItem[] = [ { id: 'height', label: '장치물 높이 (5m 이하)' }, { id: 'flame', label: '방염 라벨 부착' }, { id: 'aisle', label: '통로 침범 여부' }, { id: 'noise', label: '소음 (70~75dB)' }, ]; type Verdict = 'ok' | 'fail' | null; export default function InspectionScreen() { const { activeWorkspace } = useAuth(); const [confirmed, setConfirmed] = useState>({}); const [verdict, setVerdict] = useState>({}); const [memo, setMemo] = useState>({}); const [showFlags, setShowFlags] = useState(true); const allConfirmed = FLAGS.every((f) => confirmed[f.id]); const anyFail = ITEMS.some((it) => verdict[it.id] === 'fail'); const canApprove = allConfirmed && !anyFail; function approve() { Alert.alert('검수 승인', '검수가 승인되었습니다.'); router.back(); } function requestFix() { Alert.alert('시정 요청', '위반 항목이 첨부되어 시공업체에 전달되었습니다.'); router.back(); } return ( 현장 검수 · 부스 A-102 · {activeWorkspace?.hallLabel ?? '홀7'} {/* 비교 카드 */} 승인 도면 도면 v2 현장 사진 (AI 참고) {/* AI 사전심사 플래그 */} AI 사전심사 플래그 {FLAGS.length}건 setShowFlags((v) => !v)} /> {showFlags ? FLAGS.map((f) => ( {f.label} setConfirmed((c) => ({ ...c, [f.id]: !c[f.id] }))} > {confirmed[f.id] ? '확인함' : '확인'} )) : null} {/* 검수 항목 */} {ITEMS.map((it) => ( {it.label} setVerdict((v) => ({ ...v, [it.id]: 'ok' }))} /> setVerdict((v) => ({ ...v, [it.id]: 'fail' }))} /> {verdict[it.id] === 'fail' ? ( setMemo((m) => ({ ...m, [it.id]: t }))} placeholder="부적합 사유 메모 (사진 촬영 필수)" placeholderTextColor={colors.neutral500} style={styles.memo} multiline /> ) : null} ))} {/* 하단 고정 액션 */} {!allConfirmed ? ( 모든 AI 플래그 확인 후 승인할 수 있습니다. ) : null}