import React, { useEffect, useRef } from 'react'; import { View, Text, TouchableOpacity, StyleSheet, Animated, Alert, } from 'react-native'; import { useRouter } from 'expo-router'; import { SvgXml } from 'react-native-svg'; import { colors, typography, spacing, radius } from '@shared/theme'; import { readNFCTagUseCase, nfcRepository } from '@infrastructure/container'; const NFC_SVG = ` `; /** * Bottom sheet modal de leitura NFC — artboard 1RY-0 */ export default function NFCReaderScreen(): React.ReactElement { const router = useRouter(); const ring1 = useRef(new Animated.Value(0)).current; const ring2 = useRef(new Animated.Value(0)).current; const ring3 = useRef(new Animated.Value(0)).current; useEffect(() => { const pulse = (ring: Animated.Value, delay: number) => Animated.loop( Animated.sequence([ Animated.delay(delay), Animated.timing(ring, { toValue: 1, duration: 1400, useNativeDriver: true, }), Animated.timing(ring, { toValue: 0, duration: 0, useNativeDriver: true, }), ]), ); const a1 = pulse(ring1, 0); const a2 = pulse(ring2, 400); const a3 = pulse(ring3, 800); a1.start(); a2.start(); a3.start(); startReading(); return () => { a1.stop(); a2.stop(); a3.stop(); nfcRepository.cancelSession().catch(() => {}); }; }, []); async function startReading(): Promise { try { const filamentId = await readNFCTagUseCase.execute(); router.replace(`/(app)/inventory/${filamentId}` as never); } catch (err: unknown) { const message = err instanceof Error ? err.message : 'Erro ao ler a tag.'; Alert.alert('Erro NFC', message, [{ text: 'OK', onPress: () => router.back() }]); } } const ringStyle = (anim: Animated.Value) => ({ opacity: anim.interpolate({ inputRange: [0, 0.5, 1], outputRange: [0.5, 0.15, 0] }), transform: [{ scale: anim.interpolate({ inputRange: [0, 1], outputRange: [1, 2.2] }) }], }); return ( {/* Bottom sheet */} {/* Drag handle */} {/* NFC animation area */} {/* Status badge */} LENDO... {/* Text */} Aguardando NFC Aproxime a tag do carretel ao sensor NFC do seu dispositivo {/* Cancel */} { nfcRepository.cancelSession().catch(() => {}); router.back(); }} > Cancelar ); } const RING_SIZE = 120; const styles = StyleSheet.create({ overlay: { flex: 1, backgroundColor: 'rgba(0,0,0,0.6)', justifyContent: 'flex-end', }, sheet: { backgroundColor: colors.bgSurface, borderTopLeftRadius: radius.xl, borderTopRightRadius: radius.xl, paddingBottom: spacing[10], paddingHorizontal: spacing[6], alignItems: 'center', gap: spacing[4], paddingTop: spacing[3], }, handle: { width: 36, height: 4, borderRadius: radius.full, backgroundColor: colors.border, marginBottom: spacing[4], }, iconArea: { width: RING_SIZE * 2.2, height: RING_SIZE * 2.2, alignItems: 'center', justifyContent: 'center', }, ring: { position: 'absolute', width: RING_SIZE, height: RING_SIZE, borderRadius: RING_SIZE / 2, borderWidth: 2, borderColor: colors.accent, }, iconCircle: { width: RING_SIZE, height: RING_SIZE, borderRadius: RING_SIZE / 2, backgroundColor: colors.bgHover, borderWidth: 1, borderColor: colors.border, alignItems: 'center', justifyContent: 'center', }, badge: { flexDirection: 'row', alignItems: 'center', gap: spacing[2], backgroundColor: colors.bgHover, paddingHorizontal: spacing[3], paddingVertical: spacing[1], borderRadius: radius.full, borderWidth: 1, borderColor: colors.border, }, badgeDot: { width: 7, height: 7, borderRadius: 4, backgroundColor: colors.stockOk, }, badgeText: { fontFamily: typography.fontFamily.ui, fontSize: typography.fontSize.xs, fontWeight: typography.fontWeight.semibold, color: colors.textSecondary, letterSpacing: 0.8, }, title: { fontFamily: typography.fontFamily.ui, fontSize: typography.fontSize.xl, fontWeight: typography.fontWeight.semibold, color: colors.textPrimary, textAlign: 'center', }, subtitle: { fontFamily: typography.fontFamily.ui, fontSize: typography.fontSize.sm, color: colors.textSecondary, textAlign: 'center', lineHeight: 20, }, cancelBtn: { marginTop: spacing[2], backgroundColor: colors.bgHover, borderRadius: radius.md, paddingVertical: spacing[4], width: '100%', alignItems: 'center', borderWidth: 1, borderColor: colors.border, }, cancelText: { fontFamily: typography.fontFamily.ui, fontSize: typography.fontSize.base, color: colors.textPrimary, }, });