143 lines
4.1 KiB
TypeScript
143 lines
4.1 KiB
TypeScript
import React, { useMemo, useState } from 'react';
|
|
import { ActivityIndicator, Pressable, StyleSheet, Text, TextInput, View } from 'react-native';
|
|
import type { ReactNode } from 'react';
|
|
import { LinearGradient } from 'expo-linear-gradient';
|
|
import { Colors, Fonts, FontSize, BorderRadius, Spacing } from '@/constants/theme';
|
|
import { useMobileAuth } from '@/providers/MobileAuthProvider';
|
|
|
|
export function AuthGate({ children }: { children: ReactNode }) {
|
|
const { user, loading, signIn, error } = useMobileAuth();
|
|
const [email, setEmail] = useState('');
|
|
const [password, setPassword] = useState('');
|
|
const [submitting, setSubmitting] = useState(false);
|
|
const errorMessage = useMemo(() => error, [error]);
|
|
|
|
if (loading) {
|
|
return (
|
|
<View style={styles.centered}>
|
|
<ActivityIndicator size="large" color={Colors.accent.green} />
|
|
<Text style={styles.loadingText}>Restoring trading session...</Text>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
if (user) {
|
|
return <>{children}</>;
|
|
}
|
|
|
|
return (
|
|
<View style={styles.screen}>
|
|
<LinearGradient colors={['#14151f', '#0f1017']} style={styles.card}>
|
|
<Text style={styles.eyebrow}>BYTElyst TRADING</Text>
|
|
<Text style={styles.title}>Sign in to your trading workspace</Text>
|
|
<Text style={styles.subtitle}>
|
|
Mobile now authenticates against the shared platform-service identity boundary used across the ecosystem.
|
|
</Text>
|
|
<TextInput
|
|
value={email}
|
|
onChangeText={setEmail}
|
|
style={styles.input}
|
|
placeholder="Email"
|
|
placeholderTextColor={Colors.text.ultraDim}
|
|
autoCapitalize="none"
|
|
keyboardType="email-address"
|
|
/>
|
|
<TextInput
|
|
value={password}
|
|
onChangeText={setPassword}
|
|
style={styles.input}
|
|
placeholder="Password"
|
|
placeholderTextColor={Colors.text.ultraDim}
|
|
autoCapitalize="none"
|
|
secureTextEntry
|
|
/>
|
|
{errorMessage ? <Text style={styles.error}>{errorMessage}</Text> : null}
|
|
<Pressable
|
|
style={styles.button}
|
|
disabled={submitting}
|
|
onPress={async () => {
|
|
setSubmitting(true);
|
|
await signIn(email.trim(), password);
|
|
setSubmitting(false);
|
|
}}
|
|
>
|
|
<Text style={styles.buttonText}>{submitting ? 'Signing in...' : 'Sign In'}</Text>
|
|
</Pressable>
|
|
</LinearGradient>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
screen: {
|
|
flex: 1,
|
|
backgroundColor: Colors.background.primary,
|
|
justifyContent: 'center',
|
|
padding: Spacing.screenPadding,
|
|
},
|
|
centered: {
|
|
flex: 1,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
backgroundColor: Colors.background.primary,
|
|
gap: 12,
|
|
},
|
|
loadingText: {
|
|
fontFamily: Fonts.inter.medium,
|
|
fontSize: FontSize.body,
|
|
color: Colors.text.secondary,
|
|
},
|
|
card: {
|
|
borderRadius: BorderRadius.large,
|
|
borderWidth: 1,
|
|
borderColor: Colors.border.default,
|
|
padding: Spacing.cardPaddingLarge,
|
|
gap: 14,
|
|
},
|
|
eyebrow: {
|
|
fontFamily: Fonts.inter.black,
|
|
fontSize: FontSize.micro,
|
|
color: Colors.accent.green,
|
|
letterSpacing: 3,
|
|
},
|
|
title: {
|
|
fontFamily: Fonts.inter.black,
|
|
fontSize: FontSize.heading,
|
|
color: Colors.text.primary,
|
|
},
|
|
subtitle: {
|
|
fontFamily: Fonts.inter.medium,
|
|
fontSize: FontSize.body,
|
|
color: Colors.text.secondary,
|
|
lineHeight: 21,
|
|
},
|
|
input: {
|
|
borderWidth: 1,
|
|
borderColor: Colors.border.default,
|
|
borderRadius: BorderRadius.medium,
|
|
backgroundColor: Colors.background.card,
|
|
color: Colors.text.primary,
|
|
paddingHorizontal: 14,
|
|
paddingVertical: 12,
|
|
fontFamily: Fonts.inter.medium,
|
|
fontSize: FontSize.body,
|
|
},
|
|
button: {
|
|
marginTop: 6,
|
|
borderRadius: BorderRadius.medium,
|
|
backgroundColor: Colors.accent.green,
|
|
paddingVertical: 14,
|
|
alignItems: 'center',
|
|
},
|
|
buttonText: {
|
|
fontFamily: Fonts.inter.black,
|
|
fontSize: FontSize.body,
|
|
color: '#04120b',
|
|
},
|
|
error: {
|
|
fontFamily: Fonts.inter.medium,
|
|
fontSize: FontSize.bodySmall,
|
|
color: Colors.accent.red,
|
|
},
|
|
});
|