- fileLogger: append redacted API requests/responses + app events to an on-device log file (persists across restarts); the client's logSink now writes to it - Diagnostics screen (Account > Diagnostics): toggle recording, Share log file (expo-sharing), clear. StartSession logs the session attempt/result explicitly. - Lets a real parking session be captured while away from a computer, then shared. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
92 lines
3.2 KiB
TypeScript
92 lines
3.2 KiB
TypeScript
import React from 'react';
|
|
import { ScrollView, StyleSheet, Switch, Text, TouchableOpacity, View } from 'react-native';
|
|
import { Ionicons } from '@expo/vector-icons';
|
|
import { useNavigation } from '@react-navigation/native';
|
|
import type { NativeStackNavigationProp } from '@react-navigation/native-stack';
|
|
import { useAuth } from '@/auth/AuthContext';
|
|
import { useTheme } from '@/theme/ThemeContext';
|
|
import type { RootStackParamList } from '@/navigation/RootNavigator';
|
|
|
|
type Nav = NativeStackNavigationProp<RootStackParamList>;
|
|
|
|
export function AccountScreen() {
|
|
const { colors, mode, toggle } = useTheme();
|
|
const { logout } = useAuth();
|
|
const navigation = useNavigation<Nav>();
|
|
|
|
const Item = ({
|
|
icon,
|
|
label,
|
|
onPress,
|
|
}: {
|
|
icon: keyof typeof Ionicons.glyphMap;
|
|
label: string;
|
|
onPress: () => void;
|
|
}) => (
|
|
<TouchableOpacity
|
|
style={[styles.item, { borderBottomColor: colors.border }]}
|
|
onPress={onPress}
|
|
>
|
|
<Ionicons name={icon} size={20} color={colors.primary} />
|
|
<Text style={[styles.itemText, { color: colors.text }]}>{label}</Text>
|
|
<Ionicons name="chevron-forward" size={18} color={colors.subtext} />
|
|
</TouchableOpacity>
|
|
);
|
|
|
|
return (
|
|
<ScrollView style={{ backgroundColor: colors.bg }} contentContainerStyle={{ padding: 16 }}>
|
|
<View style={[styles.card, { backgroundColor: colors.card }]}>
|
|
<Item icon="person" label="Profile" onPress={() => navigation.navigate('Profile')} />
|
|
<Item icon="car-sport" label="Vehicles" onPress={() => navigation.navigate('Vehicles')} />
|
|
<Item
|
|
icon="card"
|
|
label="Payment methods"
|
|
onPress={() => navigation.navigate('PaymentMethods')}
|
|
/>
|
|
<Item
|
|
icon="notifications"
|
|
label="Notifications"
|
|
onPress={() => navigation.navigate('Notifications')}
|
|
/>
|
|
<Item icon="information-circle" label="About" onPress={() => navigation.navigate('About')} />
|
|
</View>
|
|
|
|
<Text style={[styles.section, { color: colors.subtext }]}>Settings</Text>
|
|
<View style={[styles.card, { backgroundColor: colors.card }]}>
|
|
<View style={[styles.item, { borderBottomColor: colors.border }]}>
|
|
<Ionicons name="moon" size={20} color={colors.primary} />
|
|
<Text style={[styles.itemText, { color: colors.text }]}>Dark mode</Text>
|
|
<Switch value={mode === 'dark'} onValueChange={toggle} />
|
|
</View>
|
|
<Item icon="bug" label="Diagnostics" onPress={() => navigation.navigate('Diagnostics')} />
|
|
</View>
|
|
|
|
<TouchableOpacity
|
|
style={[styles.logout, { borderColor: colors.danger }]}
|
|
onPress={logout}
|
|
>
|
|
<Text style={{ color: colors.danger, fontWeight: '700' }}>Sign out</Text>
|
|
</TouchableOpacity>
|
|
</ScrollView>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
card: { borderRadius: 12, paddingHorizontal: 16 },
|
|
section: { marginTop: 24, marginBottom: 8, marginLeft: 4, fontSize: 13, fontWeight: '600' },
|
|
item: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
gap: 12,
|
|
paddingVertical: 16,
|
|
borderBottomWidth: StyleSheet.hairlineWidth,
|
|
},
|
|
itemText: { flex: 1, fontSize: 16 },
|
|
logout: {
|
|
marginTop: 28,
|
|
borderWidth: 1.5,
|
|
borderRadius: 12,
|
|
padding: 14,
|
|
alignItems: 'center',
|
|
},
|
|
});
|