227 lines
9.1 KiB
TypeScript
227 lines
9.1 KiB
TypeScript
import React from 'react';
|
|
import { View, Text, TouchableOpacity, ScrollView, StyleSheet, Share, Alert } from 'react-native';
|
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
|
import { Ionicons } from '@expo/vector-icons';
|
|
import { useRouter } from 'expo-router';
|
|
import { useApp } from '../../context/AppContext';
|
|
import { useColors } from '../../constants/Colors';
|
|
import { ThemeBackdrop } from '../../components/ThemeBackdrop';
|
|
import { Language } from '../../types';
|
|
|
|
const getDataCopy = (language: Language) => {
|
|
if (language === 'de') {
|
|
return {
|
|
title: 'Daten & Datenschutz',
|
|
exportData: 'Daten exportieren',
|
|
exportHint: 'Teilt deine Sammlung als JSON.',
|
|
clearHistory: 'Lexikon-Verlauf loeschen',
|
|
clearHistoryHint: 'Entfernt alle letzten Suchbegriffe.',
|
|
clearHistoryDoneTitle: 'Verlauf geloescht',
|
|
clearHistoryDoneMessage: 'Der Suchverlauf wurde entfernt.',
|
|
logout: 'Abmelden',
|
|
logoutHint: 'Zurueck zum Onboarding und Profil zuruecksetzen.',
|
|
logoutConfirmTitle: 'Abmelden?',
|
|
logoutConfirmMessage: 'Du wirst auf den Startbildschirm zurueckgesetzt.',
|
|
deleteAccount: 'Konto unwiderruflich löschen',
|
|
deleteAccountHint: 'Löscht alle deine Daten, Pflanzen und Abos permanent.',
|
|
deleteConfirmTitle: 'Konto wirklich löschen?',
|
|
deleteConfirmMessage: 'Achtung: Dieser Schritt kann nicht rückgängig gemacht werden. Alle deine Pflanzen, Scans und Credits gehen sofort verloren.',
|
|
deleteActionBtn: 'Ja, dauerhaft löschen',
|
|
genericErrorTitle: 'Fehler',
|
|
genericErrorMessage: 'Aktion konnte nicht abgeschlossen werden.',
|
|
};
|
|
}
|
|
|
|
if (language === 'es') {
|
|
return {
|
|
title: 'Datos y Privacidad',
|
|
exportData: 'Exportar Datos',
|
|
exportHint: 'Comparte tu coleccion como JSON.',
|
|
clearHistory: 'Borrar historial',
|
|
clearHistoryHint: 'Elimina las busquedas recientes.',
|
|
clearHistoryDoneTitle: 'Historial borrado',
|
|
clearHistoryDoneMessage: 'El historial de busqueda ha sido eliminado.',
|
|
logout: 'Cerrar sesion',
|
|
logoutHint: 'Volver a la pantalla de inicio y reiniciar perfil.',
|
|
logoutConfirmTitle: 'Cerrar sesion?',
|
|
logoutConfirmMessage: 'Seras enviado a la pantalla de inicio.',
|
|
deleteAccount: 'Eliminar cuenta permanentemente',
|
|
deleteAccountHint: 'Elimina todos tus datos, plantas y suscripciones.',
|
|
deleteConfirmTitle: '¿Seguro que quieres eliminar tu cuenta?',
|
|
deleteConfirmMessage: 'Atención: Este paso no se puede deshacer. Todas tus plantas, escaneos y créditos se perderán inmediatamente.',
|
|
deleteActionBtn: 'Sí, eliminar permanentemente',
|
|
genericErrorTitle: 'Error',
|
|
genericErrorMessage: 'La accion no pudo ser completada.',
|
|
};
|
|
}
|
|
|
|
return {
|
|
title: 'Data & Privacy',
|
|
exportData: 'Export Data',
|
|
exportHint: 'Share your collection as JSON.',
|
|
clearHistory: 'Clear Search History',
|
|
clearHistoryHint: 'Removes recent search queries.',
|
|
clearHistoryDoneTitle: 'History Cleared',
|
|
clearHistoryDoneMessage: 'Search history has been removed.',
|
|
logout: 'Log Out',
|
|
logoutHint: 'Return to onboarding and reset profile.',
|
|
logoutConfirmTitle: 'Log Out?',
|
|
logoutConfirmMessage: 'You will be returned to the start screen.',
|
|
deleteAccount: 'Delete Account Permanently',
|
|
deleteAccountHint: 'Permanently deletes all your data, plants, and subscriptions.',
|
|
deleteConfirmTitle: 'Are you sure?',
|
|
deleteConfirmMessage: 'Warning: This cannot be undone. All your plants, scans, and credits will be lost immediately.',
|
|
deleteActionBtn: 'Yes, delete permanently',
|
|
genericErrorTitle: 'Error',
|
|
genericErrorMessage: 'Action could not be completed.',
|
|
};
|
|
};
|
|
|
|
export default function DataScreen() {
|
|
const router = useRouter();
|
|
const { isDarkMode, language, plants, appearanceMode, colorPalette, clearLexiconSearchHistory, signOut } = useApp();
|
|
const colors = useColors(isDarkMode, colorPalette);
|
|
const copy = getDataCopy(language);
|
|
|
|
const handleExportData = async () => {
|
|
try {
|
|
const dataStr = JSON.stringify(plants, null, 2);
|
|
await Share.share({
|
|
message: dataStr,
|
|
title: 'GreenLens_Export.json',
|
|
});
|
|
} catch {
|
|
Alert.alert(copy.genericErrorTitle, copy.genericErrorMessage);
|
|
}
|
|
};
|
|
|
|
const handleClearHistory = () => {
|
|
clearLexiconSearchHistory();
|
|
Alert.alert(copy.clearHistoryDoneTitle, copy.clearHistoryDoneMessage);
|
|
};
|
|
|
|
const handleLogout = () => {
|
|
Alert.alert(copy.logoutConfirmTitle, copy.logoutConfirmMessage, [
|
|
{ text: 'Cancel', style: 'cancel' },
|
|
{
|
|
text: copy.logout,
|
|
style: 'destructive',
|
|
onPress: async () => {
|
|
await signOut();
|
|
router.replace('/auth/login');
|
|
},
|
|
},
|
|
]);
|
|
};
|
|
|
|
const handleDeleteAccount = () => {
|
|
Alert.alert(copy.deleteConfirmTitle, copy.deleteConfirmMessage, [
|
|
{ text: 'Cancel', style: 'cancel' },
|
|
{
|
|
text: copy.deleteActionBtn,
|
|
style: 'destructive',
|
|
onPress: async () => {
|
|
// Future implementation: call backend to wipe user data, cancel active Stripe subscriptions
|
|
await signOut();
|
|
router.replace('/onboarding');
|
|
},
|
|
},
|
|
]);
|
|
};
|
|
|
|
return (
|
|
<View style={{ flex: 1, backgroundColor: colors.background }}>
|
|
<ThemeBackdrop colors={colors} />
|
|
<SafeAreaView style={styles.safeArea} edges={['top']}>
|
|
<View style={styles.header}>
|
|
<TouchableOpacity onPress={() => router.back()} style={styles.backButton}>
|
|
<Ionicons name="arrow-back" size={24} color={colors.text} />
|
|
</TouchableOpacity>
|
|
<Text style={[styles.title, { color: colors.text }]}>{copy.title}</Text>
|
|
<View style={{ width: 40 }} />
|
|
</View>
|
|
|
|
<ScrollView contentContainerStyle={styles.scrollContent}>
|
|
<TouchableOpacity style={[styles.actionRow, { backgroundColor: colors.cardBg, borderColor: colors.border }]} onPress={handleExportData}>
|
|
<View style={styles.actionIcon}>
|
|
<Ionicons name="download-outline" size={24} color={colors.text} />
|
|
</View>
|
|
<View style={styles.actionTextContainer}>
|
|
<Text style={[styles.actionTitle, { color: colors.text }]}>{copy.exportData}</Text>
|
|
<Text style={[styles.actionHint, { color: `${colors.text}80` }]}>{copy.exportHint}</Text>
|
|
</View>
|
|
</TouchableOpacity>
|
|
|
|
<TouchableOpacity style={[styles.actionRow, { backgroundColor: colors.cardBg, borderColor: colors.border }]} onPress={handleClearHistory}>
|
|
<View style={styles.actionIcon}>
|
|
<Ionicons name="time-outline" size={24} color={colors.text} />
|
|
</View>
|
|
<View style={styles.actionTextContainer}>
|
|
<Text style={[styles.actionTitle, { color: colors.text }]}>{copy.clearHistory}</Text>
|
|
<Text style={[styles.actionHint, { color: `${colors.text}80` }]}>{copy.clearHistoryHint}</Text>
|
|
</View>
|
|
</TouchableOpacity>
|
|
|
|
<TouchableOpacity style={[styles.actionRow, { backgroundColor: colors.cardBg, borderColor: colors.border }]} onPress={handleLogout}>
|
|
<View style={styles.actionIcon}>
|
|
<Ionicons name="log-out-outline" size={24} color={colors.text} />
|
|
</View>
|
|
<View style={styles.actionTextContainer}>
|
|
<Text style={[styles.actionTitle, { color: colors.text }]}>{copy.logout}</Text>
|
|
<Text style={[styles.actionHint, { color: `${colors.text}80` }]}>{copy.logoutHint}</Text>
|
|
</View>
|
|
</TouchableOpacity>
|
|
|
|
<View style={{ marginTop: 24 }}>
|
|
<TouchableOpacity style={[styles.actionRow, { backgroundColor: '#FF3B3015', borderColor: '#FF3B3050', marginBottom: 0 }]} onPress={handleDeleteAccount}>
|
|
<View style={[styles.actionIcon, { backgroundColor: '#FF3B3020' }]}>
|
|
<Ionicons name="trash-bin-outline" size={24} color="#FF3B30" />
|
|
</View>
|
|
<View style={styles.actionTextContainer}>
|
|
<Text style={[styles.actionTitle, { color: '#FF3B30' }]}>{copy.deleteAccount}</Text>
|
|
<Text style={[styles.actionHint, { color: '#FF3B3080' }]}>{copy.deleteAccountHint}</Text>
|
|
</View>
|
|
</TouchableOpacity>
|
|
</View>
|
|
</ScrollView>
|
|
</SafeAreaView>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
safeArea: { flex: 1 },
|
|
header: { flexDirection: 'row', alignItems: 'center', padding: 16 },
|
|
backButton: { width: 40, height: 40, justifyContent: 'center' },
|
|
title: { flex: 1, fontSize: 20, fontWeight: '700', textAlign: 'center' },
|
|
scrollContent: { padding: 16, gap: 16 },
|
|
actionRow: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
padding: 16,
|
|
borderRadius: 16,
|
|
borderWidth: StyleSheet.hairlineWidth,
|
|
marginBottom: 16,
|
|
},
|
|
actionIcon: {
|
|
width: 40,
|
|
height: 40,
|
|
borderRadius: 20,
|
|
backgroundColor: '#00000010',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
marginRight: 16,
|
|
},
|
|
actionTextContainer: {
|
|
flex: 1,
|
|
},
|
|
actionTitle: {
|
|
fontSize: 16,
|
|
fontWeight: '600',
|
|
marginBottom: 4,
|
|
},
|
|
actionHint: {
|
|
fontSize: 13,
|
|
},
|
|
});
|