Files

136 lines
5.8 KiB
TypeScript

import Cookies from 'js-cookie';
const API_BASE = '/api';
interface FetchOptions extends RequestInit {
skipAuth?: boolean;
}
async function fetchApi(url: string, options: FetchOptions = {}) {
const { skipAuth, ...fetchOpts } = options;
const headers: Record<string, string> = {
'Content-Type': 'application/json',
...(fetchOpts.headers as Record<string, string>),
};
if (!skipAuth) {
const token = Cookies.get('accessToken');
if (token) headers['Authorization'] = `Bearer ${token}`;
}
const res = await fetch(`${API_BASE}${url}`, { ...fetchOpts, headers });
if (res.status === 401) {
const data = await res.json().catch(() => ({}));
if (data.code === 'TOKEN_EXPIRED') {
const refreshed = await refreshToken();
if (refreshed) {
headers['Authorization'] = `Bearer ${Cookies.get('accessToken')}`;
const retry = await fetch(`${API_BASE}${url}`, { ...fetchOpts, headers });
return retry.json();
}
}
if (typeof window !== 'undefined') {
Cookies.remove('accessToken');
Cookies.remove('refreshToken');
window.location.href = '/login';
}
throw new Error('Não autenticado');
}
if (!res.ok) {
const data = await res.json().catch(() => ({ error: 'Erro desconhecido' }));
throw new Error(data.error || 'Erro na requisição');
}
return res.json();
}
async function refreshToken(): Promise<boolean> {
try {
const rt = Cookies.get('refreshToken');
if (!rt) return false;
const res = await fetch(`${API_BASE}/auth/refresh`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ refreshToken: rt }),
});
if (!res.ok) return false;
const data = await res.json();
Cookies.set('accessToken', data.accessToken, { expires: 1 });
Cookies.set('refreshToken', data.refreshToken, { expires: 7 });
return true;
} catch { return false; }
}
export const api = {
// Auth
login: (email: string, password: string) =>
fetchApi('/auth/login', { method: 'POST', body: JSON.stringify({ email, password }), skipAuth: true }),
register: (data: any) =>
fetchApi('/auth/register', { method: 'POST', body: JSON.stringify(data), skipAuth: true }),
googleAuth: (data: any) =>
fetchApi('/auth/google', { method: 'POST', body: JSON.stringify(data), skipAuth: true }),
me: () => fetchApi('/auth/me'),
logout: () => fetchApi('/auth/logout', { method: 'POST' }),
// Users
getUsers: (params?: string) => fetchApi(`/users${params ? `?${params}` : ''}`),
getUser: (id: number) => fetchApi(`/users/${id}`),
updateUser: (id: number, data: any) => fetchApi(`/users/${id}`, { method: 'PUT', body: JSON.stringify(data) }),
deleteUser: (id: number) => fetchApi(`/users/${id}`, { method: 'DELETE' }),
getUserStats: () => fetchApi('/users/me/stats'),
getFavorites: () => fetchApi('/users/me/favorites'),
addFavorite: (benefitId: number) => fetchApi('/users/me/favorites', { method: 'POST', body: JSON.stringify({ benefitId }) }),
removeFavorite: (benefitId: number) => fetchApi(`/users/me/favorites/${benefitId}`, { method: 'DELETE' }),
getHistory: () => fetchApi('/users/me/history'),
// Partners
getPartners: (params?: string) => fetchApi(`/partners${params ? `?${params}` : ''}`),
getPartner: (id: number) => fetchApi(`/partners/${id}`),
getPartnerBySlug: (slug: string) => fetchApi(`/partners/slug/${slug}`),
createPartner: (data: any) => fetchApi('/partners', { method: 'POST', body: JSON.stringify(data) }),
updatePartner: (id: number, data: any) => fetchApi(`/partners/${id}`, { method: 'PUT', body: JSON.stringify(data) }),
deletePartner: (id: number) => fetchApi(`/partners/${id}`, { method: 'DELETE' }),
getPartnerStats: (id: number) => fetchApi(`/partners/${id}/stats`),
// Benefits
getBenefits: (params?: string) => fetchApi(`/benefits${params ? `?${params}` : ''}`),
getBenefit: (id: number) => fetchApi(`/benefits/${id}`),
createBenefit: (data: any) => fetchApi('/benefits', { method: 'POST', body: JSON.stringify(data) }),
updateBenefit: (id: number, data: any) => fetchApi(`/benefits/${id}`, { method: 'PUT', body: JSON.stringify(data) }),
deleteBenefit: (id: number) => fetchApi(`/benefits/${id}`, { method: 'DELETE' }),
approveBenefit: (id: number) => fetchApi(`/benefits/${id}/approve`, { method: 'POST' }),
redeemBenefit: (id: number) => fetchApi(`/benefits/${id}/redeem`, { method: 'POST' }),
getCategories: () => fetchApi('/benefits/categories'),
// Admin
getDashboard: () => fetchApi('/admin/dashboard'),
getAuditLogs: (params?: string) => fetchApi(`/admin/logs${params ? `?${params}` : ''}`),
getMetrics: (period?: string) => fetchApi(`/admin/metrics${period ? `?period=${period}` : ''}`),
// Plugins
getPlugins: () => fetchApi('/plugins'),
activatePlugin: (slug: string) => fetchApi(`/plugins/${slug}/activate`, { method: 'POST' }),
deactivatePlugin: (slug: string) => fetchApi(`/plugins/${slug}/deactivate`, { method: 'POST' }),
removePlugin: (slug: string) => fetchApi(`/plugins/${slug}`, { method: 'DELETE' }),
// Webhooks
getWebhooks: () => fetchApi('/webhooks'),
createWebhook: (data: any) => fetchApi('/webhooks', { method: 'POST', body: JSON.stringify(data) }),
};
export function setTokens(accessToken: string, refreshToken: string) {
Cookies.set('accessToken', accessToken, { expires: 1 });
Cookies.set('refreshToken', refreshToken, { expires: 7 });
}
export function clearTokens() {
Cookies.remove('accessToken');
Cookies.remove('refreshToken');
}
export function getAccessToken() {
return Cookies.get('accessToken');
}