import React, { useState } from 'react'; import { View, StyleSheet, KeyboardAvoidingView, Platform, Alert, } from 'react-native'; import { Card, Title, Paragraph, TextInput, Button, HelperText, } from 'react-native-paper'; import { SafeAreaView } from 'react-native-safe-area-context'; import { useServerConfig } from '../services/ServerConfigContext'; import { updateAPIBaseURL } from '../services/api'; interface ServerConfig { baseUrl: string; username: string; password: string; } const ServerSetupScreen: React.FC = () => { const [config, setConfig] = useState({ baseUrl: '', username: '', password: '', }); const [isLoading, setIsLoading] = useState(false); const [errors, setErrors] = useState>({}); const { setConfig: saveConfig } = useServerConfig(); const validateConfig = (): boolean => { const newErrors: Partial = {}; if (!config.baseUrl.trim()) { newErrors.baseUrl = 'Server URL is required'; } else if (!isValidUrl(config.baseUrl)) { newErrors.baseUrl = 'Please enter a valid URL (e.g., https://your-server.com)'; } if (!config.username.trim()) { newErrors.username = 'Username is required'; } if (!config.password.trim()) { newErrors.password = 'Password is required'; } setErrors(newErrors); return Object.keys(newErrors).length === 0; }; const isValidUrl = (url: string): boolean => { try { const urlObj = new URL(url.startsWith('http') ? url : `https://${url}`); return urlObj.protocol === 'http:' || urlObj.protocol === 'https:'; } catch { return false; } }; const testConnection = async (): Promise => { try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 10000); const response = await fetch(`${config.baseUrl}/api/health`, { method: 'GET', headers: { 'Content-Type': 'application/json', }, signal: controller.signal, }); clearTimeout(timeoutId); return response.ok; } catch (error) { console.error('Connection test failed:', error); return false; } }; const handleTestConnection = async () => { if (!config.baseUrl.trim()) { Alert.alert('Error', 'Please enter a server URL first'); return; } setIsLoading(true); try { const isConnected = await testConnection(); if (isConnected) { Alert.alert('Success', 'Connection to server successful!'); } else { Alert.alert( 'Connection Failed', 'Could not connect to the server. Please check the URL and ensure the server is running.' ); } } catch (error) { Alert.alert('Error', 'Failed to test connection. Please try again.'); } finally { setIsLoading(false); } }; const handleSetup = async () => { if (!validateConfig()) { return; } setIsLoading(true); try { const isConnected = await testConnection(); if (!isConnected) { Alert.alert( 'Connection Failed', 'Could not connect to the server. Please check the URL and try again.' ); return; } // Test authentication const authResponse = await fetch(`${config.baseUrl}/api/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ username: config.username, password: config.password, }), }); if (authResponse.ok) { const authData = await authResponse.json(); if (authData.token) { await saveConfig(config); updateAPIBaseURL(`${config.baseUrl}/api`); Alert.alert('Success', 'Server configuration completed successfully!'); // Navigation will be handled automatically by the AppNavigator } else { Alert.alert('Authentication Failed', 'Invalid username or password.'); } } else { Alert.alert('Authentication Failed', 'Invalid username or password.'); } } catch (error) { Alert.alert('Setup Failed', 'An error occurred during setup. Please try again.'); } finally { setIsLoading(false); } }; return ( Welcome to Trackeep Connect to your Trackeep server to get started Server Configuration setConfig({ ...config, baseUrl: text })} placeholder="https://your-server.com" autoCapitalize="none" keyboardType="url" style={styles.input} error={!!errors.baseUrl} /> {errors.baseUrl} setConfig({ ...config, username: text })} autoCapitalize="none" autoCorrect={false} style={styles.input} error={!!errors.username} /> {errors.username} setConfig({ ...config, password: text })} secureTextEntry autoCapitalize="none" autoCorrect={false} style={styles.input} error={!!errors.password} /> {errors.password} Need Help? • Enter the full URL of your Trackeep server • Use your existing Trackeep account credentials • Make sure your server is accessible from this device ); }; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#f5f5f5', }, keyboardAvoidingView: { flex: 1, }, content: { flex: 1, padding: 16, justifyContent: 'center', }, card: { marginBottom: 16, elevation: 2, }, infoCard: { marginBottom: 24, backgroundColor: '#e3f2fd', }, title: { textAlign: 'center', fontSize: 24, fontWeight: 'bold', color: '#6200ee', }, subtitle: { textAlign: 'center', marginTop: 8, color: '#666', }, cardTitle: { fontSize: 18, marginBottom: 16, color: '#333', }, input: { marginBottom: 8, }, testButton: { marginTop: 8, }, infoText: { fontSize: 14, color: '#666', marginBottom: 4, }, setupButton: { backgroundColor: '#6200ee', }, setupButtonContent: { paddingVertical: 8, }, }); export default ServerSetupScreen;