eletrotupi / tcc/ frontend/context/AuthContext.tsx6d8c0a74220b36e86fd53538617fd70ce2618f59
4.3 KB | 178 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
    active: boolean;
21
  }) => void;
22
  login: (email: string, password: string) => Promise<void>;
23
  signup: (userData: {
24
    firstName: string;
25
    lastName?: string;
26
    email: string;
27
    password: string;
28
  }) => Promise<void>;
29
  logout: () => Promise<void>;
30
  forgotPassword: (email: string) => Promise<{ message: string; token?: string }>;
31
  resetPassword: (token: string, password: string) => Promise<void>;
32
  activate: (code: string) => Promise<void>;
33
}
34

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

48
const AuthContext = createContext<AuthContextType | null>(null);
49

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

56
  return context;
57
}
58

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

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

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

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

98
  const login = async (email: string, password: string) => {
99
    setIsLoading(true);
100

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

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

124
  const logout = async () => {
125
    setIsLoading(true);
126
    try {
127
      await apiClient.logout();
128

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

138
  const forgotPassword = async (email: string) => {
139
    return apiClient.forgotPassword(email);
140
  };
141

142
  const resetPassword = async (token: string, password: string) => {
143
    await apiClient.resetPassword(token, password);
144
  };
145

146
  const activate = async (code: number) => {
147
    const response = await apiClient.activate(code);
148

149
    if (response.user) {
150
      updateAuthUser(response.user)
151
    }
152

153
    return response
154
  }
155

156
  const updateAuthUser = (user) => {
157
    setUser(sanitizeUser(user));
158
  }
159

160
  const value: AuthContextType = {
161
    user,
162
    isLoading,
163
    isAuthenticated,
164
    login,
165
    signup,
166
    logout,
167
    forgotPassword,
168
    resetPassword,
169
    updateAuthUser,
170
    activate
171
  };
172

173
  return (
174
    <AuthContext.Provider value={value}>
175
      {children}
176
    </AuthContext.Provider>
177
  );
178
}