aboutsummaryrefslogtreecommitdiffstats
path: root/frontend/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src/lib')
-rw-r--r--frontend/src/lib/api.ts123
-rw-r--r--frontend/src/lib/utils.ts6
2 files changed, 129 insertions, 0 deletions
diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts
new file mode 100644
index 0000000..35ef8d6
--- /dev/null
+++ b/frontend/src/lib/api.ts
@@ -0,0 +1,123 @@
+// API base URL
+const API_BASE_URL = 'http://localhost:8080/api/v1';
+
+// Helper function for fetching data with authorization
+async function fetchWithAuth(url: string, options: RequestInit = {}) {
+ // Get token from local storage
+ const token = localStorage.getItem('token');
+
+ // Set up headers with authorization
+ const headers = {
+ 'Content-Type': 'application/json',
+ ...(token ? { 'Authorization': `Bearer ${token}` } : {}),
+ ...options.headers
+ };
+
+ // Perform fetch
+ const response = await fetch(`${API_BASE_URL}${url}`, {
+ ...options,
+ headers
+ });
+
+ // Handle unauthorized responses
+ if (response.status === 401) {
+ localStorage.removeItem('token');
+ window.location.href = '/login';
+ throw new Error('Unauthorized');
+ }
+
+ // Parse response
+ if (!response.ok) {
+ const errorData = await response.json().catch(() => null);
+ throw new Error(errorData?.error || `API Error: ${response.status}`);
+ }
+
+ return response.json();
+}
+
+// Auth API
+export const authApi = {
+ login: async (email: string, password: string) => {
+ const response = await fetch(`${API_BASE_URL}/auth/login`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ email, password })
+ });
+
+ if (!response.ok) {
+ const errorData = await response.json().catch(() => null);
+ throw new Error(errorData?.error || 'Login failed');
+ }
+
+ const data = await response.json();
+ localStorage.setItem('token', data.token);
+ return data;
+ },
+
+ signup: async (name: string, email: string, password: string) => {
+ const response = await fetch(`${API_BASE_URL}/auth/signup`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ name, email, password })
+ });
+
+ if (!response.ok) {
+ const errorData = await response.json().catch(() => null);
+ throw new Error(errorData?.error || 'Signup failed');
+ }
+
+ return response.json();
+ },
+
+ logout: () => {
+ localStorage.removeItem('token');
+ window.location.href = '/login';
+ }
+};
+
+// Loan API
+export interface Loan {
+ ID: number;
+ CreatedAt: string;
+ UpdatedAt: string;
+ DeletedAt: string | null;
+ UserID: number;
+ AccountID: number | null;
+ Name: string;
+ OriginalAmount: number;
+ CurrentBalance: number;
+ InterestRate: number;
+ StartDate: string;
+ EndDate: string;
+}
+
+export interface LoanInput {
+ name: string;
+ originalAmount: number;
+ currentBalance: number;
+ interestRate: number;
+ startDate: string;
+ endDate: string;
+ accountId?: number;
+}
+
+export const loanApi = {
+ getLoans: () => fetchWithAuth('/loans'),
+ getLoan: (id: number) => fetchWithAuth(`/loans/${id}`),
+ createLoan: (loan: LoanInput) => fetchWithAuth('/loans', {
+ method: 'POST',
+ body: JSON.stringify(loan)
+ }),
+ updateLoan: (id: number, loan: Partial<LoanInput>) => fetchWithAuth(`/loans/${id}`, {
+ method: 'PUT',
+ body: JSON.stringify(loan)
+ }),
+ deleteLoan: (id: number) => fetchWithAuth(`/loans/${id}`, {
+ method: 'DELETE'
+ })
+};
+
+// User API
+export const userApi = {
+ getProfile: () => fetchWithAuth('/users/me')
+}; \ No newline at end of file
diff --git a/frontend/src/lib/utils.ts b/frontend/src/lib/utils.ts
new file mode 100644
index 0000000..bd0c391
--- /dev/null
+++ b/frontend/src/lib/utils.ts
@@ -0,0 +1,6 @@
+import { clsx, type ClassValue } from "clsx"
+import { twMerge } from "tailwind-merge"
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs))
+}