All files / app/login/screens LoginScreen.tsx

100% Statements 3/3
100% Branches 0/0
100% Functions 1/1
100% Lines 3/3

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101                          8x                   8x   8x                                                                                                                                                      
/**
 * 登录页面
 */
import { View, TouchableOpacity } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { Text, YStack } from 'tamagui';
import { LottieAnimation } from '@/src/components/LottieAnimation';
import { Button, Input } from '@/src/design-system';
import { infoScale, neutralScale } from '@/src/design-system/tokens';
 
import { useLoginForm } from '../hooks';
 
export function LoginScreen() {
  const insets = useSafeAreaInsets();
  const {
    email,
    password,
    errors,
    isLoading,
    handleEmailChange,
    handlePasswordChange,
    handleLogin,
    navigateToRegister,
  } = useLoginForm();
 
  return (
    <View testID="login-screen" style={{ flex: 1 }}>
      <YStack
        flex={1}
        justifyContent="center"
        alignItems="center"
        paddingHorizontal="$8"
        paddingTop={insets.top + 16}
        paddingBottom={insets.bottom + 80}
        backgroundColor="$background"
      >
        <LottieAnimation
          source={require('@/assets/animations/cat_playing.json')}
          width={300}
          height={200}
        />
 
        <Text fontSize="$9" fontWeight="bold" marginBottom="$3" textAlign="center">
          欢迎来到Pet Love!
        </Text>
        <Text fontSize="$5" color={neutralScale.neutral9} marginBottom="$6" textAlign="center">
          为你的小猫量身定做的健康app
        </Text>
 
        <YStack width="100%" maxWidth={400} gap="$3">
          <Input
            size="lg"
            placeholder="邮箱地址"
            value={email}
            onChangeText={handleEmailChange}
            autoCapitalize="none"
            keyboardType="email-address"
            autoComplete="email"
            disabled={isLoading}
            error={!!errors.email}
            errorMessage={errors.email}
            testID="login-email-input"
          />
 
          <Input
            size="lg"
            placeholder="密码"
            value={password}
            onChangeText={handlePasswordChange}
            secureTextEntry
            disabled={isLoading}
            error={!!errors.password}
            errorMessage={errors.password}
            testID="login-password-input"
          />
 
          <Button
            size="lg"
            variant="primary"
            onPress={handleLogin}
            loading={isLoading}
            fullWidth
            marginTop="$2"
            testID="login-button"
          >
            登录
          </Button>
 
          <YStack alignItems="center" marginTop="$2">
            <TouchableOpacity onPress={navigateToRegister} testID="register-link">
              <Text color={infoScale.info9} fontSize="$4" pressStyle={{ opacity: 0.7 }}>
                还没有账号?立即注册
              </Text>
            </TouchableOpacity>
          </YStack>
        </YStack>
      </YStack>
    </View>
  );
}