Files
stl-repo/static/js/api.js
Consultoria AS 14b307110d feat: implementar 12 mejoras, tests, docs y optimizaciones
- Fase A: license templates, search history, cost estimator
- Fase B: import URL, bulk ZIP, batch download
- Fase C: comparison mode, mesh validation, measurement tool
- Fase D: cross-section clipping, overhang heatmap, layer animation
- Refactor Pydantic/SQLAlchemy warnings
- 24 tests pytest
- README actualizado
- WebP thumbnails, lazy loading, cache headers
2026-04-27 09:14:58 +00:00

60 lines
1.5 KiB
JavaScript

const API_BASE = '/api';
function showToast(message, type = 'info') {
const container = document.getElementById('toast-container');
if (!container) return;
const toast = document.createElement('div');
toast.className = `toast ${type}`;
toast.textContent = message;
container.appendChild(toast);
setTimeout(() => {
toast.style.opacity = '0';
toast.style.transform = 'translateX(20px)';
toast.style.transition = 'all 0.3s ease';
setTimeout(() => toast.remove(), 300);
}, 4000);
}
async function apiGet(path) {
const res = await fetch(API_BASE + path);
if (!res.ok) {
const text = await res.text();
throw new Error(text || `HTTP ${res.status}`);
}
return res.json();
}
async function apiDelete(path) {
const res = await fetch(API_BASE + path, { method: 'DELETE' });
if (!res.ok) {
const text = await res.text();
throw new Error(text || `HTTP ${res.status}`);
}
return res.json();
}
async function apiPostForm(path, formData) {
const res = await fetch(API_BASE + path, {
method: 'POST',
body: formData,
});
if (!res.ok) {
const text = await res.text();
throw new Error(text || `HTTP ${res.status}`);
}
return res.json();
}
async function apiPut(path, data) {
const res = await fetch(API_BASE + path, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
if (!res.ok) {
const text = await res.text();
throw new Error(text || `HTTP ${res.status}`);
}
return res.json();
}