matiru
Blockchain-Based Supply Chain Transparency for Agricultural Producegit clone https://github.com/maydayv7/matiru
frontend/components/Scanner.js (2720B)
1import { useState, useEffect } from "react";
2import {
3 Alert,
4 Button,
5 Dimensions,
6 StyleSheet,
7 TextInput,
8 View,
9} from "react-native";
10import { CameraView, Camera } from "expo-camera";
11import styles, { colors } from "../styles";
12
13const { width } = Dimensions.get("window");
14const SCAN_AREA_SIZE = width * 0.7;
15
16export default function Scanner({ value, onChange }) {
17 const [hasPermission, setHasPermission] = useState(null);
18 const [useCamera, setUseCamera] = useState(false);
19 const [scanned, setScanned] = useState(false);
20
21 useEffect(() => {
22 (async () => {
23 const { status } = await Camera.requestCameraPermissionsAsync();
24 setHasPermission(status === "granted");
25 })();
26 }, []);
27
28 const handleScanned = ({ data }) => {
29 if (!data) {
30 Alert.alert("Scan Failed", "No data found in QR code");
31 return;
32 }
33
34 setScanned(true);
35 onChange(data);
36 setUseCamera(false);
37 };
38
39 return (
40 <View style={{ marginVertical: 8 }}>
41 <Button
42 title={useCamera ? "Use Manual Entry" : "Scan QR Code"}
43 color={colors.darkGreen}
44 onPress={() => {
45 setUseCamera(!useCamera);
46 setScanned(false);
47 }}
48 />
49 {useCamera ? (
50 !scanned ? (
51 <View style={{ height: SCAN_AREA_SIZE * 1.4, marginTop: 10 }}>
52 <CameraView
53 style={{ flex: 1 }}
54 onBarcodeScanned={scanned ? undefined : handleScanned}
55 barcodeScannerSettings={{ barcodeTypes: ["qr"] }}
56 />
57 <View style={cameraStyles.overlay}>
58 <View style={cameraStyles.topBottomOverlay} />
59 <View style={cameraStyles.middleRow}>
60 <View style={cameraStyles.sideOverlay} />
61 <View style={cameraStyles.scanArea} />
62 <View style={cameraStyles.sideOverlay} />
63 </View>
64 <View style={cameraStyles.topBottomOverlay} />
65 </View>
66 </View>
67 ) : null
68 ) : (
69 <TextInput
70 style={[styles.input, { marginTop: 10 }]}
71 placeholder="Enter Produce ID"
72 value={value}
73 onChangeText={onChange}
74 />
75 )}
76 </View>
77 );
78}
79
80const cameraStyles = StyleSheet.create({
81 overlay: {
82 ...StyleSheet.absoluteFillObject,
83 justifyContent: "center",
84 alignItems: "center",
85 },
86 topBottomOverlay: {
87 flex: 1,
88 width: "100%",
89 backgroundColor: "rgba(0,0,0,0.5)",
90 },
91 middleRow: {
92 flexDirection: "row",
93 },
94 sideOverlay: {
95 flex: 1,
96 backgroundColor: "rgba(0,0,0,0.5)",
97 },
98 scanArea: {
99 width: SCAN_AREA_SIZE,
100 height: SCAN_AREA_SIZE,
101 borderWidth: 2,
102 borderColor: colors.midGreen,
103 },
104});