import React, { useState, useEffect, useRef } from "react"; import { View, Pressable, Platform, ActivityIndicator, Image, StyleSheet, } from "react-native"; import { Text } from "@/components/ui/text"; import { Button } from "@/components/ui/button"; import { X, Zap, ScanLine, Check, RefreshCw, } from "@/lib/icons"; import { ScreenWrapper } from "@/components/ScreenWrapper"; import { CameraView, useCameraPermissions } from "expo-camera"; import { useSirouRouter } from "@sirou/react-native"; import { AppRoutes } from "@/lib/routes"; import { useNavigation } from "expo-router"; import { BASE_URL } from "@/lib/api"; import { useAuthStore } from "@/lib/auth-store"; import { toast } from "@/lib/toast-store"; import { setScanData } from "@/lib/scan-cache"; const NAV_BG = "#ffffff"; export default function DeclarationScanScreen() { const nav = useSirouRouter(); const [permission, requestPermission] = useCameraPermissions(); const [torch, setTorch] = useState(false); const [scanning, setScanning] = useState(false); const [previewUri, setPreviewUri] = useState(null); const cameraRef = useRef(null); const navigation = useNavigation(); const token = useAuthStore((s) => s.token); useEffect(() => { navigation.setOptions({ tabBarStyle: { display: "none" } }); return () => { navigation.setOptions({ tabBarStyle: { display: "flex", backgroundColor: NAV_BG, borderTopWidth: 0, elevation: 10, height: 75, paddingBottom: Platform.OS === "ios" ? 30 : 10, paddingTop: 10, marginHorizontal: 20, position: "absolute", bottom: 25, left: 20, right: 20, borderRadius: 32, shadowColor: "#000", shadowOffset: { width: 0, height: 10 }, shadowOpacity: 0.12, shadowRadius: 20, }, }); }; }, [navigation]); const handleCapture = async () => { if (!cameraRef.current || scanning) return; try { const photo = await cameraRef.current.takePictureAsync({ quality: 0.8, base64: false, }); if (photo?.uri) { setPreviewUri(photo.uri); } } catch (err) { console.error("[DeclarationScan] Capture Error:", err); toast.error("Capture Failed", "Could not take a photo."); } }; const handleProcess = async () => { if (!previewUri || scanning) return; setScanning(true); try { toast.info("Processing...", "Uploading declaration for AI extraction."); const formData = new FormData(); const fileExt = previewUri.split(".").pop() || "jpg"; const fileName = `declaration-${Date.now()}.${fileExt}`; const type = `image/${fileExt === "jpg" ? "jpeg" : fileExt}`; formData.append("file", { uri: Platform.OS === "android" ? previewUri : previewUri.replace("file://", ""), name: fileName, type: type, } as any); const response = await fetch(`${BASE_URL}declarations/scan`, { method: "POST", headers: { Authorization: `Bearer ${token}`, Accept: "application/json", }, body: formData, }); if (!response.ok) { const err = await response .json() .catch(() => ({ message: "Scan processing failed." })); throw new Error(err.message || "Extraction failed."); } const scanResult = await response.json(); console.log("[DeclarationScan] Extracted data:", scanResult); toast.success("Success!", "Extracted data from declaration."); setScanData({ type: "declaration", data: scanResult, }); setPreviewUri(null); setScanning(false); nav.go("declarations/create"); return; } catch (err: any) { console.error("[DeclarationScan] Processing Error:", err); toast.error( "Processing Failed", err.message || "Declaration extraction failed.", ); } finally { setScanning(false); } }; if (!permission) { return ; } if (!permission.granted) { return ( Camera Access We need your permission to use the camera to scan declarations automatically. nav.back()} className="mt-4 border border-border w-3/4 rounded-[12px] py-3 flex-row justify-center items-center" > Go Back ); } return ( {previewUri ? ( Preview setPreviewUri(null)} className="h-12 w-12 rounded-full bg-black/40 items-center justify-center border border-white/20" > ) : ( {/* Top bar */} setTorch(!torch)} className={`h-12 w-12 rounded-full items-center justify-center border border-white/20 ${torch ? "bg-primary" : "bg-black/40"}`} > nav.back()} className="h-12 w-12 rounded-full bg-black/40 items-center justify-center border border-white/20" > {/* Scan Frame */} {/* Capture Button */} Tap to Capture )} ); }