import React, { useState } from 'react' import { View, Text, StyleSheet, TouchableOpacity, Alert, ScrollView, ActivityIndicator } from 'react-native' import { COLORS } from '../../constants/Config' import client from '../../services/api' export default function NFCAssetScreen() { const [scanning, setScanning] = useState(false) const [asset, setAsset] = useState(null) const startScan = async () => { setScanning(true) setAsset(null) try { const NFC = (() => { try { return require('react-native-nfc-manager').default } catch { return null } })() if (!NFC) { Alert.alert('NFC 미지원', '이 기기는 NFC를 지원하지 않거나 모듈이 설치되지 않았습니다.'); setScanning(false); return } await NFC.start() await NFC.requestTechnology(['Ndef']) const tag = await NFC.getTag() const payload = tag?.ndefMessage?.[0]?.payload const assetId = payload ? String.fromCharCode(...payload).replace(/^\x02en/, '') : null if (!assetId) { Alert.alert('오류', 'NFC 태그에서 자산 ID를 읽을 수 없습니다.'); setScanning(false); return } const r = await client.get(`/api/cmdb/assets/${assetId}`) setAsset(r.data) } catch (e: any) { if (!e.message?.includes('cancel')) Alert.alert('스캔 실패', e.message ?? 'NFC 스캔에 실패했습니다.') } finally { setScanning(false) try { const NFC = require('react-native-nfc-manager').default; NFC.cancelTechnologyRequest() } catch {} } } const checkin = async () => { if (!asset) return try { await client.post('/api/servers/field-checkin', { server_id: asset.id, source: 'nfc', method: 'nfc_tag' }) Alert.alert('완료', `${asset.hostname ?? asset.name} 실사 체크인 완료!`) } catch { Alert.alert('오류', '체크인에 실패했습니다.') } } return ( NFC 자산 인식 NFC 태그가 부착된 서버·장비에 폰을 가져다 대세요. {scanning ? : NFC 스캔 시작} {asset && ( {asset.hostname ?? asset.name} IP***.***.*** OS{asset.os_name ?? '-'} 위치{asset.location ?? '-'} 기관{asset.institution_name ?? '-'} 상태{asset.status ?? '-'} 실사 체크인 )} ) } const s = StyleSheet.create({ container: { flex: 1, backgroundColor: COLORS.bg }, title: { fontSize: 22, fontWeight: '800', color: COLORS.text, marginBottom: 8 }, subtitle: { fontSize: 13, color: COLORS.muted, marginBottom: 24 }, scanBtn: { backgroundColor: COLORS.accent, borderRadius: 16, padding: 24, alignItems: 'center', marginBottom: 24, elevation: 3 }, scanText: { color: '#fff', fontSize: 18, fontWeight: '800' }, assetCard: { backgroundColor: '#fff', borderRadius: 16, padding: 16, elevation: 2 }, assetName: { fontSize: 20, fontWeight: '800', color: COLORS.text, marginBottom: 16 }, infoRow: { flexDirection: 'row', paddingVertical: 8, borderBottomWidth: 1, borderBottomColor: COLORS.border }, label: { width: 60, fontSize: 12, color: COLORS.muted, fontWeight: '600' }, val: { flex: 1, fontSize: 13, color: COLORS.text }, checkinBtn: { backgroundColor: COLORS.success, borderRadius: 10, padding: 14, alignItems: 'center', marginTop: 16 }, checkinText:{ color: '#fff', fontSize: 14, fontWeight: '800' }, })