Primera version de frontend
This commit is contained in:
25
src/api/auth.js
Normal file
25
src/api/auth.js
Normal file
@@ -0,0 +1,25 @@
|
||||
const API_URL = import.meta.env.VITE_EFC_API_URL;
|
||||
|
||||
export async function login(username, password) {
|
||||
const response = await fetch(`${API_URL}/token/`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ username, password }),
|
||||
});
|
||||
|
||||
console.log('API URL:', `${API_URL}/token/`);
|
||||
if (!response.ok) {
|
||||
throw new Error('Credenciales inválidas');
|
||||
}
|
||||
return response.json(); // { access, refresh }
|
||||
}
|
||||
|
||||
export async function refreshToken(refresh) {
|
||||
const res = await fetch(`${API_URL}/token/refresh/`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ refresh }),
|
||||
});
|
||||
if (!res.ok) throw new Error('SESSION_EXPIRED');
|
||||
return res.json(); // { access: '...' }
|
||||
}
|
||||
60
src/api/documentos.ts
Normal file
60
src/api/documentos.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
// src/api/pedimentoDocuments.ts
|
||||
|
||||
export interface PedimentoDocument {
|
||||
id: string;
|
||||
organizacion: string;
|
||||
pedimento: string;
|
||||
pedimento_numero:string;
|
||||
archivo: string;
|
||||
document_type: number;
|
||||
size: number;
|
||||
extension: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export interface PedimentoDocumentsResponse {
|
||||
count: number;
|
||||
next: string | null;
|
||||
previous: string | null;
|
||||
results: PedimentoDocument[];
|
||||
}
|
||||
|
||||
const API_URL = import.meta.env.VITE_EFC_API_URL;
|
||||
|
||||
export async function fetchPedimentoDocuments(
|
||||
token: string,
|
||||
pedimentoId: string = '',
|
||||
page: number = 1,
|
||||
pageSize: number = 10,
|
||||
filters: {
|
||||
pedimento_numero?: string;
|
||||
extension?: string;
|
||||
document_type?: string | number;
|
||||
created_at?: string;
|
||||
} = {}
|
||||
): Promise<PedimentoDocumentsResponse> {
|
||||
const params = new URLSearchParams();
|
||||
params.append('page', String(page));
|
||||
params.append('page_size', String(pageSize));
|
||||
if (pedimentoId) params.append('pedimento', pedimentoId);
|
||||
if (filters.pedimento_numero) params.append('pedimento_numero', filters.pedimento_numero);
|
||||
if (filters.extension) params.append('extension', filters.extension);
|
||||
if (filters.document_type) params.append('document_type', String(filters.document_type));
|
||||
if (filters.created_at) params.append('created_at', filters.created_at);
|
||||
|
||||
const res = await fetch(
|
||||
`${API_URL}/record/documents/?${params.toString()}`,
|
||||
{
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
);
|
||||
if (res.status === 401) {
|
||||
throw new Error('SESSION_EXPIRED');
|
||||
}
|
||||
if (!res.ok) throw new Error('No autorizado o error en la petición');
|
||||
return res.json();
|
||||
}
|
||||
102
src/api/documents.js
Normal file
102
src/api/documents.js
Normal file
@@ -0,0 +1,102 @@
|
||||
|
||||
/**
|
||||
* @typedef {Object} Document
|
||||
* @property {string} id
|
||||
* @property {string} organizacion
|
||||
* @property {string} pedimento
|
||||
* @property {string} archivo
|
||||
* @property {number} document_type
|
||||
* @property {number} size
|
||||
* @property {string} extension
|
||||
* @property {string} created_at
|
||||
* @property {string} updated_at
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} DocumentsResponse
|
||||
* @property {number} count
|
||||
* @property {string|null} next
|
||||
* @property {string|null} previous
|
||||
* @property {Document[]} results
|
||||
*/
|
||||
|
||||
import { refreshToken } from './auth';
|
||||
|
||||
const API_URL = import.meta.env.VITE_EFC_API_URL;
|
||||
/**
|
||||
* Obtiene la lista de documentos (pedimentos)
|
||||
* @param {string} token
|
||||
* @returns {Promise<DocumentsResponse>}
|
||||
*/
|
||||
export async function fetchDocuments(token, queryString = '') {
|
||||
let url = `${API_URL}/customs/pedimentos/`;
|
||||
if (queryString) {
|
||||
url += `?${queryString}`;
|
||||
}
|
||||
let res = await fetch(url, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
if (res.status === 401) {
|
||||
// Intentar refrescar el token
|
||||
const refresh = localStorage.getItem('refresh');
|
||||
if (refresh) {
|
||||
try {
|
||||
const data = await refreshToken(refresh);
|
||||
localStorage.setItem('access', data.access);
|
||||
// Reintenta la petición con el nuevo access token
|
||||
res = await fetch(`${API_URL}/customs/pedimentos/`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${data.access}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
throw new Error('SESSION_EXPIRED');
|
||||
}
|
||||
} else {
|
||||
throw new Error('SESSION_EXPIRED');
|
||||
}
|
||||
}
|
||||
if (!res.ok) throw new Error('No autorizado o error en la petición');
|
||||
return res.json(); // Tipado por JSDoc: Promise<DocumentsResponse>
|
||||
}
|
||||
/**
|
||||
* Obtiene los documentos por id de pedimento
|
||||
* @param {string} token
|
||||
* @param {string} id
|
||||
* @returns {Promise<DocumentsResponse>}
|
||||
*/
|
||||
export async function fetchDocumentById(token, id) {
|
||||
let res = await fetch(`${API_URL}/record/documents/?page=1&page_size=10&pedimento=${id}/`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
if (res.status === 401) {
|
||||
// Intentar refrescar el token
|
||||
const refresh = localStorage.getItem('refresh');
|
||||
if (refresh) {
|
||||
try {
|
||||
const data = await refreshToken(refresh);
|
||||
localStorage.setItem('access', data.access);
|
||||
// Reintenta la petición con el nuevo access token
|
||||
res = await fetch(`${API_URL}/record/documents/?page=1&page_size=10&pedimento=${id}/`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${data.access}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
throw new Error('SESSION_EXPIRED');
|
||||
}
|
||||
} else {
|
||||
throw new Error('SESSION_EXPIRED');
|
||||
}
|
||||
}
|
||||
if (!res.ok) throw new Error('No autorizado o error en la petición');
|
||||
return res.json(); // Tipado por JSDoc: Promise<DocumentsResponse>
|
||||
}
|
||||
0
src/api/documents.ts
Normal file
0
src/api/documents.ts
Normal file
115
src/api/expedientes.ts
Normal file
115
src/api/expedientes.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
|
||||
|
||||
export interface Document {
|
||||
id: string;
|
||||
organizacion: string;
|
||||
pedimento: string;
|
||||
archivo: string;
|
||||
document_type: number;
|
||||
size: number;
|
||||
extension: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export interface DocumentsResponse {
|
||||
count: number;
|
||||
next: string | null;
|
||||
previous: string | null;
|
||||
results: Document[];
|
||||
}
|
||||
|
||||
import { refreshToken } from './auth';
|
||||
|
||||
const API_URL = import.meta.env.VITE_EFC_API_URL;
|
||||
// Obtiene la lista de documentos (pedimentos)
|
||||
export interface PedimentosFilters {
|
||||
search?: string;
|
||||
pedimento?: string;
|
||||
existe_expediente?: string | boolean;
|
||||
alerta?: string | boolean;
|
||||
contribuyente?: string;
|
||||
curp_apoderado?: string;
|
||||
fecha_pago?: string;
|
||||
patente?: string;
|
||||
aduana?: string;
|
||||
tipo_operacion?: string;
|
||||
clave_pedimento?: string;
|
||||
}
|
||||
|
||||
export async function fetchDocuments(
|
||||
token: string,
|
||||
page: number = 1,
|
||||
pageSize: number = 10,
|
||||
filters: PedimentosFilters = {}
|
||||
): Promise<DocumentsResponse> {
|
||||
const params = new URLSearchParams();
|
||||
params.append('page', String(page));
|
||||
params.append('page_size', String(pageSize));
|
||||
Object.entries(filters).forEach(([key, value]) => {
|
||||
if (value !== undefined && value !== null && value !== '') {
|
||||
params.append(key, String(value));
|
||||
}
|
||||
});
|
||||
let res = await fetch(`${API_URL}/customs/pedimentos/?${params.toString()}`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
if (res.status === 401) {
|
||||
// Intentar refrescar el token
|
||||
const refresh = localStorage.getItem('refresh');
|
||||
if (refresh) {
|
||||
try {
|
||||
const data = await refreshToken(refresh);
|
||||
localStorage.setItem('access', data.access);
|
||||
// Reintenta la petición con el nuevo access token
|
||||
res = await fetch(`${API_URL}/customs/pedimentos/?page=${page}&page_size=${pageSize}`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${data.access}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
throw new Error('SESSION_EXPIRED');
|
||||
}
|
||||
} else {
|
||||
throw new Error('SESSION_EXPIRED');
|
||||
}
|
||||
}
|
||||
if (!res.ok) throw new Error('No autorizado o error en la petición');
|
||||
return res.json();
|
||||
}
|
||||
// Obtiene los documentos por id de pedimento
|
||||
export async function fetchDocumentById(token: string, id: string): Promise<DocumentsResponse> {
|
||||
let res = await fetch(`${API_URL}/record/documents/?page=1&page_size=10&pedimento=${id}/`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
if (res.status === 401) {
|
||||
// Intentar refrescar el token
|
||||
const refresh = localStorage.getItem('refresh');
|
||||
if (refresh) {
|
||||
try {
|
||||
const data = await refreshToken(refresh);
|
||||
localStorage.setItem('access', data.access);
|
||||
// Reintenta la petición con el nuevo access token
|
||||
res = await fetch(`${API_URL}/record/documents/?page=1&page_size=10&pedimento=${id}/`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${data.access}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
throw new Error('SESSION_EXPIRED');
|
||||
}
|
||||
} else {
|
||||
throw new Error('SESSION_EXPIRED');
|
||||
}
|
||||
}
|
||||
if (!res.ok) throw new Error('No autorizado o error en la petición');
|
||||
return res.json();
|
||||
}
|
||||
68
src/api/notificaciones.ts
Normal file
68
src/api/notificaciones.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
// PUT para marcar una notificación como vista
|
||||
export async function marcarNotificacionComoVista(id: number): Promise<Notificacion> {
|
||||
const token = localStorage.getItem('access');
|
||||
const url = `${API_URL}/notificaciones/notificaciones/${id}/`;
|
||||
const headers = new Headers();
|
||||
if (token) headers.append('Authorization', `Bearer ${token}`);
|
||||
headers.append('Content-Type', 'application/json');
|
||||
const res = await fetch(url, {
|
||||
method: 'PUT',
|
||||
headers,
|
||||
body: JSON.stringify({ visto: true })
|
||||
});
|
||||
if (!res.ok) throw new Error('Error al actualizar notificación');
|
||||
return await res.json();
|
||||
}
|
||||
// src/api/notificaciones.ts
|
||||
|
||||
export interface TipoNotificacion {
|
||||
id: number;
|
||||
tipo: string;
|
||||
descripcion: string;
|
||||
}
|
||||
|
||||
export interface Notificacion {
|
||||
id: number;
|
||||
tipo: TipoNotificacion;
|
||||
dirigido: string;
|
||||
mensaje: string;
|
||||
fecha_envio: string;
|
||||
created_at: string;
|
||||
visto: boolean;
|
||||
}
|
||||
|
||||
export interface NotificacionesResponse {
|
||||
count: number;
|
||||
next: string | null;
|
||||
previous: string | null;
|
||||
results: Notificacion[];
|
||||
}
|
||||
|
||||
const API_URL = import.meta.env.VITE_EFC_API_URL;
|
||||
|
||||
export async function fetchNotificaciones({ page = 1, pageSize = 10, visto = false } = {}): Promise<NotificacionesResponse> {
|
||||
const token = localStorage.getItem('access');
|
||||
const url = `${API_URL}/notificaciones/notificaciones/?page=${page}&page_size=${pageSize}&visto=${visto}`;
|
||||
const headers = new Headers();
|
||||
if (token) headers.append('Authorization', `Bearer ${token}`);
|
||||
headers.append('Content-Type', 'application/json');
|
||||
const res = await fetch(url, {
|
||||
headers,
|
||||
});
|
||||
if (!res.ok) throw new Error('Error al obtener notificaciones');
|
||||
return await res.json();
|
||||
}
|
||||
|
||||
|
||||
export async function fetchAllNotifications({page = 1, page_size=10}): Promise<NotificacionesResponse>{
|
||||
const token = localStorage.getItem('access');
|
||||
const url = `${API_URL}/notificaciones/notificaciones/?page=${page}&page_size=${page_size}`;
|
||||
const headers = new Headers();
|
||||
if (token) headers.append('Authorization', `Bearer ${token}`);
|
||||
headers.append('Content-Type', 'application/json');
|
||||
const res = await fetch(url, {
|
||||
headers,
|
||||
});
|
||||
if (!res.ok) throw new Error('Error al obtener notificaciones');
|
||||
return await res.json();
|
||||
}
|
||||
36
src/api/organizacion.js
Normal file
36
src/api/organizacion.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import { refreshToken } from './auth';
|
||||
|
||||
const API_URL = import.meta.env.VITE_EFC_API_URL;
|
||||
|
||||
export async function fetchOrganizationUsage(token) {
|
||||
let res = await fetch(`${API_URL}/organization/uso-almacenamiento/mi_organizacion/`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
if (res.status === 401) {
|
||||
// Intentar refrescar el token
|
||||
const refresh = localStorage.getItem('refresh');
|
||||
if (refresh) {
|
||||
try {
|
||||
const data = await refreshToken(refresh);
|
||||
localStorage.setItem('access', data.access);
|
||||
// Reintenta la petición con el nuevo access token
|
||||
res = await fetch(`${API_URL}/organization/uso-almacenamiento/mi_organizacion/`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${data.access}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
if (res.status === 401) throw new Error('SESSION_EXPIRED');
|
||||
} catch (err) {
|
||||
throw new Error('SESSION_EXPIRED');
|
||||
}
|
||||
} else {
|
||||
throw new Error('SESSION_EXPIRED');
|
||||
}
|
||||
}
|
||||
if (!res.ok) throw new Error('No autorizado o error en la petición');
|
||||
return res.json();
|
||||
}
|
||||
33
src/api/organization.ts
Normal file
33
src/api/organization.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
// organization.ts
|
||||
// Tipos para la respuesta del endpoint de uso de almacenamiento de organización
|
||||
|
||||
export interface OrganizationUsage {
|
||||
organizacion: string;
|
||||
limite_almacenamiento_gb: number;
|
||||
espacio_utilizado_bytes: number;
|
||||
espacio_utilizado_gb: number;
|
||||
espacio_disponible_bytes: number;
|
||||
porcentaje_utilizado: number;
|
||||
total_documentos: number;
|
||||
total_pedimentos: number;
|
||||
total_usuarios: number;
|
||||
}
|
||||
|
||||
const API_URL = import.meta.env.VITE_EFC_API_URL;
|
||||
|
||||
// Ejemplo de función para obtener la información tipada
|
||||
export async function fetchOrganizationUsage(token: string): Promise<OrganizationUsage> {
|
||||
const res = await fetch(`${API_URL}/organization/uso-almacenamiento/mi_organizacion/`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
if (res.status === 401) {
|
||||
throw new Error('SESSION_EXPIRED');
|
||||
}
|
||||
if (!res.ok) {
|
||||
throw new Error('Error al obtener información de la organización');
|
||||
}
|
||||
return res.json();
|
||||
}
|
||||
44
src/api/pedimentoDocuments.ts
Normal file
44
src/api/pedimentoDocuments.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
// src/api/pedimentoDocuments.ts
|
||||
|
||||
export interface PedimentoDocument {
|
||||
id: string;
|
||||
organizacion: string;
|
||||
pedimento: string;
|
||||
archivo: string;
|
||||
document_type: number;
|
||||
size: number;
|
||||
extension: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export interface PedimentoDocumentsResponse {
|
||||
count: number;
|
||||
next: string | null;
|
||||
previous: string | null;
|
||||
results: PedimentoDocument[];
|
||||
}
|
||||
|
||||
const API_URL = import.meta.env.VITE_EFC_API_URL;
|
||||
|
||||
export async function fetchPedimentoDocuments(
|
||||
token: string,
|
||||
pedimentoId: string,
|
||||
page: number = 1,
|
||||
pageSize: number = 10
|
||||
): Promise<PedimentoDocumentsResponse> {
|
||||
const res = await fetch(
|
||||
`${API_URL}/record/documents/?page=${page}&page_size=${pageSize}&pedimento=${pedimentoId}`,
|
||||
{
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
);
|
||||
if (res.status === 401) {
|
||||
throw new Error('SESSION_EXPIRED');
|
||||
}
|
||||
if (!res.ok) throw new Error('No autorizado o error en la petición');
|
||||
return res.json();
|
||||
}
|
||||
33
src/api/procesos.ts
Normal file
33
src/api/procesos.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
// Tipos para la respuesta y registros
|
||||
export interface ProcesamientoPedimento {
|
||||
id: number;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
organizacion: string;
|
||||
organizacion_name: string;
|
||||
estado: number;
|
||||
tipo_procesamiento: number;
|
||||
pedimento: string;
|
||||
servicio: number;
|
||||
}
|
||||
|
||||
export interface ProcesamientoPedimentosResponse {
|
||||
count: number;
|
||||
next: string | null;
|
||||
previous: string | null;
|
||||
results: ProcesamientoPedimento[];
|
||||
}
|
||||
|
||||
// API para customs/procesamientopedimentos/
|
||||
export async function fetchProcesamientoPedimentos(
|
||||
token: string | null,
|
||||
page: number = 1,
|
||||
pageSize: number = 20
|
||||
): Promise<ProcesamientoPedimentosResponse> {
|
||||
const API_URL = import.meta.env.VITE_EFC_API_URL;
|
||||
const headers: Record<string, string> = {};
|
||||
if (token) headers['Authorization'] = `Bearer ${token}`;
|
||||
const res = await fetch(`${API_URL}/customs/procesamientopedimentos/?page=${page}&page_size=${pageSize}`, { headers });
|
||||
if (!res.ok) throw new Error('Error al obtener procesamiento de pedimentos');
|
||||
return await res.json();
|
||||
}
|
||||
83
src/api/users.js
Normal file
83
src/api/users.js
Normal file
@@ -0,0 +1,83 @@
|
||||
const API_URL = import.meta.env.VITE_EFC_API_URL || 'http://localhost:8000';
|
||||
|
||||
async function handleResponse(response, operation = 'operación') {
|
||||
if (response.status === 401) {
|
||||
throw new Error('SESSION_EXPIRED');
|
||||
}
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
throw new Error(`Error ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
const contentType = response.headers.get('content-type');
|
||||
if (!contentType || !contentType.includes('application/json')) {
|
||||
throw new Error('El servidor no devolvió JSON válido');
|
||||
}
|
||||
return response.json();
|
||||
}
|
||||
|
||||
export async function fetchUsers(token) {
|
||||
const url = `${API_URL}/user/users/`;
|
||||
const res = await fetch(url, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
});
|
||||
return handleResponse(res, 'Fetch Users');
|
||||
}
|
||||
|
||||
export async function createUser(token, userData) {
|
||||
const url = `${API_URL}/user/users/`;
|
||||
const res = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(userData),
|
||||
});
|
||||
return handleResponse(res, 'Create User');
|
||||
}
|
||||
|
||||
export async function updateUser(token, id, userData) {
|
||||
const url = `${API_URL}/user/users/${id}/`;
|
||||
const res = await fetch(url, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(userData),
|
||||
});
|
||||
return handleResponse(res, 'Update User');
|
||||
}
|
||||
|
||||
export async function deleteUser(token, id) {
|
||||
const url = `${API_URL}/user/users/${id}/`;
|
||||
const res = await fetch(url, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
});
|
||||
if (res.status === 401) throw new Error('SESSION_EXPIRED');
|
||||
if (!res.ok) throw new Error(`Error ${res.status}: ${res.statusText}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
export async function getCurrentUser(token) {
|
||||
const url = `${API_URL}/user/users/me/`;
|
||||
const res = await fetch(url, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
});
|
||||
return handleResponse(res, 'Get Current User');
|
||||
}
|
||||
172
src/api/users.ts
Normal file
172
src/api/users.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
const API_URL = import.meta.env.VITE_EFC_API_URL || 'http://localhost:8000';
|
||||
|
||||
// Función helper para manejar respuestas
|
||||
async function handleResponse(response, operation = 'operación') {
|
||||
console.log(`📡 ${operation} response:`, response.status, response.statusText);
|
||||
|
||||
if (response.status === 401) {
|
||||
console.error('❌ Unauthorized - session expired');
|
||||
throw new Error('SESSION_EXPIRED');
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
console.error(`❌ ${operation} error:`, response.status, errorText);
|
||||
throw new Error(`Error ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
|
||||
// Verificar que la respuesta es JSON
|
||||
const contentType = response.headers.get('content-type');
|
||||
if (!contentType || !contentType.includes('application/json')) {
|
||||
const text = await response.text();
|
||||
console.error('❌ Response is not JSON:', text.substring(0, 200));
|
||||
throw new Error('El servidor no devolvió JSON válido');
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
export async function fetchUsers(token) {
|
||||
try {
|
||||
const url = `${API_URL}/user/users/`;
|
||||
console.log('👥 Fetching users from:', url);
|
||||
|
||||
const res = await fetch(url, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
const data = await handleResponse(res, 'Fetch Users');
|
||||
console.log('✅ Users data received');
|
||||
return data;
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error in fetchUsers:', error);
|
||||
if (error.name === 'TypeError' && error.message.includes('fetch')) {
|
||||
throw new Error('Error de conexión al servidor');
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function createUser(token, userData) {
|
||||
try {
|
||||
const url = `${API_URL}/user/users/`;
|
||||
console.log('➕ Creating user at:', url);
|
||||
|
||||
const res = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(userData),
|
||||
});
|
||||
|
||||
const data = await handleResponse(res, 'Create User');
|
||||
console.log('✅ User created successfully');
|
||||
return data;
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error in createUser:', error);
|
||||
if (error.name === 'TypeError' && error.message.includes('fetch')) {
|
||||
throw new Error('Error de conexión al servidor');
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateUser(token, id, userData) {
|
||||
try {
|
||||
const url = `${API_URL}/user/users/${id}/`;
|
||||
console.log('✏️ Updating user at:', url);
|
||||
|
||||
const res = await fetch(url, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(userData),
|
||||
});
|
||||
|
||||
const data = await handleResponse(res, 'Update User');
|
||||
console.log('✅ User updated successfully');
|
||||
return data;
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error in updateUser:', error);
|
||||
if (error.name === 'TypeError' && error.message.includes('fetch')) {
|
||||
throw new Error('Error de conexión al servidor');
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteUser(token, id) {
|
||||
try {
|
||||
const url = `${API_URL}/user/users/${id}/`;
|
||||
console.log('🗑️ Deleting user at:', url);
|
||||
|
||||
const res = await fetch(url, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
if (res.status === 401) {
|
||||
console.error('❌ Unauthorized - session expired');
|
||||
throw new Error('SESSION_EXPIRED');
|
||||
}
|
||||
|
||||
if (!res.ok) {
|
||||
const errorText = await res.text();
|
||||
console.error('❌ Delete User error:', res.status, errorText);
|
||||
throw new Error(`Error ${res.status}: ${res.statusText}`);
|
||||
}
|
||||
|
||||
console.log('✅ User deleted successfully');
|
||||
return true; // DELETE suele no devolver contenido
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error in deleteUser:', error);
|
||||
if (error.name === 'TypeError' && error.message.includes('fetch')) {
|
||||
throw new Error('Error de conexión al servidor');
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getCurrentUser(token) {
|
||||
try {
|
||||
const url = `${API_URL}/user/users/me/`;
|
||||
console.log('👤 Fetching current user from:', url);
|
||||
|
||||
const res = await fetch(url, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
const data = await handleResponse(res, 'Get Current User');
|
||||
console.log('✅ Current user data received:', data);
|
||||
return data;
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error in getCurrentUser:', error);
|
||||
if (error.name === 'TypeError' && error.message.includes('fetch')) {
|
||||
throw new Error('Error de conexión al servidor');
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user