Initial commit
This commit is contained in:
102
components/QrScanModal.tsx
Normal file
102
components/QrScanModal.tsx
Normal file
@@ -0,0 +1,102 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { View, Text, Modal, TouchableOpacity, Vibration, StyleSheet, Dimensions } from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { CameraView, useCameraPermissions } from 'expo-camera';
|
||||
import { X, ScanLine } from 'lucide-react-native';
|
||||
|
||||
interface QrScanModalProps {
|
||||
visible: boolean;
|
||||
onClose: () => void;
|
||||
onScan: (data: string) => void;
|
||||
}
|
||||
|
||||
export default function QrScanModal({ visible, onClose, onScan }: QrScanModalProps) {
|
||||
const [permission, requestPermission] = useCameraPermissions();
|
||||
const [scanned, setScanned] = useState(false);
|
||||
const scanInProgress = useRef(false);
|
||||
const { width, height } = Dimensions.get('window');
|
||||
const squareSize = Math.min(width * 0.8, height * 0.8, 400);
|
||||
|
||||
// Permission Handling and Reset Scanned State on Modal Open
|
||||
useEffect(() => {
|
||||
if (visible) {
|
||||
setScanned(false);
|
||||
scanInProgress.current = false;
|
||||
if (permission && !permission.granted && permission.canAskAgain) {
|
||||
requestPermission();
|
||||
}
|
||||
}
|
||||
}, [visible, permission]);
|
||||
|
||||
const handleBarCodeScanned = ({ type, data }: { type: string; data: string }) => {
|
||||
if (scanInProgress.current) return;
|
||||
scanInProgress.current = true;
|
||||
|
||||
setScanned(true);
|
||||
Vibration.vibrate();
|
||||
console.log(`Bar code with type ${type} and data ${data} has been scanned!`);
|
||||
onScan(data);
|
||||
onClose();
|
||||
};
|
||||
|
||||
if (!permission) {
|
||||
return <View />;
|
||||
}
|
||||
|
||||
if (!permission.granted && visible) {
|
||||
requestPermission();
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={visible}
|
||||
animationType="slide"
|
||||
presentationStyle="fullScreen"
|
||||
onRequestClose={onClose}
|
||||
>
|
||||
<View className="flex-1 bg-black">
|
||||
{/* Camera Full Screen */}
|
||||
<CameraView
|
||||
style={StyleSheet.absoluteFillObject}
|
||||
facing="back"
|
||||
onBarcodeScanned={scanned ? undefined : handleBarCodeScanned}
|
||||
barcodeScannerSettings={{
|
||||
barcodeTypes: ["qr"],
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Dark Overlay with Transparent "Hole" (Visually Simulated with Borders or Opacity) */}
|
||||
<SafeAreaView className="flex-1 justify-between bg-black/60 pt-8">
|
||||
{/* Header Overlay */}
|
||||
<View className="items-center">
|
||||
<Text className="text-white text-xl font-bold">Scansiona QR Code</Text>
|
||||
<Text className="text-gray-300 text-base mt-1">Inquadra il codice nel riquadro</Text>
|
||||
</View>
|
||||
|
||||
{/* Central Area (Transparent for the camera) */}
|
||||
<View className="items-center justify-center" style={{ height: squareSize }}>
|
||||
<View style={{ width: squareSize, height: squareSize }}
|
||||
className="border-2 border-[#1071C2] bg-transparent relative justify-center items-center">
|
||||
{/* Decorative Corners */}
|
||||
<View className="absolute top-0 left-0 w-6 h-6 border-l-4 border-t-4 border-[#1071C2]" />
|
||||
<View className="absolute top-0 right-0 w-6 h-6 border-r-4 border-t-4 border-[#1071C2]" />
|
||||
<View className="absolute bottom-0 left-0 w-6 h-6 border-l-4 border-b-4 border-[#1071C2]" />
|
||||
<View className="absolute bottom-0 right-0 w-6 h-6 border-r-4 border-b-4 border-[#1071C2]" />
|
||||
|
||||
{/* Animated Scan Line or Icon */}
|
||||
{!scanned && <ScanLine color="#1071C2" size={40} className="opacity-50" pointerEvents="none" />}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Footer Overlay */}
|
||||
<View className="items-center justify-end pb-12">
|
||||
<TouchableOpacity onPress={onClose} className="bg-white/20 p-4 rounded-full">
|
||||
<X color="white" size={32} pointerEvents="none" />
|
||||
</TouchableOpacity>
|
||||
<Text className="text-white mt-4 font-medium">Chiudi</Text>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
</View>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user