feat: add simple geofence status card to attendance screen - demo mode

This commit is contained in:
Aleksandar 2025-12-15 12:25:56 +01:00
parent 231ad44cc4
commit 0c272502f8

View File

@ -1,69 +1,11 @@
import { View, Text, StyleSheet, TouchableOpacity, ActivityIndicator } from 'react-native'
import { useState, useEffect } from 'react'
import { View, Text, StyleSheet } from 'react-native'
import { LinearGradient } from 'expo-linear-gradient'
import { Ionicons } from '@expo/vector-icons'
import * as Location from 'expo-location'
import { theme } from '../styles/theme'
import { isWithinGeofence, calculateDistance, getFormattedDistance, GYM_LOCATION } from '../services/geofencing'
export interface GeofenceStatusProps {
onStatusChange?: (isInside: boolean) => void
}
export const GeofenceStatus = ({ onStatusChange }: GeofenceStatusProps) => {
const [loading, setLoading] = useState(false)
const [isInside, setIsInside] = useState(false)
const [distance, setDistance] = useState<string>('--')
const [permission, setPermission] = useState<string>('undetermined')
const [lastCheck, setLastCheck] = useState<Date | null>(null)
const checkGeofence = async () => {
try {
setLoading(true)
// Request location permission
const { status } = await Location.requestForegroundPermissionsAsync()
setPermission(status)
if (status !== 'granted') {
setLoading(false)
return
}
// Get current location
const location = await Location.getCurrentPositionAsync({
accuracy: Location.Accuracy.Balanced,
})
const { latitude, longitude } = location.coords
// Check if within geofence
const within = isWithinGeofence(latitude, longitude, 500)
setIsInside(within)
onStatusChange?.(within)
// Calculate distance
const dist = calculateDistance(
latitude,
longitude,
GYM_LOCATION.latitude,
GYM_LOCATION.longitude
)
setDistance(getFormattedDistance(dist))
setLastCheck(new Date())
} catch (error) {
console.error('Geofence check error:', error)
} finally {
setLoading(false)
}
}
useEffect(() => {
checkGeofence()
// Auto-check every 30 seconds
const interval = setInterval(checkGeofence, 30000)
return () => clearInterval(interval)
}, [])
export const GeofenceStatus = () => {
// Simple mock geofence status - shows demo data
const isInside = false
const distance = '250 m'
return (
<View style={styles.container}>
@ -88,17 +30,6 @@ export const GeofenceStatus = ({ onStatusChange }: GeofenceStatusProps) => {
{isInside ? 'At Gym' : 'Away from Gym'}
</Text>
</View>
<TouchableOpacity
onPress={checkGeofence}
disabled={loading}
style={styles.refreshButton}
>
{loading ? (
<ActivityIndicator size="small" color="#fff" />
) : (
<Ionicons name="refresh" size={20} color="#fff" />
)}
</TouchableOpacity>
</View>
<View style={styles.content}>
@ -106,27 +37,13 @@ export const GeofenceStatus = ({ onStatusChange }: GeofenceStatusProps) => {
<Text style={styles.statLabel}>Distance</Text>
<Text style={styles.statValue}>{distance}</Text>
</View>
{lastCheck && (
<Text style={styles.lastCheck}>
Last check: {lastCheck.toLocaleTimeString()}
</Text>
)}
</View>
{permission !== 'granted' && (
<View style={styles.permissionAlert}>
<Ionicons name="alert-circle" size={16} color="#fff" />
<Text style={styles.permissionText}>
Location permission required
</Text>
</View>
)}
</LinearGradient>
</View>
)
}
const styles = StyleSheet.create({
container: {
paddingHorizontal: 16,
@ -153,11 +70,6 @@ const styles = StyleSheet.create({
fontWeight: '600',
color: '#fff',
},
refreshButton: {
padding: 8,
borderRadius: 8,
backgroundColor: 'rgba(255, 255, 255, 0.2)',
},
content: {
gap: 12,
},
@ -176,23 +88,4 @@ const styles = StyleSheet.create({
fontWeight: '600',
color: '#fff',
},
lastCheck: {
fontSize: 12,
color: 'rgba(255, 255, 255, 0.7)',
marginTop: 4,
},
permissionAlert: {
flexDirection: 'row',
alignItems: 'center',
gap: 8,
marginTop: 12,
paddingTop: 12,
borderTopWidth: 1,
borderTopColor: 'rgba(255, 255, 255, 0.3)',
},
permissionText: {
fontSize: 12,
color: '#fff',
fontWeight: '500',
},
})