ICS React Native App
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 88 lines 2.0 kB view raw
1import { useState, useEffect, useCallback } from "react"; 2import { useMutation } from "@tanstack/react-query"; 3import { LoginRequest, LoginError, postLogin } from "@/generated"; 4import { z } from "zod"; 5import { useToken } from "@/providers/token-provider"; 6import { useRouter } from "expo-router"; 7 8const FieldErrorSchema = z.object({ 9 errors: z.array(z.string()), 10}); 11 12const LoginErrorSchema = z.object({ 13 errors: z.array(z.string()), 14 properties: z 15 .object({ 16 username: FieldErrorSchema.optional(), 17 password: FieldErrorSchema.optional(), 18 }) 19 .optional(), 20}); 21 22const isLoginError = (e: unknown): e is LoginError => { 23 const { success } = LoginErrorSchema.safeParse(e); 24 return success; 25}; 26 27const fromError = (error: unknown): LoginError => ({ 28 errors: [error instanceof Error ? error.message : "unknown error"], 29 properties: {}, 30}); 31 32export const useLogin = () => { 33 const { setToken, token } = useToken(); 34 const router = useRouter(); 35 const [error, setError] = useState<null | LoginError>(null); 36 37 const { 38 isPending, 39 mutateAsync, 40 error: mutationError, 41 data, 42 } = useMutation({ 43 mutationFn: (body: LoginRequest) => { 44 setError(null); 45 46 return postLogin({ body }); 47 }, 48 }); 49 50 useEffect(() => { 51 if (token) { 52 router.replace("/(tabs)"); 53 } 54 }, [token, router]); 55 56 useEffect(() => { 57 if (mutationError) { 58 setError(fromError(mutationError)); 59 } 60 }, [mutationError, setError]); 61 62 const login = useCallback( 63 async (request: LoginRequest) => { 64 try { 65 const { data, error } = await mutateAsync(request); 66 67 const realError = data && "error" in data ? data.error : error; 68 69 if (realError || !data) { 70 throw realError ?? "no data"; 71 } 72 73 setToken(data); 74 router.push("/(tabs)"); 75 } catch (e) { 76 setError(isLoginError(e) ? e : fromError(e)); 77 } 78 }, 79 [mutateAsync, setToken, router], 80 ); 81 82 return { 83 data, 84 error, 85 loading: isPending, 86 login, 87 }; 88};