Files
SPA-landing/schadenprotokoll/app.js
Admin a9eaa81c37 Add template upload functionality to Schadenprotokoll
- New Templates tab for PDF and Word template management
- API endpoints for listing and uploading templates
- Automatic backup of old templates before replacement

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 11:54:00 +00:00

251 lines
8.9 KiB
JavaScript

// Tab Navigation
document.querySelectorAll(".tab").forEach(tab => {
tab.addEventListener("click", () => {
document.querySelectorAll(".tab").forEach(t => t.classList.remove("active"));
document.querySelectorAll(".tab-content").forEach(c => c.classList.remove("active"));
tab.classList.add("active");
document.getElementById(tab.dataset.tab).classList.add("active");
});
});
// Upload Zone Setup
function setupUploadZone(zoneId, inputId, infoId, btnId) {
const zone = document.getElementById(zoneId);
const input = document.getElementById(inputId);
const info = document.getElementById(infoId);
const btn = document.getElementById(btnId);
zone.addEventListener("click", () => input.click());
zone.addEventListener("dragover", (e) => { e.preventDefault(); zone.classList.add("dragover"); });
zone.addEventListener("dragleave", () => zone.classList.remove("dragover"));
zone.addEventListener("drop", (e) => {
e.preventDefault();
zone.classList.remove("dragover");
if (e.dataTransfer.files.length) {
input.files = e.dataTransfer.files;
updateFileInfo(input, info, btn);
}
});
input.addEventListener("change", () => updateFileInfo(input, info, btn));
}
function updateFileInfo(input, info, btn) {
if (input.files.length) {
const file = input.files[0];
info.innerHTML = `<strong>✓ ${file.name}</strong> (${(file.size / 1024).toFixed(1)} KB)`;
info.classList.add("visible");
btn.disabled = false;
}
}
function showStatus(id, type, message) {
const status = document.getElementById(id);
status.className = `status visible ${type}`;
status.textContent = message;
}
// Setup all upload zones
setupUploadZone("laufzettel-zone", "laufzettel-input", "laufzettel-info", "generate-btn");
setupUploadZone("pdf-zone", "pdf-input", "pdf-info", "analyze-btn");
setupUploadZone("vorbericht-zone", "vorbericht-input", "vorbericht-info", "vorbericht-btn");
// API Base URL
const API_BASE = "/schadenprotokoll/api";
// Generate Button
document.getElementById("generate-btn").addEventListener("click", async () => {
showStatus("generate-status", "loading", "⏳ Verarbeite Laufzettel...");
const file = document.getElementById("laufzettel-input").files[0];
const formData = new FormData();
formData.append("file", file);
try {
const response = await fetch(`${API_BASE}/generate`, {
method: "POST",
body: formData
});
if (\!response.ok) {
const err = await response.json();
throw new Error(err.error || "Unbekannter Fehler");
}
const blob = await response.blob();
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "Schadenprotokoll_vorbefuellt.pdf";
a.click();
URL.revokeObjectURL(url);
showStatus("generate-status", "success", "✓ PDF erfolgreich generiert und heruntergeladen");
} catch (err) {
showStatus("generate-status", "error", `❌ Fehler: ${err.message}`);
}
});
// Analyze Button
document.getElementById("analyze-btn").addEventListener("click", async () => {
showStatus("analyze-status", "loading", "⏳ Analysiere PDF...");
const file = document.getElementById("pdf-input").files[0];
const formData = new FormData();
formData.append("file", file);
try {
const response = await fetch(`${API_BASE}/analyze`, {
method: "POST",
body: formData
});
if (\!response.ok) {
const err = await response.json();
throw new Error(err.error || "Unbekannter Fehler");
}
const result = await response.json();
displayAnalysisResult(result.data);
showStatus("analyze-status", "success", "✓ Analyse abgeschlossen");
} catch (err) {
showStatus("analyze-status", "error", `❌ Fehler: ${err.message}`);
}
});
function displayAnalysisResult(data) {
const container = document.getElementById("analyze-data");
let html = "";
// Textfelder
if (Object.keys(data.textfields).length > 0) {
html += `<div class="field-group"><h5>Textfelder</h5><div class="field-list">`;
for (const [key, value] of Object.entries(data.textfields)) {
if (value) html += `<div class="dropdown-item"><strong>${key}:</strong> ${value}</div>`;
}
html += `</div></div>`;
}
// Dropdowns
if (Object.keys(data.dropdowns).length > 0) {
html += `<div class="field-group"><h5>Dropdown-Auswahlen (Sachverhalt)</h5><div class="field-list">`;
for (const [key, val] of Object.entries(data.dropdowns)) {
if (val.selected) {
html += `<div class="dropdown-item"><strong>${key}:</strong> ${val.selected}</div>`;
}
}
html += `</div></div>`;
}
container.innerHTML = html || "<p>Keine ausgefüllten Felder gefunden.</p>";
document.getElementById("analyze-result").classList.add("visible");
}
// Vorbericht Button
document.getElementById("vorbericht-btn").addEventListener("click", async () => {
showStatus("vorbericht-status", "loading", "⏳ Erstelle Vorbericht...");
const file = document.getElementById("vorbericht-input").files[0];
const formData = new FormData();
formData.append("file", file);
try {
const response = await fetch(`${API_BASE}/vorbericht`, {
method: "POST",
body: formData
});
if (\!response.ok) {
const err = await response.json();
throw new Error(err.error || "Unbekannter Fehler");
}
const blob = await response.blob();
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "Vorbericht.docx";
a.click();
URL.revokeObjectURL(url);
showStatus("vorbericht-status", "success", "✓ Vorbericht erfolgreich erstellt und heruntergeladen");
} catch (err) {
showStatus("vorbericht-status", "error", `❌ Fehler: ${err.message}`);
}
});
// Admin Tab - Templates laden
async function loadTemplates() {
try {
const response = await fetch(`${API_BASE}/templates`);
const data = await response.json();
const container = document.getElementById("templates-container");
if (data.templates.length === 0) {
container.innerHTML = "<p>Keine Templates vorhanden.</p>";
return;
}
container.innerHTML = data.templates.map(t => `
<div class="template-item">
<span class="name">${t.type === "pdf" ? "📄" : "📝"} ${t.name}</span>
<span class="size">${(t.size / 1024).toFixed(1)} KB</span>
</div>
`).join("");
} catch (err) {
document.getElementById("templates-container").innerHTML =
`<p style="color:red;">Fehler: ${err.message}</p>`;
}
}
// Template Upload
function setupTemplateUpload(zoneId, inputId, templateType) {
const zone = document.getElementById(zoneId);
const input = document.getElementById(inputId);
zone.addEventListener("click", () => input.click());
zone.addEventListener("dragover", (e) => { e.preventDefault(); zone.classList.add("dragover"); });
zone.addEventListener("dragleave", () => zone.classList.remove("dragover"));
zone.addEventListener("drop", (e) => {
e.preventDefault();
zone.classList.remove("dragover");
if (e.dataTransfer.files.length) {
input.files = e.dataTransfer.files;
uploadTemplate(input.files[0], templateType);
}
});
input.addEventListener("change", () => {
if (input.files.length) uploadTemplate(input.files[0], templateType);
});
}
async function uploadTemplate(file, type) {
showStatus("admin-status", "loading", `⏳ Lade ${type.toUpperCase()} Template hoch...`);
const formData = new FormData();
formData.append("file", file);
formData.append("type", type);
try {
const response = await fetch(`${API_BASE}/templates/upload`, {
method: "POST",
body: formData
});
if (!response.ok) {
const err = await response.json();
throw new Error(err.error);
}
showStatus("admin-status", "success", "✓ Template erfolgreich hochgeladen");
loadTemplates();
} catch (err) {
showStatus("admin-status", "error", `❌ Fehler: ${err.message}`);
}
}
setupTemplateUpload("pdf-template-zone", "pdf-template-input", "pdf");
setupTemplateUpload("docx-template-zone", "docx-template-input", "docx");
// Templates beim Tab-Wechsel laden
document.querySelector([data-tab=admin]).addEventListener("click", loadTemplates);