michangarrito/apps/frontend/src/lib/api.ts
rckrdmrd 928eb795e6 [SIMCO-V38] feat: Actualizar a SIMCO v3.8.0 + cambios apps
- HERENCIA-SIMCO.md actualizado con directivas v3.7 y v3.8
- Cambios en backend y frontend

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 08:53:05 -06:00

217 lines
7.6 KiB
TypeScript

import axios, { AxiosError } from 'axios';
// Use proxy in development (vite will forward to backend)
// In production, use VITE_API_URL
const API_BASE = import.meta.env.VITE_API_URL || '';
const API_PREFIX = import.meta.env.VITE_API_PREFIX || '/api/v1';
export const api = axios.create({
baseURL: `${API_BASE}${API_PREFIX}`,
headers: {
'Content-Type': 'application/json',
},
});
// Add auth interceptor - attach token to requests
api.interceptors.request.use((config) => {
const token = localStorage.getItem('accessToken');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
// Response interceptor - handle 401 errors
api.interceptors.response.use(
(response) => response,
async (error: AxiosError) => {
if (error.response?.status === 401) {
// Try refresh token
const refreshToken = localStorage.getItem('refreshToken');
if (refreshToken) {
try {
const response = await axios.post(`${API_BASE}${API_PREFIX}/auth/refresh`, {
refreshToken,
});
const { accessToken, refreshToken: newRefresh } = response.data;
localStorage.setItem('accessToken', accessToken);
localStorage.setItem('refreshToken', newRefresh);
// Retry original request
if (error.config) {
error.config.headers.Authorization = `Bearer ${accessToken}`;
return axios(error.config);
}
} catch {
// Refresh failed, clear tokens and redirect to login
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
localStorage.removeItem('user');
localStorage.removeItem('tenant');
window.location.href = '/login';
}
} else {
// No refresh token, redirect to login
localStorage.removeItem('accessToken');
localStorage.removeItem('user');
localStorage.removeItem('tenant');
window.location.href = '/login';
}
}
return Promise.reject(error);
}
);
// Auth API
export const authApi = {
register: (data: {
name: string;
ownerName: string;
businessType: string;
phone: string;
pin: string;
email?: string;
whatsapp?: string;
}) => api.post('/auth/register', data),
login: (data: { phone: string; pin: string }) =>
api.post('/auth/login', data),
refresh: (refreshToken: string) =>
api.post('/auth/refresh', { refreshToken }),
changePin: (data: { currentPin: string; newPin: string }) =>
api.post('/auth/change-pin', data),
};
// Products API
export const productsApi = {
getAll: (params?: { category?: string; search?: string }) =>
api.get('/products', { params }),
getById: (id: string) => api.get(`/products/${id}`),
create: (data: any) => api.post('/products', data),
update: (id: string, data: any) => api.patch(`/products/${id}`, data),
delete: (id: string) => api.delete(`/products/${id}`),
};
// Orders API
export const ordersApi = {
getAll: (params?: { status?: string; date?: string }) =>
api.get('/orders', { params }),
getById: (id: string) => api.get(`/orders/${id}`),
create: (data: any) => api.post('/orders', data),
updateStatus: (id: string, status: string) =>
api.patch(`/orders/${id}/status`, { status }),
};
// Customers API
export const customersApi = {
getAll: (params?: { search?: string }) =>
api.get('/customers', { params }),
getById: (id: string) => api.get(`/customers/${id}`),
create: (data: any) => api.post('/customers', data),
update: (id: string, data: any) => api.patch(`/customers/${id}`, data),
getFiado: (id: string) => api.get(`/customers/${id}/fiado`),
};
// Inventory API
export const inventoryApi = {
getMovements: (params?: { productId?: string; type?: string }) =>
api.get('/inventory/movements', { params }),
createMovement: (data: any) => api.post('/inventory/movements', data),
getLowStock: () => api.get('/inventory/low-stock'),
getAlerts: () => api.get('/inventory/alerts'),
};
// Dashboard API
export const dashboardApi = {
getStats: () => api.get('/dashboard/stats'),
getSalesChart: (period: string) => api.get('/dashboard/sales', { params: { period } }),
getTopProducts: () => api.get('/dashboard/top-products'),
};
// Referrals API
export const referralsApi = {
getMyCode: () => api.get('/referrals/my-code'),
generateCode: () => api.post('/referrals/generate-code'),
validateCode: (code: string) => api.get(`/referrals/validate/${code}`),
applyCode: (code: string) => api.post('/referrals/apply-code', { code }),
getMyReferrals: () => api.get('/referrals/list'),
getStats: () => api.get('/referrals/stats'),
getRewards: () => api.get('/referrals/rewards'),
getAvailableMonths: () => api.get('/referrals/rewards/available-months'),
getDiscount: () => api.get('/referrals/discount'),
};
// CoDi/SPEI API
export const codiSpeiApi = {
// CoDi
generateQr: (data: { amount: number; description?: string; saleId?: string }) =>
api.post('/codi/generate-qr', data),
getCodiStatus: (id: string) => api.get(`/codi/status/${id}`),
getCodiTransactions: (limit?: number) =>
api.get('/codi/transactions', { params: { limit } }),
// SPEI
getClabe: () => api.get('/spei/clabe'),
createClabe: (beneficiaryName: string) =>
api.post('/spei/create-clabe', { beneficiaryName }),
getSpeiTransactions: (limit?: number) =>
api.get('/spei/transactions', { params: { limit } }),
// Summary
getSummary: (date?: string) =>
api.get('/payments/summary', { params: { date } }),
};
// Invoices API (SAT/CFDI)
export const invoicesApi = {
// Tax Config
getTaxConfig: () => api.get('/invoices/tax-config'),
saveTaxConfig: (data: any) => api.post('/invoices/tax-config', data),
// Invoices
getAll: (params?: { status?: string; from?: string; to?: string; limit?: number }) =>
api.get('/invoices', { params }),
getById: (id: string) => api.get(`/invoices/${id}`),
create: (data: any) => api.post('/invoices', data),
stamp: (id: string) => api.post(`/invoices/${id}/stamp`),
cancel: (id: string, reason: string, uuidReplacement?: string) =>
api.post(`/invoices/${id}/cancel`, { reason, uuidReplacement }),
send: (id: string, email?: string) =>
api.post(`/invoices/${id}/send`, { email }),
getSummary: (month?: string) =>
api.get('/invoices/summary', { params: { month } }),
};
// Marketplace API
export const marketplaceApi = {
// Suppliers
getSuppliers: (params?: { category?: string; zipCode?: string; search?: string; limit?: number }) =>
api.get('/marketplace/suppliers', { params }),
getSupplier: (id: string) => api.get(`/marketplace/suppliers/${id}`),
getSupplierProducts: (id: string, params?: { category?: string; search?: string }) =>
api.get(`/marketplace/suppliers/${id}/products`, { params }),
getSupplierReviews: (id: string, params?: { limit?: number }) =>
api.get(`/marketplace/suppliers/${id}/reviews`, { params }),
// Orders
createOrder: (data: any) => api.post('/marketplace/orders', data),
getOrders: (params?: { status?: string; supplierId?: string; limit?: number }) =>
api.get('/marketplace/orders', { params }),
getOrder: (id: string) => api.get(`/marketplace/orders/${id}`),
cancelOrder: (id: string, reason: string) =>
api.put(`/marketplace/orders/${id}/cancel`, { reason }),
// Reviews
createReview: (data: any) => api.post('/marketplace/reviews', data),
// Favorites
getFavorites: () => api.get('/marketplace/favorites'),
addFavorite: (supplierId: string) => api.post(`/marketplace/favorites/${supplierId}`),
removeFavorite: (supplierId: string) => api.delete(`/marketplace/favorites/${supplierId}`),
// Stats
getStats: () => api.get('/marketplace/stats'),
};