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 (
(
),
}}
/>
(
),
}}
/>
(
),
}}
/>
(
),
}}
/>
(
),
}}
/>
(
),
}}
/>
)
}