import React, { useState } from 'react'; import { StyleSheet, View, Text, ScrollView, TouchableOpacity, Alert, ActivityIndicator, Switch, TextInput, } from 'react-native'; import { useTheme } from '../services/ThemeContext'; import DatabaseService from '../services/DatabaseService'; import GoogleAUTH from '../AUTH/GoogleAUTH'; import NASAUTH from '../AUTH/NASAUTH'; import NASSetupInstructions from '../components/NASSetupInstructions'; import ServiceHealthIndicator from '../components/ServiceHealthIndicator'; const OnboardingScreen = ({ navigation, route }) => { const { userId } = route.params; const { theme } = useTheme(); const [currentStep, setCurrentStep] = useState(0); const [loading, setLoading] = useState(false); // Step 0 — service toggles const [googleEnabled, setGoogleEnabled] = useState(false); const [iosEnabled, setIosEnabled] = useState(false); const [nasEnabled, setNasEnabled] = useState(false); // Step 1 — connection status const [googleConnected, setGoogleConnected] = useState(false); const [iosConnected, setIosConnected] = useState(false); const [nasConnected, setNasConnected] = useState(false); // Step 1 — health indicators const [googleHealth, setGoogleHealth] = useState('inactive'); const [iosHealth, setIosHealth] = useState('inactive'); const [nasHealth, setNasHealth] = useState('inactive'); // NAS fields const [nasHost, setNasHost] = useState(''); const [nasPort, setNasPort] = useState('9500'); const [nasUsername, setNasUsername] = useState(''); // Step 2 — auto-backup checklist const [autoBackupServices, setAutoBackupServices] = useState([]); const steps = [ { title: 'Choose Services', description: 'Select which photo services to connect (1-3)' }, { title: 'Connect Services', description: 'Set up each selected service' }, { title: 'Automatic Backup', description: 'Choose where new photos are backed up' }, ]; const getConnectedServices = () => { const services = []; if (googleEnabled && googleConnected) services.push({ name: 'Google Photos', type: 'GOOGLE_PHOTOS', icon: '📷' }); if (iosEnabled && iosConnected) services.push({ name: 'iCloud Photos', type: 'ICLOUD_PHOTOS', icon: '🍎' }); if (nasEnabled && nasConnected) services.push({ name: 'NAS Storage', type: 'NAS', icon: '💾' }); return services; }; const handleGoogleAuth = async () => { setLoading(true); setGoogleHealth('checking'); try { const googleAuth = new GoogleAUTH(); const result = await googleAuth.authenticate(); await DatabaseService.linkAccount(userId, 'GOOGLE_PHOTOS', { accessToken: result.accessToken, refreshToken: result.refreshToken || null, expiresAt: googleAuth.expiresAt || Date.now() + 3600000, email: result.email || 'google-user', }); setGoogleConnected(true); setGoogleHealth('healthy'); Alert.alert('Success', 'Google Photos connected!'); } catch (error) { setGoogleHealth('error'); Alert.alert('Error', 'Failed to connect Google Photos: ' + error.message); } finally { setLoading(false); } }; const handleIosAuth = async () => { setLoading(true); setIosHealth('checking'); try { await DatabaseService.linkAccount(userId, 'ICLOUD_PHOTOS', { status: 'placeholder', note: 'iCloud integration pending Apple API access', }); setIosConnected(true); setIosHealth('healthy'); Alert.alert('Info', 'iCloud Photos registered. Full integration coming soon.'); } catch (error) { setIosHealth('error'); Alert.alert('Error', 'Failed to set up iCloud: ' + error.message); } finally { setLoading(false); } }; const handleNasAuth = async () => { if (!nasHost.trim() || !nasUsername.trim()) { Alert.alert('Error', 'Please fill in the NAS host and username'); return; } setLoading(true); setNasHealth('checking'); try { const nasAuth = new NASAUTH(); await nasAuth.authenticate(nasHost.trim(), parseInt(nasPort) || 9500, nasUsername.trim()); await DatabaseService.linkAccount(userId, 'NAS', { host: nasHost.trim(), port: parseInt(nasPort) || 9500, username: nasUsername.trim(), }); setNasConnected(true); setNasHealth('healthy'); Alert.alert('Success', 'NAS connected!'); } catch (error) { setNasHealth('error'); Alert.alert('Error', 'Failed to connect NAS: ' + error.message); } finally { setLoading(false); } }; const toggleAutoBackup = (serviceType) => { setAutoBackupServices((prev) => prev.includes(serviceType) ? prev.filter((s) => s !== serviceType) : [...prev, serviceType] ); }; const handleNext = async () => { if (currentStep === 0) { if (!googleEnabled && !iosEnabled && !nasEnabled) { Alert.alert('Error', 'Please select at least one service'); return; } setCurrentStep(1); } else if (currentStep === 1) { const anyConnected = (googleEnabled && googleConnected) || (iosEnabled && iosConnected) || (nasEnabled && nasConnected); if (!anyConnected) { Alert.alert('Error', 'Please connect at least one service'); return; } setCurrentStep(2); } else if (currentStep === 2) { try { setLoading(true); await DatabaseService.setAutoBackupServices(userId, autoBackupServices); navigation.replace('MainTabs', { userId }); } catch (error) { Alert.alert('Error', 'Failed to complete setup: ' + error.message); } finally { setLoading(false); } } }; return ( {/* Progress bar */} {steps.map((_, i) => ( ))} Step {currentStep + 1} of {steps.length} {steps[currentStep].title} {steps[currentStep].description} {/* ── Step 0: pick services ── */} {currentStep === 0 && ( setGoogleEnabled(!googleEnabled)} /> setIosEnabled(!iosEnabled)} /> setNasEnabled(!nasEnabled)} /> {nasEnabled && } )} {/* ── Step 1: connect each service ── */} {currentStep === 1 && ( {googleEnabled && ( 📷 Google Photos {googleConnected && ✓ Connected} {!googleConnected && ( {loading ? : Sign in with Google} )} )} {iosEnabled && ( 🍎 iCloud Photos {iosConnected && ✓ Connected} {!iosConnected && ( {loading ? : Connect iCloud} )} )} {nasEnabled && ( 💾 NAS Storage {nasConnected && ✓ Connected} {!nasConnected && ( <> Server Address Port Username {loading ? : Test & Connect} )} )} )} {/* ── Step 2: auto-backup ── */} {currentStep === 2 && ( Select which services new photos should automatically upload to. You can select multiple or none. {getConnectedServices().map((svc) => ( toggleAutoBackup(svc.type)} activeOpacity={0.7} > {autoBackupServices.includes(svc.type) && ✓} {svc.icon} {svc.name} ))} setAutoBackupServices([])} activeOpacity={0.7}> {autoBackupServices.length === 0 && ✓} Don't automatically back up )} {/* Footer */} {currentStep > 0 ? ( setCurrentStep(currentStep - 1)} disabled={loading}> Back ) : } {loading ? : ( {currentStep === steps.length - 1 ? 'Get Started' : 'Next'} )} ); }; const ServiceToggleCard = ({ theme, icon, name, description, enabled, onToggle }) => ( {icon} {name} {description} ); const styles = StyleSheet.create({ container: { flex: 1 }, progressBar: { flexDirection: 'row', justifyContent: 'center', gap: 8, paddingTop: 60, paddingBottom: 8 }, progressDot: { width: 32, height: 4, borderRadius: 2 }, content: { flex: 1, paddingHorizontal: 20 }, header: { marginBottom: 24 }, stepLabel: { fontSize: 12, fontWeight: '600', marginBottom: 6 }, title: { fontSize: 26, fontWeight: '700', marginBottom: 6 }, description: { fontSize: 14 }, cardsContainer: { gap: 12 }, toggleCard: { borderRadius: 12, padding: 16, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', borderWidth: 1.5 }, toggleCardContent: { flex: 1, flexDirection: 'row', alignItems: 'center' }, toggleIcon: { fontSize: 28, marginRight: 14 }, toggleInfo: { flex: 1 }, toggleName: { fontSize: 15, fontWeight: '600', marginBottom: 2 }, toggleDescription: { fontSize: 12 }, configCard: { borderRadius: 12, padding: 16, borderWidth: 1 }, configHeader: { flexDirection: 'row', alignItems: 'center', marginBottom: 12 }, configIcon: { fontSize: 24, marginRight: 10 }, configTitle: { fontSize: 16, fontWeight: '600', flex: 1 }, connectedBadge: { fontSize: 13, fontWeight: '600' }, authButton: { borderRadius: 8, paddingVertical: 12, alignItems: 'center', marginTop: 4 }, authButtonText: { color: '#fff', fontSize: 14, fontWeight: '600' }, fieldLabel: { fontSize: 12, fontWeight: '600', marginTop: 10, marginBottom: 4 }, fieldInput: { borderWidth: 1, borderRadius: 8, paddingHorizontal: 12, paddingVertical: 10, fontSize: 14 }, checklistInfo: { fontSize: 13, marginBottom: 8 }, checkRow: { flexDirection: 'row', alignItems: 'center', paddingVertical: 14, borderBottomWidth: StyleSheet.hairlineWidth }, checkbox: { width: 22, height: 22, borderRadius: 4, borderWidth: 2, justifyContent: 'center', alignItems: 'center', marginRight: 12 }, checkmark: { color: '#fff', fontSize: 14, fontWeight: '700' }, checkIcon: { fontSize: 18, marginRight: 8 }, checkLabel: { fontSize: 14, fontWeight: '500', flex: 1 }, footer: { flexDirection: 'row', paddingHorizontal: 20, paddingVertical: 14, borderTopWidth: 1, gap: 12 }, backButton: { flex: 1, paddingVertical: 12, borderRadius: 8, alignItems: 'center', borderWidth: 1 }, backButtonText: { fontSize: 15, fontWeight: '600' }, nextButton: { flex: 1, paddingVertical: 12, borderRadius: 8, alignItems: 'center' }, nextButtonText: { fontSize: 15, fontWeight: '600', color: '#fff' }, buttonDisabled: { opacity: 0.6 }, }); export default OnboardingScreen;