aboutsummaryrefslogtreecommitdiffstats
path: root/apps/mobile/app/signin.tsx
blob: 07ab8e08a8937c4693d0478c115f7a51a988e78c (plain) (blame)
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
102
103
104
105
106
107
108
109
110
111
112
113
import { useEffect, useState } from "react";
import {
  Keyboard,
  KeyboardAvoidingView,
  Platform,
  Text,
  TouchableWithoutFeedback,
  View,
} from "react-native";
import { useRouter } from "expo-router";
import Logo from "@/components/Logo";
import { Button } from "@/components/ui/Button";
import { Input } from "@/components/ui/Input";
import useAppSettings from "@/lib/settings";
import { api } from "@/lib/trpc";

export default function Signin() {
  const router = useRouter();

  const { settings, setSettings } = useAppSettings();

  const [error, setError] = useState<string | undefined>();

  const { mutate: login, isPending } = api.apiKeys.exchange.useMutation({
    onSuccess: (resp) => {
      setSettings({ ...settings, apiKey: resp.key });
      router.replace("dashboard");
    },
    onError: (e) => {
      if (e.data?.code === "UNAUTHORIZED") {
        setError("Wrong username or password");
      } else {
        setError(`${e.message}`);
      }
    },
  });

  const [formData, setFormData] = useState<{
    email: string;
    password: string;
  }>({
    email: "",
    password: "",
  });

  useEffect(() => {
    if (settings.apiKey) {
      router.navigate("dashboard");
    }
  }, [settings]);

  const onSignin = () => {
    const randStr = (Math.random() + 1).toString(36).substring(5);
    login({ ...formData, keyName: `Mobile App: (${randStr})` });
  };

  return (
    <KeyboardAvoidingView
      behavior={Platform.OS === "ios" ? "padding" : "height"}
    >
      <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
        <View className="flex h-full flex-col justify-center gap-2 px-4">
          <View className="items-center">
            <Logo />
          </View>
          {error && (
            <Text className="w-full text-center text-red-500">{error}</Text>
          )}
          <View className="gap-2">
            <Text className="font-bold">Server Address</Text>
            <Input
              className="w-full"
              placeholder="Server Address"
              value={settings.address}
              autoCapitalize="none"
              keyboardType="url"
              onChangeText={(e) =>
                setSettings({ ...settings, address: e })
              }
            />
          </View>
          <View className="gap-2">
            <Text className="font-bold">Email</Text>
            <Input
              className="w-full"
              placeholder="Email"
              keyboardType="email-address"
              autoCapitalize="none"
              value={formData.email}
              onChangeText={(e) => setFormData((s) => ({ ...s, email: e }))}
            />
          </View>
          <View className="gap-2">
            <Text className="font-bold">Password</Text>
            <Input
              className="w-full"
              placeholder="Password"
              secureTextEntry
              value={formData.password}
              onChangeText={(e) => setFormData((s) => ({ ...s, password: e }))}
            />
          </View>
          <Button
            className="w-full"
            label="Sign In"
            onPress={onSignin}
            disabled={isPending}
          />
        </View>
      </TouchableWithoutFeedback>
    </KeyboardAvoidingView>
  );
}