This commit is contained in:
Fabio 2026-01-01 22:32:35 +01:00
parent dfaf542c4b
commit 045977f9fb
7 changed files with 933 additions and 762 deletions

6
.gitignore vendored
View file

@ -18,9 +18,9 @@ ios/
www/ www/
# Environment files # Environment files
.env #.env
.env.* #.env.*
!.env.example #!.env.example
# System files # System files
.DS_Store .DS_Store

1561
app/app.js

File diff suppressed because it is too large Load diff

View file

@ -14,6 +14,8 @@
<div id="setup-page" class="hidden"> <div id="setup-page" class="hidden">
<h2>Configurazione</h2> <h2>Configurazione</h2>
<button id="cfg-refresh">Aggiorna ora</button>
<label>URL</label> <label>URL</label>
<input id="cfg-url" type="text"> <input id="cfg-url" type="text">
@ -37,5 +39,10 @@
</div> </div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<script src="app.js"></script> <script src="app.js"></script>
<!-- --> <script src="https://cdn.jsdelivr.net/npm/eruda"></script>
<script>
eruda.init();
</script> <!-- -->
</body> </body>
</html> </html>

4
app/start.sh Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
# Avvia un server HTTP sulla porta 11002 senza cache
npx http-server . -c-1 -p 11002

View file

@ -254,3 +254,6 @@ html, body {
border: none; border: none;
} }
#cfg-refresh {
display: none;
}

16
server/backend/.env Normal file
View file

@ -0,0 +1,16 @@
# === SERVER CONFIG ===
PORT=11001
# === JWT CONFIG ===
# Cambialo SEMPRE in produzione
JWT_SECRET=master66
# === MONGO CONFIG ===
# In locale:
# MONGO_URI=mongodb://localhost:27017/mydb
#
# In Docker (usato dal docker-compose):
MONGO_URI=mongodb://root:example@192.168.1.3:27017/myapphttps?authSource=admin
# === UPLOADS ===
# Cartella dove Express serve le icone
UPLOAD_DIR=uploads

View file

@ -1,98 +0,0 @@
import {
login,
register,
getLinks,
createLink,
deleteLink,
updateLink
} from "./api.js";
const authSection = document.getElementById("authSection");
const linkSection = document.getElementById("linkSection");
const authStatus = document.getElementById("authStatus");
const list = document.getElementById("list");
let token = null;
// ------------------------------
// AUTH
// ------------------------------
function setToken(t) {
token = t;
if (token) {
authSection.style.display = "none";
linkSection.style.display = "block";
loadLinks();
} else {
authSection.style.display = "block";
linkSection.style.display = "none";
}
}
document.getElementById("loginForm").addEventListener("submit", async e => {
e.preventDefault();
const email = e.target.email.value;
const password = e.target.password.value;
try {
const t = await login(email, password);
setToken(t);
} catch (err) {
authStatus.textContent = err.message;
}
});
document.getElementById("registerForm").addEventListener("submit", async e => {
e.preventDefault();
const email = e.target.email.value;
const password = e.target.password.value;
try {
await register(email, password);
authStatus.textContent = "Registrato! Ora effettua il login.";
} catch (err) {
authStatus.textContent = err.message;
}
});
// ------------------------------
// LINKS
// ------------------------------
async function loadLinks() {
const links = await getLinks(token);
list.innerHTML = links
.map(
link => `
<div class="item">
${link.icon ? `<img src="http://192.168.1.3:3000${link.icon}">` : ""}
<div>
<strong>${link.name}</strong><br>
<a href="${link.url}" target="_blank">${link.url}</a>
</div>
</div>
`
)
.join("");
}
document.getElementById("linkForm").addEventListener("submit", async e => {
e.preventDefault();
const formData = new FormData(e.target);
const iconFile = formData.get("icon");
await createLink(token, {
name: formData.get("name"),
url: formData.get("url"),
iconFile: iconFile.size > 0 ? iconFile : null
});
e.target.reset();
loadLinks();
});
// Init
setToken(null);