RyanHub – file viewer
filename: app/(tabs)/Settings.jsx
branch: master
back to repo
import React, { useState, useEffect } from 'react';
import { View, Text, Alert, Switch, StyleSheet, Modal, Button, ScrollView, TouchableOpacity, TextInput, Linking } from 'react-native';
import { AntDesign, Ionicons, MaterialIcons } from '@expo/vector-icons';
import { FIREBASE_AUTH } from '../../FirebaseConfig';
import { signOut } from 'firebase/auth';
import AsyncStorage from '@react-native-async-storage/async-storage';

import { useAppTheme, updateApp, getCurrentScheme } from '../../hooks/colorScheme';

export default function Settings({ navigation }) {
  const colors = useAppTheme();
  const [userEmail, setUserEmail] = useState('');
  const [isEnabled, setIsEnabled] = useState(getCurrentScheme() === 'dark');
  const [isPolicyVisible, setIsPolicyVisible] = useState(false);
  const [vibrationEnabled, setVibrationEnabled] = useState(false);
  const [notificationsEnabled, setNotificationsEnabled] = useState(false);
  const [reminderTime, setReminderTime] = useState('21:00');
  const [isFeedbackVisible, setIsFeedbackVisible] = useState(false);
  const [feedbackText, setFeedbackText] = useState('');

  useEffect(() => {
    // Load user email
    const user = FIREBASE_AUTH.currentUser;
    if (user) {
      setUserEmail(user.email);
    }

    // Initialize switch state from stored theme
    AsyncStorage.getItem('@app_theme')
      .then(savedTheme => {
        if (savedTheme) {
          setIsEnabled(savedTheme === 'dark');
        }
      })
      .catch(error => console.error('Error loading theme state:', error));
  }, []);

  const handleLogout = async () => {
    Alert.alert(
      "Logout",
      "Are you sure you want to logout?",
      [
        {
          text: "Cancel",
          style: "cancel"
        },
        { 
          text: "Logout", 
          onPress: async () => {
            try {
              await AsyncStorage.setItem('isLoggedOut', 'true');
              await signOut(FIREBASE_AUTH);
              // The auth state change will automatically trigger navigation
            } catch (error) {
              Alert.alert('Error', 'Failed to logout. Please try again.');
            }
          }
        }
      ]
    );
  };
  const hangleDeleteAccount = async () => {
    Alert.alert(
      "Delete Account",
      "Are you sure you want to delete your account?",
      [
        {
          text: "Cancel",
          style: "cancel"
        },
        { 
          text: "Delete", 
          onPress: async () => {
            try {
              //await FIREBASE_AUTH.currentUser.delete();
              await AsyncStorage.setItem('email', '');
              await AsyncStorage.setItem('isLoggedOut', 'true');
              await signOut(FIREBASE_AUTH);
              // The auth state change will automatically trigger navigation
            } catch (error) {
              Alert.alert('Error', 'Failed to delete account. Please try again.');
            }
          }
        }
      ]
    );
  }
  const privacyPolicyModal = () => {
    setIsPolicyVisible(true);
  };

  const closePrivacyPolicy = () => {
    setIsPolicyVisible(false);
  };

  const doTest = async () => {
    console.log('test! ');
  };

  const flipColorScheme = () => {
    const newScheme = !isEnabled ? 'dark' : 'light';
    setIsEnabled(!isEnabled);
    updateApp(newScheme);
  };

  const gotToPayments = () => {
    console.log('go to payments');
    //navigation.navigate('Payments') // fix when we include payments
  };

  const handleSendFeedback = async () => {
    if (!feedbackText.trim()) {
      Alert.alert('Error', 'Please enter your feedback before sending.');
      return;
    }

    const emailSubject = 'Nobs App Feedback';
    const emailBody = feedbackText;
    const mailtoUrl = `mailto:ryanstestemail123@gmail.com?subject=${encodeURIComponent(emailSubject)}&body=${encodeURIComponent(emailBody)}`;

    const canOpen = await Linking.canOpenURL(mailtoUrl);
    if (canOpen) {
      await Linking.openURL(mailtoUrl);
      setFeedbackText('');
      setIsFeedbackVisible(false);
    } else {
      Alert.alert('Error', 'Could not open email client');
    }
  };

  const openFeedbackModal = () => {
    setIsFeedbackVisible(true);
  };

  const closeFeedbackModal = () => {
    setIsFeedbackVisible(false);
    setFeedbackText('');
  };

  return (
    <ScrollView 
      style={[styles.container, { backgroundColor: colors.background }]}
      contentContainerStyle={styles.contentContainer}
    >
      <View style={[styles.banner, {backgroundColor: colors.boxes}]}>
        <Text style={[styles.headerText, {color: colors.text}]}>Settings</Text>
      </View>

      {/* Account Section */}
      <View style={styles.section}>
        <Text style={[styles.sectionHeader, {color: colors.text}]}>Account</Text>
        <View style={[styles.card, {backgroundColor: colors.boxes}]}>
          <View style={styles.settingRow}>
            <View style={styles.settingInfo}>
              <Ionicons name="person-outline" size={24} color={colors.text} />
              <Text style={[styles.settingText, {color: colors.text}]}>{userEmail}</Text>
            </View>
          </View>
          
          <TouchableOpacity onPress={handleLogout} style={styles.settingRow}>
            <View style={styles.settingInfo}>
              <MaterialIcons name="logout" size={24} color={colors.accent} />
              <Text style={[styles.settingText, {color: colors.accent}]}>Logout</Text>
            </View>
            <AntDesign name="right" size={20} color={colors.accent} />
          </TouchableOpacity>

          <TouchableOpacity onPress={hangleDeleteAccount} style={styles.settingRow}>
            <View style={styles.settingInfo}>
              <MaterialIcons name="delete-outline" size={24} color={colors.accent} />
              <Text style={[styles.settingText, {color: colors.accent}]}>Delete Account</Text>
            </View>
            <AntDesign name="right" size={20} color={colors.accent} />
          </TouchableOpacity>
        </View>
      </View>

      {/* Preferences Section */}
      <View style={styles.section}>
        <Text style={[styles.sectionHeader, {color: colors.text}]}>Preferences</Text>
        <View style={[styles.card, {backgroundColor: colors.boxes}]}>
          <View style={styles.settingRow}>
            <View style={styles.settingInfo}>
              <Ionicons name="moon-outline" size={24} color={colors.text} />
              <Text style={[styles.settingText, {color: colors.text}]}>Dark Mode</Text>
            </View>
            <Switch
              value={isEnabled}
              onValueChange={flipColorScheme}
              trackColor={{ false: colors.text, true: colors.accent }}
              thumbColor={colors.boxes}
            />
          </View>

          <View style={styles.settingRow}>
            <View style={styles.settingInfo}>
              <Ionicons name="notifications-outline" size={24} color={colors.text} />
              <Text style={[styles.settingText, {color: colors.text}]}>Notifications</Text>
            </View>
            <Switch
              disabled={true}
              value={notificationsEnabled}
              onValueChange={setNotificationsEnabled}
              trackColor={{ false: colors.text, true: colors.accent }}
              thumbColor={colors.boxes}            />
          </View>

          <View style={styles.settingRow}>
            <View style={styles.settingInfo}>
              <AntDesign name="shake" size={24} color={colors.text} />
              <Text style={[styles.settingText, {color: colors.text}]}>Haptic Feedback</Text>
            </View>
            <Switch
              disabled={true}
              value={vibrationEnabled}
              onValueChange={setVibrationEnabled}
              trackColor={{ false: colors.text, true: colors.accent }}
              thumbColor={colors.boxes}            />
          </View>
        </View>
      </View>

      {/* Help & Legal Section */}
      <View style={styles.section}>
        <Text style={[styles.sectionHeader, {color: colors.text}]}>Help & Legal</Text>
        <View style={[styles.card, {backgroundColor: colors.boxes}]}>
          <TouchableOpacity onPress={privacyPolicyModal} style={styles.settingRow}>
            <View style={styles.settingInfo}>
              <MaterialIcons name="privacy-tip" size={24} color={colors.text} />
              <Text style={[styles.settingText, {color: colors.text}]}>Privacy Policy</Text>
            </View>
            <AntDesign name="right" size={20} color={colors.text} />
          </TouchableOpacity>

          <TouchableOpacity onPress={openFeedbackModal} style={styles.settingRow}>
            <View style={styles.settingInfo}>
              <MaterialIcons name="help-outline" size={24} color={colors.text} />
              <Text style={[styles.settingText, {color: colors.text}]}>Help Center</Text>
            </View>
            <AntDesign name="right" size={20} color={colors.text} />
          </TouchableOpacity>

          <TouchableOpacity onPress={openFeedbackModal} style={styles.settingRow}>
            <View style={styles.settingInfo}>
              <MaterialIcons name="feedback" size={24} color={colors.text} />
              <Text style={[styles.settingText, {color: colors.text}]}>Send Feedback</Text>
            </View>
            <AntDesign name="right" size={20} color={colors.text} />
          </TouchableOpacity>
        </View>
      </View>

      <Modal
        animationType="slide"
        transparent={true}
        visible={isPolicyVisible}
        onRequestClose={closePrivacyPolicy}
      >
        <View style={[styles.modalView, { backgroundColor: colors.background }]}>
          <ScrollView style={styles.scrollView} showsVerticalScrollIndicator={false}>
            <Text style={[styles.title, { color: colors.text, textAlign: 'center', marginTop: 50  }]}>Privacy Policy</Text>
            
            <Text style={[styles.sectionTitle, { color: colors.text }]}>1. Data Collection</Text>
            <Text style={[styles.content, { color: colors.text }]}>We collect the following data:
              {'\n'}- Email address for authentication purposes
              {'\n'}- Food tracking data that you input into the app
              {'\n'}- Basic analytics data through Firebase Analytics
            </Text>
            
            <Text style={[styles.sectionTitle, { color: colors.text }]}>2. Data Usage</Text>
            <Text style={[styles.content, { color: colors.text }]}>Your data is used for the following purposes:
              {'\n'}- Email: Used solely for account authentication via Firebase
              {'\n'}- Food tracking data: Used to display your personal metrics and progress
              {'\n'}- Analytics: Used to improve app performance and user experience
            </Text>
            
            <Text style={[styles.sectionTitle, { color: colors.text }]}>3. Data Sharing</Text>
            <Text style={[styles.content, { color: colors.text }]}>We use the following third-party services:
              {'\n'}- Firebase Authentication: For secure user authentication
              {'\n'}- Firebase Analytics: For app performance monitoring
              {'\n\n'}These services are provided by Google and are subject to their respective privacy policies. We do not share your personal data with any other third parties.
            </Text>
            
            <Text style={[styles.sectionTitle, { color: colors.text }]}>4. Data Retention</Text>
            <Text style={[styles.content, { color: colors.text }]}>- Your food tracking data is stored indefinitely to maintain your historical records
              {'\n'}- You can delete your account and all associated data at any time through the settings menu
              {'\n'}- Authentication data is stored securely by Firebase
            </Text>

            <Text style={[styles.sectionTitle, { color: colors.text }]}>5. Your Rights</Text>
            <Text style={[styles.content, { color: colors.text }]}>You have the right to:
              {'\n'}- Access your personal data
              {'\n'}- Delete your account and associated data
              {'\n'}- Withdraw consent at any time
              {'\n\n'}To exercise these rights, use the available options in the Settings menu or contact us.
            </Text>
          </ScrollView>
          
          <Button
            title="Close"
            onPress={closePrivacyPolicy}
            color={colors.accent} 
          />
        </View>
      </Modal>
      
      <Modal
        animationType="slide"
        transparent={true}
        visible={isFeedbackVisible}
        onRequestClose={closeFeedbackModal}
      >
        <View style={[styles.modalView, { backgroundColor: colors.background }]}>
          <Text style={[styles.title, { color: colors.text, textAlign: 'center', marginTop: 50 }]}>Send Feedback</Text>
          <TextInput
            style={[styles.feedbackInput, { 
              color: colors.text,
              backgroundColor: colors.boxes,
              borderColor: colors.text

            }]}
            multiline
            numberOfLines={6}
            placeholder="Type your feedback or questions here..."
            placeholderTextColor={colors.text + '80'}
            value={feedbackText}
            textAlign='center'
            onChangeText={setFeedbackText}
          />
          <View style={styles.modalButtons}>
            <Button title="Cancel" 
            color={colors.accent} 
            onPress={closeFeedbackModal}/>
            <Button title="Send"
            color={colors.accent} 
            onPress={handleSendFeedback} />
          </View>
        </View>
      </Modal>

      {/*
      <View style={styles.section}>
        <Text style={[styles.sectionHeader, {color: colors.text}]}>Payment</Text>
        <View style={[styles.card, {backgroundColor: colors.boxes}]}>
          
          <TouchableOpacity onPress={gotToPayments} style={styles.settingRow}>
            <View style={styles.settingInfo}>
              <MaterialIcons name="close" size={24} color={colors.text} />
              <Text style={[styles.settingText, {color: colors.text}]}>Update or Cancel</Text>
            </View>
            <AntDesign name="right" size={20} color={colors.text} />
          </TouchableOpacity>
          </View>
      </View> */}



    </ScrollView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  contentContainer: {
    paddingBottom: 20,
  },
  banner: {
    height: 120,
    marginTop: -10,
    width: '120%',
    marginHorizontal: '-10%',
    alignItems: 'center',
    marginBottom: 20,
    borderRadius: 20,
    shadowColor: '#000',
    shadowOffset: {
      width: 0,
      height: 2,
    },
    shadowOpacity: 0.1,
    shadowRadius: 8,
    elevation: 5,
  },
  headerText: {
    fontSize: 24,
    fontWeight: 'bold',
    marginTop: 70,
  },
  section: {
    marginBottom: 20,
    paddingHorizontal: 15,
  },
  sectionHeader: {
    fontSize: 16,
    fontWeight: '600',
    marginBottom: 10,
    marginLeft: 5,
    textTransform: 'uppercase',
    opacity: 0.8,
  },
  card: {
    borderRadius: 15,
    overflow: 'hidden',
  },
  settingRow: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    padding: 16,
    borderBottomWidth: 1,
    borderBottomColor: 'rgba(128,128,128,0.2)',
  },
  settingInfo: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 15,
  },
  settingText: {
    fontSize: 16,
  },
  modalView: {
    flex: 1,
    padding: 35,
    shadowColor: 'rgba(0,0,0,0.3)',
    shadowOffset: {
      width: 0,
      height: 2
    },
    shadowOpacity: 0.25,
    shadowRadius: 4,
    elevation: 5
  },
  scrollView: {
    flex: 1,
    marginBottom: 20
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20
  },
  content: {
    fontSize: 16,
    marginBottom: 15,
    lineHeight: 22,
  },
  feedbackInput: {
    borderWidth: 1,
    height: 200,
    borderRadius: 20,
    padding: 10,
    marginVertical: 20,
    textAlignVertical: 'top',
  },
  modalButtons: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    width: '100%',
  },
});