ace #1

Open
dimitar wants to merge 42 commits from ace into master
3 changed files with 142 additions and 3 deletions
Showing only changes of commit 94beb7da78 - Show all commits

View File

@ -0,0 +1,47 @@
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import QRCode from 'react-native-qrcode-svg';
interface QRCodeProps {
value: string;
size?: number;
logo?: string;
}
export const QRCodeGenerator: React.FC<QRCodeProps> = ({
value,
size = 250
}) => {
return (
<View style={styles.container}>
<View style={styles.qrWrapper}>
<QRCode
value={value}
size={size}
color="black"
backgroundColor="white"
quietZone={10}
/>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 16,
},
qrWrapper: {
padding: 16,
backgroundColor: 'white',
borderRadius: 12,
elevation: 5,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.25,
shadowRadius: 3.84,
},
});

View File

@ -0,0 +1,92 @@
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,
},
});

View File

@ -3,10 +3,10 @@
* Handles gym location validation and distance calculations
*/
// Gym location coordinates (example: gym location)
// Gym location coordinates - Teretana Isaija Mazhovski, Skopje, North Macedonia
export const GYM_LOCATION = {
latitude: 37.7749,
longitude: -122.4194,
latitude: 41.9973,
longitude: 21.4280,
};
// Geofence radius in meters (500m default)