frontend/api: talk to backend
Pedro Lucas Porcellis porcellis@eletrotupi.com · 6 months ago
ab2823cbed15286495b6d3cf14e40bc9389967b1 Browse filesParents
7dacef6Changed files
1
Additions
+129
Deletions
0
/dev/null → frontend/lib/api.ts
1 +
import * as SecureStore from 'expo-secure-store';
2 +
3 +
const API_BASE_URL = 'http://192.168.3.76:3000';
4 +
const TOKEN_KEY = 'sky-is-crying'; // Gary B.B Coleman fucking slaps
5 +
6 +
export interface User {
7 +
id: number;
8 +
email: string;
9 +
firstName: string;
10 +
lastName?: string;
11 +
}
12 +
13 +
export interface AuthResponse {
14 +
token: string;
15 +
user: User;
16 +
}
17 +
18 +
class ApiClient {
19 +
private async getStoredToken(): Promise<string | null> {
20 +
try {
21 +
return await SecureStore.getItemAsync(TOKEN_KEY);
22 +
} catch (error) {
23 +
console.error('Failed to get stored token:', error);
24 +
return null;
25 +
}
26 +
}
27 +
28 +
private async storeToken(token: string): Promise<void> {
29 +
try {
30 +
await SecureStore.setItemAsync(TOKEN_KEY, token);
31 +
} catch (error) {
32 +
console.error('Failed to store token:', error);
33 +
throw error;
34 +
}
35 +
}
36 +
37 +
private async removeToken(): Promise<void> {
38 +
try {
39 +
await SecureStore.deleteItemAsync(TOKEN_KEY);
40 +
} catch (error) {
41 +
console.error('Failed to remove token:', error);
42 +
}
43 +
}
44 +
45 +
private async request<T>(
46 +
endpoint: string,
47 +
options: RequestInit = {}
48 +
): Promise<T> {
49 +
const token = await this.getStoredToken();
50 +
51 +
const config: RequestInit = {
52 +
...options,
53 +
headers: {
54 +
'Content-Type': 'application/json',
55 +
...(token && { Authorization: `Bearer ${token}` }),
56 +
...options.headers,
57 +
},
58 +
};
59 +
60 +
const response = await fetch(`${API_BASE_URL}${endpoint}`, config);
61 +
62 +
if (!response.ok) {
63 +
const error = await response.json().catch(() => ({ error: 'Network error' }));
64 +
throw new Error(error.error || `HTTP ${response.status}`);
65 +
}
66 +
67 +
return response.json();
68 +
}
69 +
70 +
async login(email: string, password: string): Promise<AuthResponse> {
71 +
const response = await this.request<AuthResponse>('/auth/login', {
72 +
method: 'POST',
73 +
body: JSON.stringify({ email, password }),
74 +
});
75 +
76 +
await this.storeToken(response.token);
77 +
return response;
78 +
}
79 +
80 +
async signup(userData: {
81 +
first_name: string;
82 +
last_name?: string;
83 +
email: string;
84 +
password: string;
85 +
}): Promise<AuthResponse> {
86 +
const response = await this.request<AuthResponse>('/users', {
87 +
method: 'POST',
88 +
body: JSON.stringify(userData),
89 +
});
90 +
91 +
await this.storeToken(response.token);
92 +
return response;
93 +
}
94 +
95 +
async forgotPassword(email: string): Promise<{ message: string; token?: string }> {
96 +
return this.request('/auth/forgot-password', {
97 +
method: 'POST',
98 +
body: JSON.stringify({ email }),
99 +
});
100 +
}
101 +
102 +
async resetPassword(token: string, password: string): Promise<{ message: string }> {
103 +
return this.request('/auth/reset-password', {
104 +
method: 'POST',
105 +
body: JSON.stringify({ token, password }),
106 +
});
107 +
}
108 +
109 +
async verifyToken(): Promise<{ valid: boolean; userId?: number; email?: string }> {
110 +
try {
111 +
return await this.request('/auth/verify');
112 +
} catch (error) {
113 +
// Token is invalid or expired
114 +
await this.removeToken();
115 +
throw error;
116 +
}
117 +
}
118 +
119 +
async logout(): Promise<void> {
120 +
await this.removeToken();
121 +
}
122 +
123 +
async getStoredAuthData(): Promise<{ token: string | null }> {
124 +
const token = await this.getStoredToken();
125 +
return { token };
126 +
}
127 +
}
128 +
129 +
export const apiClient = new ApiClient();