frontend/context: auth provider + hooks

Pedro Lucas Porcellis porcellis@eletrotupi.com 2 months ago 5d37e204b398ac39b26f3226aa1500a045d0e2ce
Parents: ab2823c
1 file(s) changed
  • frontend/context/AuthContext.tsx +130 -0
frontend/context/AuthContext.tsx
@@ -0,0 +1,130 @@
1 + import React, { createContext, useContext, useEffect, useState } from 'react';
2 + import { apiClient, User } from '@/lib/api';
3 +
4 + interface AuthContextType {
5 + user: User | null;
6 + isLoading: boolean;
7 + isAuthenticated: boolean;
8 + login: (email: string, password: string) => Promise<void>;
9 + signup: (userData: {
10 + first_name: string;
11 + last_name?: string;
12 + email: string;
13 + password: string;
14 + }) => Promise<void>;
15 + logout: () => Promise<void>;
16 + forgotPassword: (email: string) => Promise<{ message: string; token?: string }>;
17 + resetPassword: (token: string, password: string) => Promise<void>;
18 + }
19 +
20 + const AuthContext = createContext<AuthContextType | null>(null);
21 +
22 + export function useAuth() {
23 + const context = useContext(AuthContext);
24 + if (!context) {
25 + throw new Error('useAuth must be used within an AuthProvider');
26 + }
27 + return context;
28 + }
29 +
30 + interface AuthProviderProps {
31 + children: React.ReactNode;
32 + }
33 +
34 + export function AuthProvider({ children }: AuthProviderProps) {
35 + const [user, setUser] = useState<User | null>(null);
36 + const [isLoading, setIsLoading] = useState(true);
37 +
38 + const isAuthenticated = !!user;
39 +
40 + // Check for existing authentication on app start
41 + useEffect(() => {
42 + checkAuthState();
43 + }, []);
44 +
45 + const checkAuthState = async () => {
46 + try {
47 + const { token } = await apiClient.getStoredAuthData();
48 +
49 + if (token) {
50 + const verifyResponse = await apiClient.verifyToken();
51 + if (verifyResponse.valid && verifyResponse.userId && verifyResponse.email) {
52 + // TODO: Fetch the full user profile
53 + // For now, we'll create a basic user object
54 + setUser({
55 + id: verifyResponse.userId,
56 + email: verifyResponse.email,
57 + firstName: '',
58 + lastName: undefined,
59 + });
60 + }
61 + }
62 + } catch (error) {
63 + console.error('Auth check failed:', error);
64 + // Token is invalid, wipe out any stored data
65 + await apiClient.logout();
66 + } finally {
67 + setIsLoading(false);
68 + }
69 + };
70 +
71 + const login = async (email: string, password: string) => {
72 + setIsLoading(true);
73 + try {
74 + const response = await apiClient.login(email, password);
75 + setUser(response.user);
76 + } finally {
77 + setIsLoading(false);
78 + }
79 + };
80 +
81 + const signup = async (userData: {
82 + first_name: string;
83 + last_name?: string;
84 + email: string;
85 + password: string;
86 + }) => {
87 + setIsLoading(true);
88 + try {
89 + const response = await apiClient.signup(userData);
90 + setUser(response.user);
91 + } finally {
92 + setIsLoading(false);
93 + }
94 + };
95 +
96 + const logout = async () => {
97 + setIsLoading(true);
98 + try {
99 + await apiClient.logout();
100 + setUser(null);
101 + } finally {
102 + setIsLoading(false);
103 + }
104 + };
105 +
106 + const forgotPassword = async (email: string) => {
107 + return apiClient.forgotPassword(email);
108 + };
109 +
110 + const resetPassword = async (token: string, password: string) => {
111 + await apiClient.resetPassword(token, password);
112 + };
113 +
114 + const value: AuthContextType = {
115 + user,
116 + isLoading,
117 + isAuthenticated,
118 + login,
119 + signup,
120 + logout,
121 + forgotPassword,
122 + resetPassword,
123 + };
124 +
125 + return (
126 + <AuthContext.Provider value={value}>
127 + {children}
128 + </AuthContext.Provider>
129 + );
130 + }