eletrotupi / tcc/ frontend/context/AuthContext.tsx031a372a6e1f95cfbac1b82e2078da48a3674fb3
4.0 KB | 164 lines Raw
1
import React, { createContext, useContext, useEffect, useState } from 'react';
2
import { apiClient, User } from '@/lib/api';
3
import { queryClient, storage } from '@/lib/queryClient';
4

5
interface AuthProviderProps {
6
  children: React.ReactNode;
7
}
8

9
interface AuthContextType {
10
  user: User | null;
11
  isLoading: boolean;
12
  isAuthenticated: boolean;
13
  updateAuthUser: (user: {
14
    firstName: string;
15
    lastName?: string;
16
    email: string;
17
    updatedAt: date;
18
    avatarURL?: string;
19
    avatarKey?: string;
20
  }) => void;
21
  login: (email: string, password: string) => Promise<void>;
22
  signup: (userData: {
23
    firstName: string;
24
    lastName?: string;
25
    email: string;
26
    password: string;
27
  }) => Promise<void>;
28
  logout: () => Promise<void>;
29
  forgotPassword: (email: string) => Promise<{ message: string; token?: string }>;
30
  resetPassword: (token: string, password: string) => Promise<void>;
31
}
32

33

34
export function sanitizeUser(data: any): User {
35
  return {
36
    id: data.id,
37
    email: data.email,
38
    firstName: data.firstName,
39
    lastName: data.lastName,
40
    updatedAt: data.updatedAt,
41
    avatarKey: data.avatarKey,
42
    avatarURL: data.avatarURL,
43
  };
44
}
45

46
const AuthContext = createContext<AuthContextType | null>(null);
47

48
export function useAuth() {
49
  const context = useContext(AuthContext);
50
  if (!context) {
51
    throw new Error('useAuth must be used within an AuthProvider');
52
  }
53

54
  return context;
55
}
56

57
export const AuthProvider = ({ children }: AuthProviderProps) => {
58
  const [user, setUser] = useState<User | null>(null);
59
  const [isLoading, setIsLoading] = useState(true);
60
  const isAuthenticated = !!user;
61

62
  // Check for existing authentication on app start
63
  useEffect(() => {
64
    checkAuthState();
65
  }, []);
66

67
  const checkAuthState = async () => {
68
    try {
69
      const { token } = await apiClient.getStoredAuthData();
70

71
      if (token) {
72
        const verifyResponse = await apiClient.verifyToken();
73
        if (verifyResponse.valid && verifyResponse.userId && verifyResponse.email) {
74
          // TODO: Fetch the full user profile
75
          // For now, we'll create a basic user object
76
          setUser({
77
            id: verifyResponse.userId,
78
            email: verifyResponse.email,
79
            firstName: verifyResponse.user.firstName,
80
            lastName: verifyResponse.user.lastName,
81
            avatarURL: verifyResponse.user.avatarURL,
82
            avatarKey: verifyResponse.user.avatarKey
83
          });
84
        }
85
      }
86
    } catch (error) {
87
      console.error('Auth check failed:', error);
88
      // Token is invalid, wipe out any stored data
89
      await apiClient.logout();
90
    } finally {
91
      setIsLoading(false);
92
    }
93
  };
94

95
  const login = async (email: string, password: string) => {
96
    setIsLoading(true);
97

98
    try {
99
      const response = await apiClient.login(email, password);
100
      setUser(response.user);
101
    } finally {
102
      setIsLoading(false);
103
    }
104
  };
105

106
  const signup = async (userData: {
107
    firstName: string;
108
    lastName?: string;
109
    email: string;
110
    password: string;
111
  }) => {
112
    setIsLoading(true);
113
    try {
114
      const response = await apiClient.signup(userData);
115
      setUser(response.user);
116
    } finally {
117
      setIsLoading(false);
118
    }
119
  };
120

121
  const logout = async () => {
122
    setIsLoading(true);
123
    try {
124
      await apiClient.logout();
125

126
      setUser(null);
127
      // Clear both the in-memory cache and the persisted MMKV cache
128
      queryClient.clear();
129
      storage.clearAll();
130
    } finally {
131
      setIsLoading(false);
132
    }
133
  };
134

135
  const forgotPassword = async (email: string) => {
136
    return apiClient.forgotPassword(email);
137
  };
138

139
  const resetPassword = async (token: string, password: string) => {
140
    await apiClient.resetPassword(token, password);
141
  };
142

143
  const updateAuthUser = (user) => {
144
    setUser(sanitizeUser(user));
145
  }
146

147
  const value: AuthContextType = {
148
    user,
149
    isLoading,
150
    isAuthenticated,
151
    login,
152
    signup,
153
    logout,
154
    forgotPassword,
155
    resetPassword,
156
    updateAuthUser
157
  };
158

159
  return (
160
    <AuthContext.Provider value={value}>
161
      {children}
162
    </AuthContext.Provider>
163
  );
164
}