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 getHeaders(contentType: 'json' | 'form' | 'none' = 'json'): Record { const token = localStorage.getItem('token'); const headers: Record = {}; if (contentType === 'json') { headers['Content-Type'] = 'application/json'; } else if (contentType === 'form') { headers['Content-Type'] = 'application/x-www-form-urlencoded'; } if (token) { headers['Authorization'] = `Bearer ${token}`; } return headers; } export async function login(email: string, password: string): Promise { 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 { 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 { const res = await fetch(`${getBaseUrl()}/categories/`, { headers: getHeaders(), }); 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 { const res = await fetch(`${getBaseUrl()}/transactions/create`, { method: 'POST', headers: getHeaders(), 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 { const res = await fetch(`${getBaseUrl()}/transactions/`, { headers: getHeaders(), }); 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 { const res = await fetch(`${getBaseUrl()}/users/me`, { headers: getHeaders(), }); if (!res.ok) throw new Error('Failed to load user'); return res.json(); } export type UpdateMeInput = Partial> & { password?: string }; export async function updateMe(input: UpdateMeInput): Promise { const res = await fetch(`${getBaseUrl()}/users/me`, { method: 'PATCH', headers: getHeaders(), 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 { const res = await fetch(`${getBaseUrl()}/users/me`, { method: 'DELETE', headers: getHeaders(), }); if (!res.ok) { const text = await res.text(); throw new Error(text || 'Failed to delete account'); } } export function logout() { localStorage.removeItem('token'); }