diff --git a/app/src/screens/ScanScreen.tsx b/app/src/screens/ScanScreen.tsx index 9fa6580..1901a4e 100644 --- a/app/src/screens/ScanScreen.tsx +++ b/app/src/screens/ScanScreen.tsx @@ -1,5 +1,14 @@ import React, { useCallback, useRef, useState } from 'react'; -import { ActivityIndicator, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; +import { + ActivityIndicator, + Alert, + Modal, + StyleSheet, + Text, + TextInput, + TouchableOpacity, + View, +} from 'react-native'; import { Camera, useCameraDevice, @@ -14,38 +23,98 @@ import type { RootStackParamList } from '@/navigation/RootNavigator'; type Nav = NativeStackNavigationProp; /** - * Scan a kiosk QR code (its `ScannerCode`), look the meter up via the API, and - * jump to the detail screen where it can be saved/shared. - * Uses on-device VisionCamera code scanning — no Google Play Services. + * Interpret a scanned code. Kiosk QR codes come in two flavors: + * - a raw scanner/zone code (e.g. "DSB13") -> use directly + * - a ParkSmarter/ips-txt2pay URL. If it has a query with the code + * (…/processQR?code=DSB13) we extract it; a bare app-link URL (this older + * sticker: …/processQR) carries no zone, so we ask for the printed Zone ID. */ +export function parseScannedCode(raw: string): { code?: string; isAppLink?: boolean } { + const v = raw.trim(); + if (!/^https?:\/\//i.test(v)) return { code: v }; + if (v.length > 255) return {}; + const lower = v.toLowerCase(); + if (!(lower.includes('parksmarter.com') || lower.includes('ips-txt2pay'))) { + return { isAppLink: true }; + } + const q = v.split('?')[1]; + if (!q) return { isAppLink: true }; + for (const pair of q.split('&')) { + const [k, val] = pair.split('='); + if (val && /^(code|zone|zoneid|m|meter)$/i.test(k)) { + return { code: decodeURIComponent(val) }; + } + } + const bare = q.split('&')[0]; + if (bare && !bare.includes('=')) return { code: decodeURIComponent(bare) }; + return { isAppLink: true }; +} + export function ScanScreen() { const navigation = useNavigation