add client api methods

This commit is contained in:
Joseph D'Souza 2026-02-11 13:04:04 +01:00
parent da9ba3094c
commit 685c6bb2ce

View File

@ -1,4 +1,14 @@
export const API_URL = 'https://supercuriously-precongested-chester.ngrok-free.dev/api';
import { useAuthStore } from '../store/useAuthStore';
const getAuthHeaders = () => {
const token = useAuthStore.getState().user?.token;
return {
'Accept': 'application/json',
...(token ? { 'Authorization': `Bearer ${token}` } : {}),
};
};
export const API_URL = 'https://supercuriously-precongested-chester.ngrok-free.dev/api'; // ngrok URL for testing
export const authService = {
login: async (username, password) => {
@ -45,11 +55,11 @@ export const authService = {
},
body: JSON.stringify({ email }),
});
if (response.ok) {
return { ok: true };
}
// Parse error message
const data = await response.json();
return { ok: false, message: data.message || 'Failed to send reset link' };
@ -71,4 +81,114 @@ export const authService = {
});
return response.json();
},
getProfile: async () => {
const response = await fetch(`${API_URL}/me`, {
method: 'GET',
headers: getAuthHeaders(),
});
return response.json();
},
updateProfile: async (data: any) => {
const response = await fetch(`${API_URL}/me/details`, {
method: 'PATCH',
headers: {
...getAuthHeaders(),
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
const text = await response.text();
try {
const json = JSON.parse(text);
if (response.ok) {
return { ok: true, data: json };
}
return { ok: false, message: json.message || 'Failed to update profile' };
} catch (e) {
console.error('Update Profile Error (Raw Response):', text);
return { ok: false, message: 'Server returned an invalid response' };
}
},
uploadAvatar: async (imageUri: string) => {
const formData = new FormData();
// Simplification: Always name the file 'avatar.jpg' and type 'image/jpeg'.
// This avoids issues with weird temp filenames or missing extensions
// that cause backend validation ("must be an image") to fail.
// React Native's FormData will read the file bytes correctly from the URI.
const filename = 'avatar.jpg';
const type = 'image/jpeg';
// React Native FormData expects an object with uri, name, type.
// Cast to 'any' to avoid TypeScript type mismatch.
formData.append('file', { uri: imageUri, name: filename, type } as any);
const response = await fetch(`${API_URL}/me/avatar`, {
method: 'POST',
headers: {
...getAuthHeaders(),
},
body: formData,
});
const text = await response.text();
try {
const json = JSON.parse(text);
if (response.ok) {
return { ok: true, data: json };
}
console.error('Upload Avatar Failed (Server Message):', json);
return { ok: false, message: json.message || 'Failed to upload avatar' };
} catch (e) {
console.error('Upload Avatar Error (Raw Response):', text);
return { ok: false, message: 'Server returned an invalid response' };
}
},
resendVerificationEmail: async () => {
const response = await fetch(`${API_URL}/email/resend`, {
method: 'POST',
headers: {
...getAuthHeaders(),
'Content-Type': 'application/json',
},
});
if (response.ok) {
return { ok: true };
}
const text = await response.text();
try {
const json = JSON.parse(text);
return { ok: false, message: json.message || 'Failed to send verification email' };
} catch {
return { ok: false, message: 'Network error' };
}
},
deleteAccount: async () => {
const response = await fetch(`${API_URL}/me`, {
method: 'DELETE',
headers: getAuthHeaders(),
});
if (response.ok) {
return { ok: true };
}
const text = await response.text();
try {
const json = JSON.parse(text);
console.error('Delete Account Failed (Server Message):', json);
return { ok: false, message: json.message || 'Failed to delete account' };
} catch {
console.error('Delete Account Failed (Raw Response):', text);
return { ok: false, message: 'Server returned an invalid response' };
}
},
};