import { Tabs, Redirect } from 'expo-router' import { Platform, View, Text, StyleSheet, TextInput, TouchableOpacity, ActivityIndicator, Alert, ScrollView } from 'react-native' import { useEffect, useState } from 'react' import { Ionicons } from '@expo/vector-icons' import { SafeAreaView } from 'react-native-safe-area-context' import { useAuthStore } from '@/store/auth.store' import { trpc } from '@/lib/trpc' import { setupPushNotifications } from '@/lib/notifications' import { authClient } from '@/lib/auth-client' function UnreadBadge({ count }: { count: number }) { if (count === 0) return null return ( {count > 9 ? '9+' : count} ) } const badge = StyleSheet.create({ dot: { position: 'absolute', top: -4, right: -8, minWidth: 17, height: 17, borderRadius: 9, backgroundColor: '#DC2626', justifyContent: 'center', alignItems: 'center', paddingHorizontal: 4, borderWidth: 2, borderColor: '#FFFFFF', }, text: { fontSize: 10, fontWeight: '700', color: '#FFFFFF', lineHeight: 13, }, }) function ChatTabIcon({ color, focused }: { color: string; focused: boolean }) { const { data: unreadCount } = trpc.messages.getConversations.useQuery(undefined, { refetchInterval: 15_000, staleTime: 10_000, select: (data) => data.filter((c) => c.hasUnread).length, }) return ( ) } function ForcePasswordChangeScreen() { const { setSession, signOut } = useAuthStore() const [next, setNext] = useState('') const [confirm, setConfirm] = useState('') const [loading, setLoading] = useState(false) const [error, setError] = useState('') async function handleSubmit() { setError('') if (next.length < 8) { setError('Das neue Passwort muss mindestens 8 Zeichen haben.'); return } if (next !== confirm) { setError('Die Passwörter stimmen nicht überein.'); return } setLoading(true) // Set password directly via tRPC (no old password needed — user is already authenticated) try { const apiUrl = process.env.EXPO_PUBLIC_API_URL ?? 'http://localhost:3032' const sessionResult = await authClient.getSession() const token = (sessionResult?.data as any)?.session?.token const res = await fetch(`${apiUrl}/api/auth/force-set-password`, { method: 'POST', headers: { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}), }, credentials: 'include', body: JSON.stringify({ newPassword: next }), }) const data = await res.json() if (!res.ok || data.error) { setError(data.error ?? 'Passwort konnte nicht geändert werden.') setLoading(false) return } // Update local session state if (sessionResult?.data?.user) { const u = sessionResult.data.user as any await setSession({ user: { id: u.id, email: u.email, name: u.name, mustChangePassword: false } }) } } catch (e) { setError('Verbindungsfehler. Bitte erneut versuchen.') } setLoading(false) } return ( Passwort festlegen Bitte legen Sie jetzt Ihr persönliches Passwort fest. Neues Passwort Neues Passwort wiederholen {!!error && ( {error} )} {loading ? : Passwort festlegen } void signOut()}> Abmelden ) } const fpc = StyleSheet.create({ safe: { flex: 1, backgroundColor: '#F8FAFC' }, content: { flexGrow: 1, justifyContent: 'center', padding: 24, paddingBottom: 40 }, card: { backgroundColor: '#FFFFFF', borderRadius: 20, borderWidth: 1, borderColor: '#E2E8F0', padding: 24, gap: 12, }, iconWrap: { width: 60, height: 60, borderRadius: 16, backgroundColor: '#EFF6FF', alignItems: 'center', justifyContent: 'center', alignSelf: 'center', marginBottom: 4, }, title: { fontSize: 22, fontWeight: '800', color: '#0F172A', textAlign: 'center' }, subtitle: { fontSize: 13, color: '#64748B', textAlign: 'center', lineHeight: 19 }, field: { gap: 4 }, label: { fontSize: 12, fontWeight: '700', color: '#475569', textTransform: 'uppercase', letterSpacing: 0.5 }, input: { borderWidth: 1, borderColor: '#E2E8F0', borderRadius: 10, paddingHorizontal: 12, paddingVertical: 11, fontSize: 14, color: '#0F172A', backgroundColor: '#F8FAFC', }, errorBox: { backgroundColor: '#FEF2F2', borderWidth: 1, borderColor: '#FECACA', borderRadius: 10, paddingHorizontal: 12, paddingVertical: 10, }, errorText: { color: '#B91C1C', fontSize: 13 }, btn: { backgroundColor: '#003B7E', borderRadius: 12, paddingVertical: 13, alignItems: 'center', marginTop: 4, }, btnText: { color: '#FFFFFF', fontWeight: '700', fontSize: 15 }, logoutBtn: { alignItems: 'center', paddingVertical: 8 }, logoutText: { color: '#94A3B8', fontSize: 13 }, }) export default function AppLayout() { const session = useAuthStore((s) => s.session) useEffect(() => { if (!session?.user) return setupPushNotifications().catch(() => {}) }, [session?.user?.id]) if (!session) { return } if (session.user.mustChangePassword) { return } return ( ( ), }} /> ( ), }} /> ( ), }} /> ( ), }} /> ( ), }} /> ( ), }} /> ) }