json_server_myapps/frontend/app.js
2026-01-27 12:51:43 +01:00

273 lines
7.6 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
login,
register,
getLinks,
createLink,
deleteLink,
updateLink
} from "./api.js";
const URL_SVR = "http://192.168.1.4:11001";
let token = null;
let autoIconURL = null;
let editingId = null;
// ===============================
// MOSTRA DIMENSIONI IMMAGINE
// ===============================
function showImageSize(imgElement, sizeElement) {
const img = new Image();
img.onload = () => {
sizeElement.textContent = `${img.width} × ${img.height} px`;
sizeElement.style.display = "block";
};
img.src = imgElement.src;
}
// ===============================
// AUTH
// ===============================
function setToken(t) {
token = t;
document.getElementById("authSection").style.display = token ? "none" : "block";
document.getElementById("linkSection").style.display = token ? "block" : "none";
if (token) loadLinks();
}
document.getElementById("loginForm").addEventListener("submit", async e => {
e.preventDefault();
try {
const t = await login(e.target.email.value, e.target.password.value);
setToken(t);
} catch (err) {
document.getElementById("authStatus").textContent = err.message;
}
});
document.getElementById("registerForm").addEventListener("submit", async e => {
e.preventDefault();
try {
await register(e.target.email.value, e.target.password.value);
document.getElementById("authStatus").textContent = "Registrato! Ora accedi.";
} catch (err) {
document.getElementById("authStatus").textContent = err.message;
}
});
// ===============================
// LOAD LINKS
// ===============================
/*async function loadLinks() {
const links = await getLinks(token);
const list = document.getElementById("list");
list.innerHTML = links
.map(
link => `
<div class="item" data-id="${link._id}">
${link.icon ? `<img src="${URL_SVR}${link.icon}">` : ""}
<div class="info">
<strong>${link.name}</strong><br>
<a href="${link.url}" target="_blank">${link.url}</a>
</div>
<div class="actions">
<button class="editBtn" data-id="${link._id}">Modifica</button>
<button class="deleteBtn" data-id="${link._id}">Elimina</button>
</div>
</div>
`
)
.join("");
}*/
async function loadLinks() {
const links = await getLinks(token);
// alert(links);
const list = document.getElementById("list");
list.innerHTML = links
.map(link => {
let iconHtml = "";
if (link.icon && link.icon.data && link.icon.mime) {
const base64 = btoa(
String.fromCharCode(...link.icon.data.data)
);
iconHtml = `<img src="data:${link.icon.mime};base64,${base64}" />`;
}
return `
<div class="item" data-id="${link._id}">
${iconHtml}
<div class="info">
<strong>${link.name}</strong><br>
<a href="${link.url}" target="_blank">${link.url}</a>
</div>
<div class="actions">
<button class="editBtn" data-id="${link._id}">Edit</button>
<button class="deleteBtn" data-id="${link._id}">Delete</button>
</div>
</div>
`;
})
.join("");
/*
list.innerHTML = links
.map(link => `
<div class="item" data-id="${link._id}">
${link.icon ? `<img src="${URL_SVR}/links/icon/${link._id}" class="icon">` : ""}
<div class="info">
<strong>${link.name}</strong><br>
<a href="${link.url}" target="_blank">${link.url}</a>
</div>
<div class="actions">
<button class="editBtn" data-id="${link._id}">✏️</button>
<button class="deleteBtn" data-id="${link._id}">🗑️</button>
</div>
</div>
`)
.join("");*/
}
// ===============================
// METADATA (icona automatica)
// ===============================
document.getElementById("fetchMetaBtn").addEventListener("click", async () => {
const url = document.getElementById("urlInput").value.trim();
if (!url) return;
const res = await fetch(`${URL_SVR}/metadata?url=${encodeURIComponent(url)}`);
const data = await res.json();
document.getElementById("nameInput").value = data.name || "";
autoIconURL = data.icon || null;
// Licona automatica è lultima scelta → reset input manuale
const fileInput = document.getElementById("iconInput");
fileInput.value = "";
const preview = document.getElementById("iconPreview");
const sizeBox = document.getElementById("iconSize");
if (autoIconURL) {
preview.src = autoIconURL;
preview.style.display = "block";
sizeBox.style.display = "none";
showImageSize(preview, sizeBox);
}
});
// ===============================
// ANTEPRIMA ICONA MANUALE
// ===============================
document.getElementById("iconInput").addEventListener("change", e => {
const file = e.target.files[0];
if (!file) return;
autoIconURL = null; // manuale vince
const preview = document.getElementById("iconPreview");
const sizeBox = document.getElementById("iconSize");
preview.src = URL.createObjectURL(file);
preview.style.display = "block";
sizeBox.style.display = "none";
showImageSize(preview, sizeBox);
});
// ===============================
// CREAZIONE LINK
// ===============================
document.getElementById("linkForm").addEventListener("submit", async e => {
e.preventDefault();
const raw = new FormData(e.target);
const manualFile = raw.get("icon");
const hasManualFile = manualFile instanceof File && manualFile.size > 0;
await createLink(token, {
name: raw.get("name"),
url: raw.get("url"),
iconFile: hasManualFile ? manualFile : null,
iconURL: !hasManualFile ? autoIconURL : null
});
autoIconURL = null;
document.getElementById("iconPreview").style.display = "none";
document.getElementById("iconSize").style.display = "none";
e.target.reset();
loadLinks();
});
// ===============================
// EDIT
// ===============================
document.getElementById("list").addEventListener("click", e => {
const id = e.target.dataset.id;
if (!id) return;
if (e.target.classList.contains("deleteBtn")) {
deleteLink(token, id).then(loadLinks);
return;
}
if (e.target.classList.contains("editBtn")) {
editingId = id;
const item = e.target.closest(".item");
const name = item.querySelector("strong").textContent;
const url = item.querySelector("a").textContent;
const form = document.getElementById("editForm");
form.name.value = name;
form.url.value = url;
document.getElementById("iconPreviewEdit").style.display = "none";
document.getElementById("iconSizeEdit").style.display = "none";
document.getElementById("editModal").style.display = "flex";
}
});
// ANTEPRIMA MANUALE IN EDIT
document.getElementById("iconInputEdit").addEventListener("change", e => {
const file = e.target.files[0];
if (!file) return;
const preview = document.getElementById("iconPreviewEdit");
const sizeBox = document.getElementById("iconSizeEdit");
preview.src = URL.createObjectURL(file);
preview.style.display = "block";
sizeBox.style.display = "none";
showImageSize(preview, sizeBox);
});
// SALVA EDIT
document.getElementById("editForm").addEventListener("submit", async e => {
e.preventDefault();
const name = e.target.name.value;
const url = e.target.url.value;
const iconFile = e.target.icon.files[0] || null;
await updateLink(token, editingId, {
name,
url,
iconFile,
iconURL: null
});
document.getElementById("editModal").style.display = "none";
loadLinks();
});
document.getElementById("closeModal").addEventListener("click", () => {
document.getElementById("editModal").style.display = "none";
});
setToken(null);