eletrotupi / tcc/ frontend/context/AuthContext.tsxf9e8c48e8060613464a074cf3f6336a360a9c3c6
4.3 KB | 182 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: User) => void;
14
  login: (email: string, password: string) => Promise<{ user: User } | null>;
15
  signup: (userData: {
16
    firstName: string;
17
    lastName?: string;
18
    email: string;
19
    password: string;
20
  }) => Promise<void>;
21
  logout: () => Promise<void>;
22
  forgotPassword: (
23
    email: string,
24
  ) => Promise<{ message: string; token?: string }>;
25
  resetPassword: (token: string, password: string) => Promise<void>;
26
  activate: (code: string) => Promise<void>;
27
  requestActivateCode: () => Promise<void>;
28
}
29

30
export function sanitizeUser(data: any): User {
31
  return {
32
    id: data.id,
33
    email: data.email,
34
    firstName: data.firstName,
35
    lastName: data.lastName,
36
    updatedAt: data.updatedAt,
37
    avatarKey: data.avatarKey,
38
    avatarURL: data.avatarURL,
39
    active: data.active,
40
  };
41
}
42

43
const AuthContext = createContext<AuthContextType | null>(null);
44

45
export function useAuth() {
46
  const context = useContext(AuthContext);
47
  if (!context) {
48
    throw new Error("useAuth must be used within an AuthProvider");
49
  }
50

51
  return context;
52
}
53

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

59
  // Check for existing authentication on app start
60
  useEffect(() => {
61
    checkAuthState();
62
  }, []);
63

64
  const checkAuthState = async () => {
65
    try {
66
      const { token } = await apiClient.getStoredAuthData();
67

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

93
  const login = async (
94
    email: string,
95
    password: string,
96
  ): Promise<{ user: User } | null> => {
97
    setIsLoading(true);
98

99
    try {
100
      const response = await apiClient.login(email, password);
101

102
      if (response.user) {
103
        setUser(response.user);
104
      }
105

106
      return response;
107
    } finally {
108
      setIsLoading(false);
109
    }
110
  };
111

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

127
  const logout = async () => {
128
    setIsLoading(true);
129
    try {
130
      await apiClient.logout();
131

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

141
  const forgotPassword = async (email: string) => {
142
    return apiClient.forgotPassword(email);
143
  };
144

145
  const resetPassword = async (token: string, password: string) => {
146
    await apiClient.resetPassword(token, password);
147
  };
148

149
  const activate = async (code: number) => {
150
    const response = await apiClient.activate(code);
151

152
    if (response.user) {
153
      setUser(response.user);
154
    }
155

156
    return response;
157
  };
158

159
  const requestActivateCode = async () => {
160
    await apiClient.requestActivateCode();
161
  };
162

163
  const updateAuthUser = (user) => {
164
    setUser(user);
165
  };
166

167
  const value: AuthContextType = {
168
    user,
169
    isLoading,
170
    isAuthenticated,
171
    login,
172
    signup,
173
    logout,
174
    forgotPassword,
175
    resetPassword,
176
    updateAuthUser,
177
    activate,
178
    requestActivateCode,
179
  };
180

181
  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
182
};