auto-commit for 8033ed4c-21fc-4cc9-a507-2516fe7b0026

This commit is contained in:
emergent-agent-e1
2025-11-08 21:35:15 +00:00
parent d7a512424f
commit 5944b09048
+251
View File
@@ -0,0 +1,251 @@
import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, Alert } from 'react-native';
import { CameraView, Camera } from 'expo-camera';
import { Ionicons } from '@expo/vector-icons';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
export default function QRScannerScreen({ navigation }: any) {
const insets = useSafeAreaInsets();
const [hasPermission, setHasPermission] = useState<boolean | null>(null);
const [scanned, setScanned] = useState(false);
useEffect(() => {
requestCameraPermission();
}, []);
const requestCameraPermission = async () => {
const { status } = await Camera.requestCameraPermissionsAsync();
setHasPermission(status === 'granted');
};
const handleBarCodeScanned = ({ type, data }: any) => {
setScanned(true);
Alert.alert(
'QR Code Scanned',
`Type: ${type}\nData: ${data}`,
[
{
text: 'Scan Again',
onPress: () => setScanned(false),
},
{
text: 'OK',
onPress: () => navigation.goBack(),
},
]
);
};
if (hasPermission === null) {
return (
<View style={styles.container}>
<Text>Requesting camera permission...</Text>
</View>
);
}
if (hasPermission === false) {
return (
<View style={[styles.container, { paddingTop: insets.top }]}>
<View style={styles.header}>
<TouchableOpacity onPress={() => navigation.goBack()} style={styles.backButton}>
<Ionicons name="arrow-back" size={24} color="#FFF" />
</TouchableOpacity>
<Text style={styles.headerTitle}>QR Scanner</Text>
<View style={{ width: 40 }} />
</View>
<View style={styles.permissionContainer}>
<Ionicons name="camera-off" size={64} color="#6B7280" />
<Text style={styles.permissionTitle}>Camera Permission Denied</Text>
<Text style={styles.permissionText}>
Please enable camera access in your device settings to scan QR codes.
</Text>
<TouchableOpacity style={styles.settingsButton} onPress={requestCameraPermission}>
<Text style={styles.settingsButtonText}>Request Permission Again</Text>
</TouchableOpacity>
</View>
</View>
);
}
return (
<View style={styles.container}>
<CameraView
style={styles.camera}
facing="back"
onBarcodeScanned={scanned ? undefined : handleBarCodeScanned}
barcodeScannerSettings={{
barcodeTypes: ['qr'],
}}
>
{/* Header Overlay */}
<View style={[styles.header, { paddingTop: insets.top + 16 }]}>
<TouchableOpacity onPress={() => navigation.goBack()} style={styles.backButton}>
<Ionicons name="arrow-back" size={24} color="#FFF" />
</TouchableOpacity>
<Text style={styles.headerTitle}>Scan QR Code</Text>
<View style={{ width: 40 }} />
</View>
{/* Scanning Frame */}
<View style={styles.scannerContainer}>
<View style={styles.scannerFrame}>
<View style={[styles.corner, styles.cornerTopLeft]} />
<View style={[styles.corner, styles.cornerTopRight]} />
<View style={[styles.corner, styles.cornerBottomLeft]} />
<View style={[styles.corner, styles.cornerBottomRight]} />
</View>
<Text style={styles.instructionText}>
Position the QR code within the frame
</Text>
</View>
{/* Bottom Actions */}
<View style={styles.bottomContainer}>
{scanned && (
<TouchableOpacity
style={styles.scanAgainButton}
onPress={() => setScanned(false)}
>
<Ionicons name="refresh" size={24} color="#FFF" />
<Text style={styles.scanAgainText}>Scan Again</Text>
</TouchableOpacity>
)}
</View>
</CameraView>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#000',
},
camera: {
flex: 1,
},
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: 16,
paddingVertical: 16,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
},
backButton: {
width: 40,
height: 40,
borderRadius: 20,
backgroundColor: 'rgba(255, 255, 255, 0.2)',
alignItems: 'center',
justifyContent: 'center',
},
headerTitle: {
fontSize: 18,
fontWeight: '700',
color: '#FFF',
},
scannerContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
scannerFrame: {
width: 250,
height: 250,
position: 'relative',
},
corner: {
position: 'absolute',
width: 40,
height: 40,
borderColor: '#EE2A35',
},
cornerTopLeft: {
top: 0,
left: 0,
borderTopWidth: 4,
borderLeftWidth: 4,
borderTopLeftRadius: 8,
},
cornerTopRight: {
top: 0,
right: 0,
borderTopWidth: 4,
borderRightWidth: 4,
borderTopRightRadius: 8,
},
cornerBottomLeft: {
bottom: 0,
left: 0,
borderBottomWidth: 4,
borderLeftWidth: 4,
borderBottomLeftRadius: 8,
},
cornerBottomRight: {
bottom: 0,
right: 0,
borderBottomWidth: 4,
borderRightWidth: 4,
borderBottomRightRadius: 8,
},
instructionText: {
marginTop: 32,
fontSize: 16,
color: '#FFF',
textAlign: 'center',
backgroundColor: 'rgba(0, 0, 0, 0.5)',
paddingHorizontal: 24,
paddingVertical: 12,
borderRadius: 8,
},
bottomContainer: {
padding: 32,
alignItems: 'center',
},
scanAgainButton: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#EE2A35',
paddingHorizontal: 24,
paddingVertical: 12,
borderRadius: 12,
},
scanAgainText: {
fontSize: 16,
fontWeight: '600',
color: '#FFF',
marginLeft: 8,
},
permissionContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 32,
},
permissionTitle: {
fontSize: 20,
fontWeight: '700',
color: '#1F2937',
marginTop: 24,
marginBottom: 12,
},
permissionText: {
fontSize: 16,
color: '#6B7280',
textAlign: 'center',
marginBottom: 24,
},
settingsButton: {
backgroundColor: '#EE2A35',
paddingHorizontal: 24,
paddingVertical: 12,
borderRadius: 12,
},
settingsButtonText: {
fontSize: 16,
fontWeight: '600',
color: '#FFF',
},
});