Files
dickendock/backend/upload-page.html

148 lines
6.9 KiB
HTML
Raw 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.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Datei hochladen DickenDock</title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{background:#0d0d0f;color:#fff;font-family:'Courier New',monospace;min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px}
.card{background:#1a1a1e;border:1px solid rgba(255,255,255,0.1);border-radius:16px;padding:32px;width:100%;max-width:440px}
h1{font-size:18px;margin-bottom:6px;color:#4ecdc4}
.sub{color:rgba(255,255,255,0.4);font-size:12px;margin-bottom:24px}
label{display:block;color:rgba(255,255,255,0.5);font-size:10px;letter-spacing:2px;margin-bottom:4px}
input[type=password],input[type=file]{width:100%;background:rgba(255,255,255,0.05);border:1px solid rgba(255,255,255,0.12);border-radius:8px;padding:10px 12px;color:#fff;font-family:inherit;font-size:14px;outline:none}
input[type=file]{cursor:pointer;padding:8px}
input[type=file]::file-selector-button{background:#4ecdc4;border:none;border-radius:6px;color:#0d0d0f;cursor:pointer;font-family:inherit;font-weight:700;padding:4px 12px;margin-right:10px}
.btn{width:100%;background:#4ecdc4;border:none;border-radius:8px;color:#0d0d0f;cursor:pointer;font-family:inherit;font-size:14px;font-weight:700;padding:12px;margin-top:12px}
.btn:disabled{opacity:0.4;cursor:default}
.btn.danger{background:#ff6b9d}
.info{background:rgba(78,205,196,0.08);border:1px solid rgba(78,205,196,0.2);border-radius:8px;padding:10px 12px;font-size:12px;color:rgba(255,255,255,0.6);margin-bottom:16px}
.msg{border-radius:8px;padding:10px 12px;font-size:13px;margin-top:12px}
.msg.ok{background:rgba(78,205,196,0.12);border:1px solid rgba(78,205,196,0.3);color:#4ecdc4}
.msg.err{background:rgba(255,107,157,0.12);border:1px solid rgba(255,107,157,0.3);color:#ff6b9d}
.hidden{display:none}
.done-list{margin-top:12px;font-size:12px;color:rgba(255,255,255,0.5)}
.done-list li{padding:3px 0;list-style:none}
.done-list li::before{content:'✓ ';color:#4ecdc4}
#progress{height:4px;background:rgba(78,205,196,0.2);border-radius:2px;margin-top:8px;overflow:hidden}
#progress-bar{height:100%;background:#4ecdc4;width:0;transition:width 0.3s}
</style>
</head>
<body>
<div class="card">
<h1>📤 Datei-Upload</h1>
<p class="sub" id="sub">Dateien hochladen</p>
<!-- Passwort-Sektion -->
<div id="pw-section">
<div class="info" id="share-info">Link wird geprüft…</div>
<label>PASSWORT</label>
<input type="password" id="pw" placeholder="Passwort eingeben" autocomplete="off"/>
<button class="btn" id="pw-btn" onclick="verify()">Zugang bestätigen</button>
<div id="pw-msg" class="msg hidden"></div>
</div>
<!-- Upload-Sektion -->
<div id="upload-section" class="hidden">
<div class="info" id="upload-info"></div>
<label>DATEI AUSWÄHLEN</label>
<input type="file" id="file-input" multiple/>
<div id="progress"><div id="progress-bar"></div></div>
<button class="btn" id="upload-btn" onclick="upload()">⬆ Hochladen</button>
<div id="upload-msg" class="msg hidden"></div>
<ul class="done-list" id="done-list"></ul>
</div>
</div>
<script>
const token = location.pathname.replace('/u/','').replace('/','');
let password = '';
let maxMb = 10;
async function init() {
try {
const r = await fetch(`/api/upload-shares/public/${token}`);
const d = await r.json();
if (!r.ok) return showFatal(d.error || 'Ungültiger Link');
maxMb = d.max_size_mb;
const exp = new Date(d.expires_at).toLocaleString('de-DE', {timeZone:'Europe/Berlin',day:'2-digit',month:'2-digit',year:'numeric',hour:'2-digit',minute:'2-digit'});
document.getElementById('share-info').textContent = `Gültig bis: ${exp} · Max ${d.max_size_mb} MB pro Datei`;
} catch { showFatal('Verbindung fehlgeschlagen'); }
}
function showFatal(msg) {
document.getElementById('pw-section').innerHTML = `<div class="msg err">${msg}</div>`;
}
async function verify() {
const pw = document.getElementById('pw').value;
if (!pw) return;
document.getElementById('pw-btn').disabled = true;
try {
const r = await fetch(`/api/upload-shares/public/${token}/verify`, {
method:'POST', headers:{'Content-Type':'application/json'},
body: JSON.stringify({ password: pw })
});
const d = await r.json();
if (!r.ok) {
document.getElementById('pw-msg').className = 'msg err';
document.getElementById('pw-msg').textContent = d.error;
document.getElementById('pw-msg').classList.remove('hidden');
document.getElementById('pw-btn').disabled = false;
return;
}
password = pw;
maxMb = d.max_size_mb;
document.getElementById('pw-section').classList.add('hidden');
document.getElementById('upload-section').classList.remove('hidden');
const exp = new Date(d.expires_at).toLocaleString('de-DE', {timeZone:'Europe/Berlin',day:'2-digit',month:'2-digit',year:'numeric',hour:'2-digit',minute:'2-digit'});
document.getElementById('upload-info').textContent = `Gültig bis ${exp} · Max ${d.max_size_mb} MB pro Datei`;
document.getElementById('sub').textContent = 'Dateien hochladen ✓';
} catch {
document.getElementById('pw-btn').disabled = false;
}
}
async function upload() {
const files = document.getElementById('file-input').files;
if (!files.length) return;
const btn = document.getElementById('upload-btn');
btn.disabled = true;
const msg = document.getElementById('upload-msg');
const bar = document.getElementById('progress-bar');
const list = document.getElementById('done-list');
for (let i=0; i<files.length; i++) {
const file = files[i];
if (file.size > maxMb*1024*1024) {
msg.className = 'msg err'; msg.textContent = `"${file.name}" ist zu groß (max ${maxMb} MB)`; msg.classList.remove('hidden');
continue;
}
bar.style.width = ((i+0.5)/files.length*100)+'%';
const fd = new FormData(); fd.append('file', file);
try {
const r = await fetch(`/api/upload-shares/public/${token}/upload`, {
method:'POST', headers:{'x-upload-password': password}, body: fd
});
const d = await r.json();
if (r.ok) {
const li = document.createElement('li'); li.textContent = file.name; list.appendChild(li);
msg.className = 'msg ok'; msg.textContent = `${list.children.length} Datei(en) erfolgreich hochgeladen`; msg.classList.remove('hidden');
} else {
msg.className = 'msg err'; msg.textContent = d.error; msg.classList.remove('hidden');
}
} catch { msg.className='msg err'; msg.textContent='Upload fehlgeschlagen'; msg.classList.remove('hidden'); }
}
bar.style.width = '100%';
setTimeout(()=>{ bar.style.width='0'; }, 1500);
btn.disabled = false;
document.getElementById('file-input').value = '';
}
document.getElementById('pw').addEventListener('keydown', e => { if(e.key==='Enter') verify(); });
init();
</script>
</body>
</html>