93 lines
2.3 KiB
TypeScript
93 lines
2.3 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
|
import { View, Text, StyleSheet, Button, Alert } from 'react-native';
|
|
import { BarCodeScanner } from 'expo-barcode-scanner';
|
|
|
|
interface QRScannerProps {
|
|
onScan: (data: string) => void;
|
|
onClose?: () => void;
|
|
}
|
|
|
|
export const QRScanner: React.FC<QRScannerProps> = ({ onScan, onClose }) => {
|
|
const [hasPermission, setHasPermission] = useState<boolean | null>(null);
|
|
const [scanned, setScanned] = useState(false);
|
|
|
|
useEffect(() => {
|
|
const getBarCodeScannerPermissions = async () => {
|
|
const { status } = await BarCodeScanner.requestPermissionsAsync();
|
|
setHasPermission(status === 'granted');
|
|
};
|
|
|
|
getBarCodeScannerPermissions();
|
|
}, []);
|
|
|
|
const handleBarCodeScanned = ({ type, data }: { type: string; data: string }) => {
|
|
setScanned(true);
|
|
onScan(data);
|
|
Alert.alert('QR Code', `Scanned: ${data}`, [
|
|
{ text: 'OK', onPress: () => setScanned(false) },
|
|
]);
|
|
};
|
|
|
|
if (hasPermission === null) {
|
|
return (
|
|
<View style={styles.container}>
|
|
<Text>Requesting for camera permission...</Text>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
if (hasPermission === false) {
|
|
return (
|
|
<View style={styles.container}>
|
|
<Text>No access to camera</Text>
|
|
{onClose && <Button title="Close" onPress={onClose} />}
|
|
</View>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<View style={styles.container}>
|
|
<BarCodeScanner
|
|
onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
|
|
style={StyleSheet.absoluteFillObject}
|
|
/>
|
|
<View style={styles.overlay}>
|
|
<View style={styles.scanBox} />
|
|
</View>
|
|
{onClose && (
|
|
<View style={styles.buttonContainer}>
|
|
<Button title="Close Scanner" onPress={onClose} color="#FF6B6B" />
|
|
</View>
|
|
)}
|
|
</View>
|
|
);
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
backgroundColor: '#000',
|
|
},
|
|
overlay: {
|
|
flex: 1,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
scanBox: {
|
|
width: 250,
|
|
height: 250,
|
|
borderWidth: 2,
|
|
borderColor: '#4CAF50',
|
|
borderRadius: 10,
|
|
backgroundColor: 'transparent',
|
|
},
|
|
buttonContainer: {
|
|
position: 'absolute',
|
|
bottom: 20,
|
|
left: 20,
|
|
right: 20,
|
|
},
|
|
});
|