- Expo SDK 54, expo-router, NativeWind - 7 screens: login, tasks, calendar, goals, chat, settings, tabs - API client (api.hasdo.info), SecureStore auth, AuthContext - Tab navigation: Ukoly, Kalendar, Cile, Chat, Nastaveni - Pull-to-refresh, FAB, group colors, priority dots - Calendar grid with task dots - AI chat with keyboard avoiding - Web export verified (780 modules, 1.5MB bundle) - Bundle ID: info.hasdo.taskteam Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
221 lines
6.1 KiB
TypeScript
221 lines
6.1 KiB
TypeScript
import { useState } from 'react';
|
|
import {
|
|
View,
|
|
Text,
|
|
StyleSheet,
|
|
ScrollView,
|
|
TouchableOpacity,
|
|
Switch,
|
|
Alert,
|
|
} from 'react-native';
|
|
import { Ionicons } from '@expo/vector-icons';
|
|
import { useAuthContext } from '../../lib/AuthContext';
|
|
import Constants from 'expo-constants';
|
|
|
|
export default function SettingsScreen() {
|
|
const { user, logout } = useAuthContext();
|
|
const [darkMode, setDarkMode] = useState(false);
|
|
const [notifications, setNotifications] = useState(true);
|
|
const [language, setLanguage] = useState<'cs' | 'en'>('cs');
|
|
|
|
const handleLogout = () => {
|
|
Alert.alert(
|
|
'Odhlaseni',
|
|
'Opravdu se chcete odhlasit?',
|
|
[
|
|
{ text: 'Zrusit', style: 'cancel' },
|
|
{
|
|
text: 'Odhlasit',
|
|
style: 'destructive',
|
|
onPress: logout,
|
|
},
|
|
],
|
|
);
|
|
};
|
|
|
|
const renderSection = (title: string, children: React.ReactNode) => (
|
|
<View style={styles.section}>
|
|
<Text style={styles.sectionTitle}>{title}</Text>
|
|
<View style={styles.sectionContent}>{children}</View>
|
|
</View>
|
|
);
|
|
|
|
const renderRow = (
|
|
icon: string,
|
|
label: string,
|
|
right?: React.ReactNode,
|
|
onPress?: () => void,
|
|
) => (
|
|
<TouchableOpacity
|
|
style={styles.row}
|
|
onPress={onPress}
|
|
disabled={!onPress && !right}
|
|
activeOpacity={onPress ? 0.7 : 1}
|
|
>
|
|
<View style={styles.rowLeft}>
|
|
<Ionicons name={icon as any} size={20} color="#64748B" />
|
|
<Text style={styles.rowLabel}>{label}</Text>
|
|
</View>
|
|
{right || (onPress && <Ionicons name="chevron-forward" size={18} color="#CBD5E1" />)}
|
|
</TouchableOpacity>
|
|
);
|
|
|
|
return (
|
|
<ScrollView style={styles.container}>
|
|
{/* User card */}
|
|
<View style={styles.userCard}>
|
|
<View style={styles.userAvatar}>
|
|
<Text style={styles.userAvatarText}>
|
|
{(user?.name || 'U')[0].toUpperCase()}
|
|
</Text>
|
|
</View>
|
|
<View style={styles.userInfo}>
|
|
<Text style={styles.userName}>{user?.name || 'Uzivatel'}</Text>
|
|
<Text style={styles.userEmail}>{user?.email || ''}</Text>
|
|
</View>
|
|
</View>
|
|
|
|
{renderSection('Predvolby', (
|
|
<>
|
|
{renderRow(
|
|
'moon-outline',
|
|
'Tmavy rezim',
|
|
<Switch
|
|
value={darkMode}
|
|
onValueChange={setDarkMode}
|
|
trackColor={{ false: '#E2E8F0', true: '#3B82F6' }}
|
|
/>,
|
|
)}
|
|
{renderRow(
|
|
'notifications-outline',
|
|
'Oznameni',
|
|
<Switch
|
|
value={notifications}
|
|
onValueChange={setNotifications}
|
|
trackColor={{ false: '#E2E8F0', true: '#3B82F6' }}
|
|
/>,
|
|
)}
|
|
{renderRow(
|
|
'language-outline',
|
|
'Jazyk',
|
|
<TouchableOpacity
|
|
style={styles.langToggle}
|
|
onPress={() => setLanguage(language === 'cs' ? 'en' : 'cs')}
|
|
>
|
|
<Text style={styles.langText}>
|
|
{language === 'cs' ? 'Cestina' : 'English'}
|
|
</Text>
|
|
</TouchableOpacity>,
|
|
)}
|
|
</>
|
|
))}
|
|
|
|
{renderSection('Ucet', (
|
|
<>
|
|
{renderRow('person-outline', 'Upravit profil', undefined, () =>
|
|
Alert.alert('Info', 'Bude k dispozici brzy'),
|
|
)}
|
|
{renderRow('lock-closed-outline', 'Zmenit heslo', undefined, () =>
|
|
Alert.alert('Info', 'Bude k dispozici brzy'),
|
|
)}
|
|
</>
|
|
))}
|
|
|
|
{renderSection('Informace', (
|
|
<>
|
|
{renderRow('information-circle-outline', 'Verze', (
|
|
<Text style={styles.versionText}>
|
|
{Constants.expoConfig?.version || '1.0.0'}
|
|
</Text>
|
|
))}
|
|
{renderRow('document-text-outline', 'Podminky pouziti', undefined, () =>
|
|
Alert.alert('Info', 'Bude k dispozici brzy'),
|
|
)}
|
|
</>
|
|
))}
|
|
|
|
{/* Logout */}
|
|
<TouchableOpacity style={styles.logoutBtn} onPress={handleLogout}>
|
|
<Ionicons name="log-out-outline" size={20} color="#EF4444" />
|
|
<Text style={styles.logoutText}>Odhlasit se</Text>
|
|
</TouchableOpacity>
|
|
|
|
<View style={{ height: 40 }} />
|
|
</ScrollView>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: { flex: 1, backgroundColor: '#F8FAFC' },
|
|
userCard: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
backgroundColor: '#fff',
|
|
padding: 20,
|
|
margin: 12,
|
|
borderRadius: 12,
|
|
shadowColor: '#000',
|
|
shadowOffset: { width: 0, height: 1 },
|
|
shadowOpacity: 0.05,
|
|
shadowRadius: 3,
|
|
elevation: 2,
|
|
},
|
|
userAvatar: {
|
|
width: 56,
|
|
height: 56,
|
|
borderRadius: 28,
|
|
backgroundColor: '#3B82F6',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
},
|
|
userAvatarText: { color: '#fff', fontSize: 22, fontWeight: '700' },
|
|
userInfo: { marginLeft: 16, flex: 1 },
|
|
userName: { fontSize: 18, fontWeight: '600', color: '#1E293B' },
|
|
userEmail: { fontSize: 14, color: '#64748B', marginTop: 2 },
|
|
section: { marginTop: 12, marginHorizontal: 12 },
|
|
sectionTitle: {
|
|
fontSize: 13,
|
|
fontWeight: '600',
|
|
color: '#64748B',
|
|
textTransform: 'uppercase',
|
|
marginBottom: 6,
|
|
marginLeft: 4,
|
|
},
|
|
sectionContent: {
|
|
backgroundColor: '#fff',
|
|
borderRadius: 12,
|
|
overflow: 'hidden',
|
|
},
|
|
row: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
justifyContent: 'space-between',
|
|
paddingHorizontal: 16,
|
|
paddingVertical: 14,
|
|
borderBottomWidth: 1,
|
|
borderBottomColor: '#F1F5F9',
|
|
},
|
|
rowLeft: { flexDirection: 'row', alignItems: 'center', gap: 12 },
|
|
rowLabel: { fontSize: 15, color: '#1E293B' },
|
|
langToggle: {
|
|
backgroundColor: '#F1F5F9',
|
|
paddingHorizontal: 12,
|
|
paddingVertical: 4,
|
|
borderRadius: 8,
|
|
},
|
|
langText: { fontSize: 13, color: '#3B82F6', fontWeight: '600' },
|
|
versionText: { fontSize: 14, color: '#94A3B8' },
|
|
logoutBtn: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
gap: 8,
|
|
marginTop: 24,
|
|
marginHorizontal: 12,
|
|
paddingVertical: 14,
|
|
backgroundColor: '#FEF2F2',
|
|
borderRadius: 12,
|
|
},
|
|
logoutText: { color: '#EF4444', fontSize: 16, fontWeight: '600' },
|
|
});
|