import { useState } from 'react'; import type { ReactElement } from 'react'; import { ActivityIndicator, KeyboardAvoidingView, Platform, Pressable, StyleSheet, Text, TextInput, View, } from 'react-native'; import { ApiError } from '@altricade/core/api'; import { useSession } from '@/stores/session'; import { Screen } from '@/components'; import { useTheme } from '@/theme'; import { spacing, radius, fontSize } from '@/theme'; type Mode = 'login' | 'register'; export const SignInScreen = (): ReactElement => { const { colors } = useTheme(); const login = useSession((s) => s.login); const register = useSession((s) => s.register); const [mode, setMode] = useState('login'); const [username, setUsername] = useState(''); const [displayName, setDisplayName] = useState(''); const [password, setPassword] = useState(''); const [error, setError] = useState(null); const [busy, setBusy] = useState(false); const submit = (): void => { setBusy(true); setError(null); void (async () => { try { if (mode === 'login') { await login({ username: username.trim(), password }); } else { await register({ username: username.trim(), displayName: displayName.trim(), password }); } } catch (caught) { setError(caught instanceof ApiError ? caught.message : 'Something went wrong'); setBusy(false); } })(); }; const inputStyle = [styles.input, { backgroundColor: colors.surface, color: colors.text }]; return ( Z Zovi {mode === 'login' ? 'Welcome back.' : 'Create your account.'} {mode === 'register' ? ( ) : null} {error !== null ? {error} : null} {busy ? ( ) : ( {mode === 'login' ? 'Log in' : 'Create account'} )} { setMode(mode === 'login' ? 'register' : 'login'); setError(null); }} > {mode === 'login' ? 'Need an account? Sign up' : 'Have an account? Log in'} ); }; const styles = StyleSheet.create({ flex: { flex: 1 }, center: { flex: 1, justifyContent: 'center', paddingHorizontal: spacing.xl }, mark: { width: 56, height: 56, borderRadius: 18, alignItems: 'center', justifyContent: 'center', alignSelf: 'center', marginBottom: spacing.md, }, markText: { fontSize: 28, fontWeight: '800' }, title: { fontSize: 28, fontWeight: '700', textAlign: 'center' }, tagline: { textAlign: 'center', marginTop: spacing.xs, marginBottom: spacing.xl }, input: { borderRadius: radius.md, paddingHorizontal: spacing.lg, paddingVertical: spacing.md, fontSize: fontSize.base, marginBottom: spacing.md, }, error: { fontSize: fontSize.sm, marginBottom: spacing.sm }, primary: { borderRadius: radius.md, paddingVertical: spacing.md, alignItems: 'center', marginTop: spacing.xs, }, primaryText: { fontSize: fontSize.md, fontWeight: '600' }, switch: { textAlign: 'center', marginTop: spacing.xl, fontWeight: '600' }, });