Files
tfm_ainventory/frontend/lib/api.ts
Daniel Bedeleanu 704934165f Build [v.1.3.6]
2026-04-11 17:14:22 +03:00

169 lines
4.7 KiB
TypeScript

import axios from 'axios';
import { getToken, clearAuth } from './auth';
export const getBackendUrl = () => {
if (typeof window === 'undefined') return 'http://localhost:8000';
const host = window.location.hostname;
// If we are on HTTPS (Proxy/Mobile mode), we use port 3002 for the backend
if (window.location.protocol === 'https:') {
if (host.includes('.loca.lt')) {
return 'https://inventory-ai-api.loca.lt';
}
return `https://${host}:3002`;
}
return `http://${host}:8000`;
};
/**
* [C-01] Axios instance cu JWT Bearer token în header
* și interceptor pentru 401 Unauthorized (token expired)
*/
const axiosInstance = axios.create({});
axiosInstance.interceptors.request.use((config) => {
if (!config.baseURL) {
config.baseURL = getBackendUrl(); // called at request time — always correct
}
const token = getToken();
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
}, (error) => Promise.reject(error));
axiosInstance.interceptors.response.use(
(response) => response,
(error) => {
// [L-01] Handle 401 Unauthorized — token expired
if (error.response?.status === 401) {
clearAuth();
if (typeof window !== 'undefined' && !window.location.pathname.includes('/login')) {
window.location.href = '/login';
}
}
return Promise.reject(error);
}
);
export const inventoryApi = {
getItems: async () => {
const res = await axiosInstance.get('/items/');
return res.data;
},
getStats: async () => {
const res = await axiosInstance.get('/items/stats');
return res.data;
},
syncBulkOperations: async (userId: number, operations: any[]) => {
try {
const res = await axiosInstance.post('/operations/bulk-sync', {
user_id: userId,
operations: operations
});
return res.data;
} catch (err: any) {
console.error("Sync API Error:", err);
if (err.response?.status === 404) {
throw new Error(`404: Endpoint not found`);
}
throw err;
}
},
analyzeLabel: async (formData: FormData) => {
const res = await axiosInstance.post('/items/extract-label', formData, {
headers: { 'Content-Type': 'multipart/form-data' }
});
return res.data;
},
createItem: async (userId: number, itemData: any) => {
const res = await axiosInstance.post('/items/', itemData);
return res.data;
},
updateItem: async (itemId: number, itemData: any) => {
const res = await axiosInstance.put(`/items/${itemId}`, itemData);
return res.data;
},
adjustStock: async (endpoint: string, data: any) => {
const res = await axiosInstance.post(`/operations/${endpoint}`, data);
return res.data;
},
deleteItem: async (itemId: number) => {
const res = await axiosInstance.delete(`/items/${itemId}`);
return res.data;
},
getAuditLogs: async (limit: number = 50) => {
const res = await axiosInstance.get('/operations/logs', { params: { limit } });
return res.data;
},
// Users
getUsers: async () => {
// [C-01] Public endpoint — use plain axios to avoid JWT interceptor
const res = await axios.get(`${getBackendUrl()}/users/`);
return res.data;
},
createUser: async (userData: any) => {
const res = await axiosInstance.post('/users/', userData);
return res.data;
},
login: async (credentials: any) => {
// [C-01] Login endpoint — NU adaug token header (login e public)
const res = await axios.post(`${getBackendUrl()}/users/login`, credentials);
return res.data;
},
deleteUser: async (userId: number) => {
const res = await axiosInstance.delete(`/users/${userId}`);
return res.data;
},
updateUser: async (userId: number, data: any) => {
const res = await axiosInstance.put(`/users/${userId}`, data);
return res.data;
},
getLdapConfig: async () => {
const res = await axiosInstance.get('/users/ldap-config');
return res.data;
},
updateLdapConfig: async (config: any) => {
const res = await axiosInstance.post('/users/ldap-config', config);
return res.data;
},
testLdapConnection: async (config: any) => {
const res = await axiosInstance.post('/users/test-ldap', config);
return res.data;
},
// Categories
getCategories: async () => {
const res = await axiosInstance.get('/categories/');
return res.data;
},
createCategory: async (data: any) => {
const res = await axiosInstance.post('/categories/', data);
return res.data;
},
updateCategory: async (id: number, data: any) => {
const res = await axiosInstance.put(`/categories/${id}`, data);
return res.data;
},
deleteCategory: async (id: number) => {
const res = await axiosInstance.delete(`/categories/${id}`);
return res.data;
}
};