eletrotupi / tcc/ frontend/context/AuthContext.tsx12c613c01bc44da902e59329b5ed93393aa84da7
4.4 KB | 184 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
    notificationsEnabled: data.notificationsEnabled,
41
    dailyReminderTime: data.dailyReminderTime,
42
  };
43
}
44

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

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

53
  return context;
54
}
55

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

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

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

70
      if (token) {
71
        const verifyResponse = await apiClient.verifyToken();
72
        if (
73
          verifyResponse.valid &&
74
          verifyResponse.userId &&
75
          verifyResponse.email
76
        ) {
77
          // TODO: Fetch the full user profile
78
          // For now, we'll create a basic user object
79
          setUser({
80
            id: verifyResponse.userId,
81
            email: verifyResponse.email,
82
            ...verifyResponse.user,
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 (
96
    email: string,
97
    password: string,
98
  ): Promise<{ user: User } | null> => {
99
    setIsLoading(true);
100

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

104
      if (response.user) {
105
        setUser(response.user);
106
      }
107

108
      return response;
109
    } finally {
110
      setIsLoading(false);
111
    }
112
  };
113

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

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

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

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

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

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

154
    if (response.user) {
155
      setUser(response.user);
156
    }
157

158
    return response;
159
  };
160

161
  const requestActivateCode = async () => {
162
    await apiClient.requestActivateCode();
163
  };
164

165
  const updateAuthUser = (user) => {
166
    setUser(user);
167
  };
168

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

183
  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
184
};