Initial commit for Greenlens
This commit is contained in:
226
app/profile/data.tsx
Normal file
226
app/profile/data.tsx
Normal file
@@ -0,0 +1,226 @@
|
||||
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,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user