feat: integrate NFC functionality for reading and writing tags

- Added NFCManagerRepository to handle NFC operations using react-native-nfc-manager.
- Implemented ReadNFCTagUseCase and WriteNFCTagUseCase for reading and writing NFC tags.
- Updated app layout to include NFC reader screen.
- Created WriteNFCScreen for writing NFC tags with filament data.
- Enhanced HomeScreen to support NFC reading and added NFC button in FilamentDetailScreen.
- Updated app.json to include react-native-nfc-manager dependency.
- Added animations and user feedback for NFC operations in the UI.
This commit is contained in:
2026-03-14 20:14:06 -03:00
parent 74adc35b53
commit 6a78cb41d8
15 changed files with 797 additions and 23 deletions
+33 -7
View File
@@ -1,7 +1,8 @@
import React, { useEffect } from 'react';
import {
View, Text, ScrollView, TouchableOpacity, StyleSheet,
View, Text, ScrollView, TouchableOpacity, StyleSheet, Alert,
} from 'react-native';
import { SvgXml } from 'react-native-svg';
import { useRouter } from 'expo-router';
import { Ionicons } from '@expo/vector-icons';
import { SafeAreaView } from 'react-native-safe-area-context';
@@ -13,6 +14,16 @@ import { Card } from '@presentation/components/ui/Card';
import { calcFilamentPercentage } from '@domain/Filament';
import { formatWeight } from '@shared/utils/filament';
import { colors, typography, spacing, radius } from '@shared/theme';
import { nfcRepository } from '@infrastructure/container';
const NFC_SVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<g stroke="${colors.textPrimary}" stroke-width="10" fill="none">
<path d="M 23.49 41.51 A 12 12 0 0 1 23.49 58.49"/>
<path d="M 34.80 30.20 A 28 28 0 0 1 34.80 69.80"/>
<path d="M 46.11 18.89 A 44 44 0 0 1 46.11 81.11"/>
<path d="M 57.43 7.57 A 60 60 0 0 1 57.43 92.43"/>
</g>
</svg>`;
/**
* Tela Home / Dashboard — 1-0
@@ -27,6 +38,15 @@ import { colors, typography, spacing, radius } from '@shared/theme';
export default function HomeScreen(): React.ReactElement {
const router = useRouter();
const { user } = useAuthStore();
async function handleNFCRead(): Promise<void> {
const supported = await nfcRepository.isSupported();
if (!supported) {
Alert.alert('NFC indisponível', 'Este dispositivo não possui suporte a NFC.');
return;
}
router.push('/(app)/nfc-reader' as never);
}
const { filaments, isLoading } = useFilamentStore();
// Dados derivados
@@ -54,12 +74,17 @@ export default function HomeScreen(): React.ReactElement {
<Text style={styles.welcomeText}>Bem-vindo de volta,</Text>
<Text style={styles.title}>Seu Inventário</Text>
</View>
<TouchableOpacity
style={styles.qrBtn}
onPress={() => router.push('/(app)/scanner' as never)}
>
<Ionicons name="qr-code-outline" size={22} color={colors.textPrimary} />
</TouchableOpacity>
<View style={styles.headerBtns}>
<TouchableOpacity style={styles.qrBtn} onPress={handleNFCRead}>
<SvgXml xml={NFC_SVG} width={22} height={22} />
</TouchableOpacity>
<TouchableOpacity
style={styles.qrBtn}
onPress={() => router.push('/(app)/scanner' as never)}
>
<Ionicons name="qr-code-outline" size={22} color={colors.textPrimary} />
</TouchableOpacity>
</View>
</View>
{/* Totais */}
@@ -203,6 +228,7 @@ const styles = StyleSheet.create({
headerRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: spacing[2] },
welcomeText: { fontFamily: typography.fontFamily.ui, fontSize: typography.fontSize.sm, color: colors.textSecondary },
title: { fontFamily: typography.fontFamily.ui, fontSize: typography.fontSize['2xl'], fontWeight: typography.fontWeight.bold, color: colors.textPrimary },
headerBtns: { flexDirection: 'row', gap: spacing[2] },
qrBtn: { width: 40, height: 40, borderRadius: radius.md, backgroundColor: colors.bgSurface, alignItems: 'center', justifyContent: 'center', borderWidth: 1, borderColor: colors.border },
statsRow: { flexDirection: 'row', gap: spacing[3] },
statCard: { flex: 1, gap: spacing[1] },