mirror of
https://github.com/dat515-2025/Group-8.git
synced 2026-03-22 06:57:47 +01:00
144 lines
3.9 KiB
TypeScript
144 lines
3.9 KiB
TypeScript
import { BACKEND_URL } from './config';
|
|
|
|
export type LoginResponse = {
|
|
access_token: string;
|
|
token_type: string;
|
|
};
|
|
|
|
export type Category = {
|
|
id: number;
|
|
name: string;
|
|
description?: string | null;
|
|
};
|
|
|
|
export type Transaction = {
|
|
id: number;
|
|
amount: number;
|
|
description?: string | null;
|
|
category_ids: number[];
|
|
};
|
|
|
|
function getBaseUrl() {
|
|
const base = BACKEND_URL?.replace(/\/$/, '') || '';
|
|
return base || '';
|
|
}
|
|
|
|
function authHeaders() {
|
|
const token = localStorage.getItem('token');
|
|
return token ? { Authorization: `Bearer ${token}` } : {};
|
|
}
|
|
|
|
export async function login(email: string, password: string): Promise<void> {
|
|
const body = new URLSearchParams();
|
|
body.set('username', email);
|
|
body.set('password', password);
|
|
|
|
const res = await fetch(`${getBaseUrl()}/auth/jwt/login`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
},
|
|
body: body.toString(),
|
|
});
|
|
if (!res.ok) {
|
|
const text = await res.text();
|
|
throw new Error(text || 'Login failed');
|
|
}
|
|
const data: LoginResponse = await res.json();
|
|
localStorage.setItem('token', data.access_token);
|
|
}
|
|
|
|
export async function register(email: string, password: string, first_name?: string, last_name?: string): Promise<void> {
|
|
const res = await fetch(`${getBaseUrl()}/auth/register`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ email, password, first_name, last_name }),
|
|
});
|
|
if (!res.ok) {
|
|
const text = await res.text();
|
|
throw new Error(text || 'Registration failed');
|
|
}
|
|
}
|
|
|
|
export async function getCategories(): Promise<Category[]> {
|
|
const res = await fetch(`${getBaseUrl()}/categories/`, {
|
|
headers: { 'Content-Type': 'application/json', ...authHeaders() },
|
|
});
|
|
if (!res.ok) throw new Error('Failed to load categories');
|
|
return res.json();
|
|
}
|
|
|
|
export type CreateTransactionInput = {
|
|
amount: number;
|
|
description?: string;
|
|
category_ids?: number[];
|
|
};
|
|
|
|
export async function createTransaction(input: CreateTransactionInput): Promise<Transaction> {
|
|
const res = await fetch(`${getBaseUrl()}/transactions/create`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', ...authHeaders() },
|
|
body: JSON.stringify(input),
|
|
});
|
|
if (!res.ok) {
|
|
const text = await res.text();
|
|
throw new Error(text || 'Failed to create transaction');
|
|
}
|
|
return res.json();
|
|
}
|
|
|
|
export async function getTransactions(): Promise<Transaction[]> {
|
|
const res = await fetch(`${getBaseUrl()}/transactions/`, {
|
|
headers: { 'Content-Type': 'application/json', ...authHeaders() },
|
|
});
|
|
if (!res.ok) throw new Error('Failed to load transactions');
|
|
return res.json();
|
|
}
|
|
|
|
export type User = {
|
|
id: string;
|
|
email: string;
|
|
first_name?: string | null;
|
|
last_name?: string | null;
|
|
is_active: boolean;
|
|
is_superuser: boolean;
|
|
is_verified: boolean;
|
|
};
|
|
|
|
export async function getMe(): Promise<User> {
|
|
const res = await fetch(`${getBaseUrl()}/users/me`, {
|
|
headers: { 'Content-Type': 'application/json', ...authHeaders() },
|
|
});
|
|
if (!res.ok) throw new Error('Failed to load user');
|
|
return res.json();
|
|
}
|
|
|
|
export type UpdateMeInput = Partial<Pick<User, 'first_name' | 'last_name'>> & { password?: string };
|
|
export async function updateMe(input: UpdateMeInput): Promise<User> {
|
|
const res = await fetch(`${getBaseUrl()}/users/me`, {
|
|
method: 'PATCH',
|
|
headers: { 'Content-Type': 'application/json', ...authHeaders() },
|
|
body: JSON.stringify(input),
|
|
});
|
|
if (!res.ok) {
|
|
const text = await res.text();
|
|
throw new Error(text || 'Failed to update user');
|
|
}
|
|
return res.json();
|
|
}
|
|
|
|
export async function deleteMe(): Promise<void> {
|
|
const res = await fetch(`${getBaseUrl()}/users/me`, {
|
|
method: 'DELETE',
|
|
headers: { ...authHeaders() },
|
|
});
|
|
if (!res.ok) {
|
|
const text = await res.text();
|
|
throw new Error(text || 'Failed to delete account');
|
|
}
|
|
}
|
|
|
|
export function logout() {
|
|
localStorage.removeItem('token');
|
|
}
|