ente_nazionale_frontend/lib/api.ts
Linas 5c50f28f7e Add Modelli (templates) admin section
New /dashboard/templates page (MANAGER/ADMIN, matches backend access):
lists document templates, lets MANAGER/ADMIN download the current
file and ADMIN replace it. Nav link added to the header. Also renamed
"Genera Attestato" to "Genera Certificato di Adesione" and the
downloaded file's name prefix to match, for consistency with the
document's real name.

Verified live: nav link navigates to the page, download round-trips
the file, and uploading a new file updates the listed filename and
timestamp immediately.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017hQcuUQFue2bFvrYw2UQhK
2026-08-24 19:22:18 +03:00

242 lines
6.2 KiB
TypeScript

const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL ?? 'http://localhost:8080/api';
import { LoginResponse, User, Association, DocumentTemplate } from "./models";
// Store token in localStorage (we'll improve this later)
export function setAuthToken(token: string) {
localStorage.setItem('auth_token', token);
}
export function getAuthToken(): string | null {
return localStorage.getItem('auth_token');
}
export function removeAuthToken() {
localStorage.removeItem('auth_token');
}
// Helper to add Authorization header
function getHeaders(): HeadersInit {
const headers: HeadersInit = {
'Content-Type': 'application/json',
};
const token = getAuthToken();
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
return headers;
}
export async function login(email: string, password: string): Promise<LoginResponse> {
const response = await fetch(`${API_BASE_URL}/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password }),
});
if (!response.ok) {
throw new Error('Invalid credentials');
}
const data: LoginResponse = await response.json();
setAuthToken(data.token); // Store token
return data;
}
export async function getAssociation(id: string): Promise<Association> {
const response = await fetch(`${API_BASE_URL}/associations/${id}`, {
headers: getHeaders(),
});
if (!response.ok) {
if (response.status === 401 || response.status === 403) {
removeAuthToken();
throw new Error('Unauthorized');
}
throw new Error('Failed to fetch association');
}
return response.json();
}
export async function getAssociations(): Promise<Association[]> {
const response = await fetch(`${API_BASE_URL}/associations`, {
headers: getHeaders(),
});
if (!response.ok) {
if (response.status === 401 || response.status === 403) {
removeAuthToken();
throw new Error('Unauthorized');
}
throw new Error('Failed to fetch associations');
}
return response.json();
}
export async function createAssociation(association: Omit<Association, 'id' | 'created' | 'translit'>): Promise<Association> {
const response = await fetch(`${API_BASE_URL}/associations`, {
method: 'POST',
headers: getHeaders(),
body: JSON.stringify(association),
});
if (!response.ok) {
throw new Error('Failed to create association');
}
return response.json();
}
export async function updateAssociation(id: string, association: Association): Promise<Association> {
const response = await fetch(`${API_BASE_URL}/associations/${id}`, {
method: 'PUT',
headers: getHeaders(),
body: JSON.stringify(association),
});
if (!response.ok) {
if (response.status === 401 || response.status === 403) {
removeAuthToken();
throw new Error('Unauthorized');
}
throw new Error('Failed to update association');
}
return response.json();
}
export async function downloadAttestato(id: string, associationName: string): Promise<void> {
const response = await fetch(`${API_BASE_URL}/associations/${id}/attestato`, {
headers: getHeaders(),
});
if (!response.ok) {
if (response.status === 401 || response.status === 403) {
removeAuthToken();
throw new Error('Unauthorized');
}
throw new Error('Failed to generate attestato');
}
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = `certificato-di-adesione-${associationName}.pdf`;
document.body.appendChild(link);
link.click();
link.remove();
window.URL.revokeObjectURL(url);
}
export async function deleteAssociation(id: string): Promise<void> {
const response = await fetch(`${API_BASE_URL}/associations/${id}`, {
method: 'DELETE',
headers: getHeaders(),
});
if (!response.ok) {
if (response.status === 401 || response.status === 403) {
removeAuthToken();
throw new Error('Unauthorized');
}
throw new Error('Failed to delete association');
}
}
export async function getTemplates(): Promise<DocumentTemplate[]> {
const response = await fetch(`${API_BASE_URL}/templates`, {
headers: getHeaders(),
});
if (!response.ok) {
if (response.status === 401 || response.status === 403) {
removeAuthToken();
throw new Error('Unauthorized');
}
throw new Error('Failed to fetch templates');
}
return response.json();
}
export async function downloadTemplate(key: string, fileName: string): Promise<void> {
const response = await fetch(`${API_BASE_URL}/templates/${key}/download`, {
headers: getHeaders(),
});
if (!response.ok) {
if (response.status === 401 || response.status === 403) {
removeAuthToken();
throw new Error('Unauthorized');
}
throw new Error('Failed to download template');
}
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = fileName;
document.body.appendChild(link);
link.click();
link.remove();
window.URL.revokeObjectURL(url);
}
export async function uploadTemplate(key: string, file: File): Promise<DocumentTemplate> {
const formData = new FormData();
formData.append('file', file);
const token = getAuthToken();
const headers: HeadersInit = {};
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
const response = await fetch(`${API_BASE_URL}/templates/${key}`, {
method: 'POST',
headers,
body: formData,
});
if (!response.ok) {
if (response.status === 401 || response.status === 403) {
removeAuthToken();
throw new Error('Unauthorized');
}
throw new Error('Failed to upload template');
}
return response.json();
}
export function logout() {
removeAuthToken();
}
export async function verifyToken(): Promise<boolean> {
try {
const token = getAuthToken();
if (!token) return false;
const response = await fetch(`${API_BASE_URL}/associations`, {
headers: getHeaders(),
});
if (response.status === 401 || response.status === 403) {
removeAuthToken();
return false;
}
return response.ok;
} catch (error) {
console.error("verifyToken error:", error);
return false;
}
}