feat: add simple geofence status card to attendance screen - demo mode
This commit is contained in:
parent
231ad44cc4
commit
0c272502f8
@ -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',
|
||||
},
|
||||
})
|
||||
|
||||
Loading…
Reference in New Issue
Block a user