From 92101e307748106608206b34499c6ad5e969dd14 Mon Sep 17 00:00:00 2001 From: bernd Date: Thu, 13 Aug 2026 12:11:08 +0000 Subject: [PATCH] Let uploaded documents open as a preview, download separately MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every uploaded-document link (contract PDFs, ID front/back, Schufa report — active and archived) previously forced a download on click via the `download` attribute, with no way to just look at the file first. New shared buildDocumentChip() renders the filename as a target="_blank" link (browsers preview PDFs/images natively) plus a small ⬇ icon next to it for an explicit download, reused across all three places these chips are rendered. --- web-dashboard/index.html | 52 +++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/web-dashboard/index.html b/web-dashboard/index.html index 6ea4725..c943625 100644 --- a/web-dashboard/index.html +++ b/web-dashboard/index.html @@ -2854,6 +2854,33 @@ return `Dokument ${index + 1}.${ext}`; } + // Klick auf den Namen öffnet eine Vorschau im neuen Tab (Browser können + // PDFs/Bilder nativ anzeigen); der Pfeil daneben lädt bei Bedarf separat + // herunter. Für alle hochgeladenen Dokumente (Verträge, Ausweis, Schufa) einheitlich. + function buildDocumentChip(label, url) { + const chip = el('span', 'invite-status-chip'); + chip.style.cssText = 'background:var(--bg); color:var(--text); text-transform:none; display:inline-flex; align-items:center; gap:7px;'; + + const previewLink = document.createElement('a'); + previewLink.href = url; + previewLink.target = '_blank'; + previewLink.rel = 'noopener'; + previewLink.textContent = label; + previewLink.style.color = 'var(--text)'; + chip.appendChild(previewLink); + + const ext = url.includes('application/pdf') ? 'pdf' : (/^data:image\/(\w+)/.exec(url)?.[1] || 'jpg'); + const downloadLink = document.createElement('a'); + downloadLink.href = url; + downloadLink.download = `${label.replace(/[^\w.-]+/g, '_')}.${ext}`; + downloadLink.title = 'Herunterladen'; + downloadLink.textContent = '⬇'; + downloadLink.style.cssText = 'color:var(--text-muted); text-decoration:none; font-size:12px;'; + chip.appendChild(downloadLink); + + return chip; + } + function buildProfileCompletenessBadge(user) { const missing = []; if (!user.phoneNumber) missing.push('Telefonnummer'); @@ -2894,13 +2921,7 @@ ['Schufa-Auskunft', user.schufaDocumentUrl], ].forEach(([label, url]) => { if (!url) return; - const link = document.createElement('a'); - link.href = url; - link.download = label + '.' + (url.includes('application/pdf') ? 'pdf' : 'jpg'); - link.textContent = label; - link.className = 'invite-status-chip'; - link.style.cssText = 'background:var(--bg); color:var(--text); text-transform:none;'; - linkWrap.appendChild(link); + linkWrap.appendChild(buildDocumentChip(label, url)); }); if (linkWrap.children.length) wrap.appendChild(linkWrap); @@ -2951,14 +2972,7 @@ docWrap.appendChild(el('span', 'meta-text', 'Noch keine Dateien hochgeladen.')); } else { c.contractDocumentUrls.forEach((url, idx) => { - const chip = el('span', 'invite-status-chip'); - chip.style.cssText = 'background:var(--bg); color:var(--text); display:inline-flex; align-items:center; gap:6px; text-transform:none;'; - const link = document.createElement('a'); - link.href = url; - link.download = documentFileName(url, idx); - link.textContent = documentFileName(url, idx); - link.style.color = 'var(--text)'; - chip.appendChild(link); + const chip = buildDocumentChip(documentFileName(url, idx), url); if (isLandlord) { const removeBtn = document.createElement('button'); removeBtn.type = 'button'; @@ -3068,13 +3082,7 @@ const docWrap = el('div'); docWrap.style.cssText = 'display:flex; flex-wrap:wrap; gap:6px;'; c.contractDocumentUrls.forEach((url, idx) => { - const link = document.createElement('a'); - link.href = url; - link.download = documentFileName(url, idx); - link.textContent = documentFileName(url, idx); - link.className = 'invite-status-chip'; - link.style.cssText = 'background:var(--bg); color:var(--text); text-transform:none;'; - docWrap.appendChild(link); + docWrap.appendChild(buildDocumentChip(documentFileName(url, idx), url)); }); row.appendChild(docWrap); }