- Moderationsseite und Melde-Funktion (report) komplett ausgebaut; folgt als eigenständiges Projekt - alle API-Endpunkte unter /api, dort ausschließlich JSON: auch 404, 405, Rate-Limit (429) und Panics (500) - Fehler nur über HTTP-Status; stille DB-Fehler in stats, logout und Vote-Zählern liefern jetzt 500 statt Nullen - /auth/headerbar entfernt (Frontend nutzt /api/user/info) - Frontend auf /api und statusbasierte Auswertung umgestellt - notes/api.md neu als Referenz der aktuellen API Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TiXsPUqw7oeomZ8wZrQW5q
70 lines
2.4 KiB
JavaScript
70 lines
2.4 KiB
JavaScript
"use strict";
|
|
|
|
// Nutzername aus dem Pfad /u/<name>.
|
|
const username = decodeURIComponent(location.pathname.split("/")[2] || "");
|
|
|
|
document.getElementById("rename-form").addEventListener("submit", async (e) => {
|
|
e.preventDefault();
|
|
const res = await api.post("/user/rename", new FormData(e.target));
|
|
if (res.ok) {
|
|
location.href = `/u/${encodeURIComponent(res.data.username)}`;
|
|
} else {
|
|
document.getElementById("rename-msg").textContent =
|
|
errMsg(res.data, "Umbenennen fehlgeschlagen.");
|
|
}
|
|
});
|
|
|
|
document.getElementById("avatar-form").addEventListener("submit", async (e) => {
|
|
e.preventDefault();
|
|
const res = await api.post("/user/avatar", new FormData(e.target));
|
|
if (res.ok) {
|
|
// Cache umgehen, damit das neue Bild sofort erscheint.
|
|
document.getElementById("profile-avatar").src = `${avatarUrl(res.data.avatar)}?t=${Date.now()}`;
|
|
e.target.reset();
|
|
document.getElementById("avatar-msg").textContent = "";
|
|
} else {
|
|
document.getElementById("avatar-msg").textContent =
|
|
errMsg(res.data, "Hochladen fehlgeschlagen.");
|
|
}
|
|
});
|
|
|
|
document.getElementById("delete-form").addEventListener("submit", async (e) => {
|
|
e.preventDefault();
|
|
if (!confirm("Konto wirklich unwiderruflich löschen?")) return;
|
|
const res = await api.post("/user/delete", new FormData(e.target));
|
|
if (res.ok) {
|
|
location.href = "/";
|
|
} else {
|
|
document.getElementById("delete-msg").textContent =
|
|
errMsg(res.data, "Löschen fehlgeschlagen.");
|
|
}
|
|
});
|
|
|
|
async function init() {
|
|
const res = await api.get(`/u/${encodeURIComponent(username)}/info`);
|
|
if (!res.ok) {
|
|
document.getElementById("profile-name").textContent =
|
|
errMsg(res.data, "Profil konnte nicht geladen werden.");
|
|
return;
|
|
}
|
|
const info = res.data;
|
|
|
|
document.getElementById("profile-name").textContent = info.username;
|
|
document.getElementById("profile-avatar").src = avatarUrl(info.avatar);
|
|
const since = new Date(info.created_at * 1000).toLocaleDateString("de-DE");
|
|
document.getElementById("profile-info").textContent = `Mitglied seit ${since}`;
|
|
|
|
// Eigene Seite? -> Einstellungen einblenden.
|
|
const me = await api.get("/user/info");
|
|
const isOwner = me.ok && me.data.username === info.username;
|
|
document.getElementById("settings").hidden = !isOwner;
|
|
|
|
createFeed(
|
|
document.getElementById("feed"),
|
|
document.getElementById("sentinel"),
|
|
(page) => `/u/${encodeURIComponent(username)}/feed/${page}`
|
|
);
|
|
}
|
|
|
|
init();
|