122 lines
3.2 KiB
TypeScript
122 lines
3.2 KiB
TypeScript
import React, { useState } from 'react';
|
||
import { View, StyleSheet, KeyboardAvoidingView, Platform, ScrollView } from 'react-native';
|
||
import { TextInput, Button, Text, Headline, HelperText } from 'react-native-paper';
|
||
import { useMutation } from '@apollo/client';
|
||
import { LOGIN } from '../graphql/mutations';
|
||
import { useAuth } from '../contexts/AuthContext';
|
||
|
||
export const LoginScreen = ({ navigation }: any) => {
|
||
const [username, setUsername] = useState('');
|
||
const [password, setPassword] = useState('');
|
||
const [showPassword, setShowPassword] = useState(false);
|
||
const { login } = useAuth();
|
||
|
||
const [loginMutation, { loading, error }] = useMutation(LOGIN, {
|
||
onCompleted: async (data) => {
|
||
await login(data.login.access_token, data.login.user);
|
||
},
|
||
onError: (error) => {
|
||
console.error('Login error:', error);
|
||
},
|
||
});
|
||
|
||
const handleLogin = () => {
|
||
if (!username || !password) return;
|
||
loginMutation({ variables: { username, password } });
|
||
};
|
||
|
||
return (
|
||
<KeyboardAvoidingView
|
||
style={styles.container}
|
||
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||
>
|
||
<ScrollView contentContainerStyle={styles.scrollContent}>
|
||
<View style={styles.content}>
|
||
<Headline style={styles.title}>Вход в Prism</Headline>
|
||
|
||
<TextInput
|
||
label="Имя пользователя"
|
||
value={username}
|
||
onChangeText={setUsername}
|
||
mode="outlined"
|
||
style={styles.input}
|
||
autoCapitalize="none"
|
||
disabled={loading}
|
||
/>
|
||
|
||
<TextInput
|
||
label="Пароль"
|
||
value={password}
|
||
onChangeText={setPassword}
|
||
mode="outlined"
|
||
style={styles.input}
|
||
secureTextEntry={!showPassword}
|
||
disabled={loading}
|
||
right={
|
||
<TextInput.Icon
|
||
icon={showPassword ? 'eye-off' : 'eye'}
|
||
onPress={() => setShowPassword(!showPassword)}
|
||
/>
|
||
}
|
||
/>
|
||
|
||
{error && (
|
||
<HelperText type="error" visible={true}>
|
||
{error.message}
|
||
</HelperText>
|
||
)}
|
||
|
||
<Button
|
||
mode="contained"
|
||
onPress={handleLogin}
|
||
loading={loading}
|
||
disabled={loading || !username || !password}
|
||
style={styles.button}
|
||
>
|
||
Войти
|
||
</Button>
|
||
|
||
<Button
|
||
mode="text"
|
||
onPress={() => navigation.navigate('Register')}
|
||
disabled={loading}
|
||
style={styles.linkButton}
|
||
>
|
||
Нет аккаунта? Зарегистрироваться
|
||
</Button>
|
||
</View>
|
||
</ScrollView>
|
||
</KeyboardAvoidingView>
|
||
);
|
||
};
|
||
|
||
const styles = StyleSheet.create({
|
||
container: {
|
||
flex: 1,
|
||
backgroundColor: '#f5f5f5',
|
||
},
|
||
scrollContent: {
|
||
flexGrow: 1,
|
||
justifyContent: 'center',
|
||
},
|
||
content: {
|
||
padding: 20,
|
||
maxWidth: 400,
|
||
width: '100%',
|
||
alignSelf: 'center',
|
||
},
|
||
title: {
|
||
textAlign: 'center',
|
||
marginBottom: 30,
|
||
},
|
||
input: {
|
||
marginBottom: 15,
|
||
},
|
||
button: {
|
||
marginTop: 10,
|
||
marginBottom: 10,
|
||
},
|
||
linkButton: {
|
||
marginTop: 10,
|
||
},
|
||
}); |