Feature: Beleg-Vorschau als Split-Panel statt Tooltip in Bank-Zuordnung

This commit is contained in:
fds2610-bot 2026-05-14 20:21:29 +02:00
parent 99aa823d0f
commit b4967a9f18

View file

@ -81,8 +81,11 @@ $vorschauHoehe = (int)($settings['beleg_vorschau_hoehe'] ?? 300);
</div>
</div>
<!-- Offene Belege verknüpfen -->
<div class="card">
<!-- Offene Belege + Vorschau nebeneinander -->
<div style="display:flex;gap:1rem;align-items:flex-start">
<!-- Linke Hälfte: Tabelle -->
<div class="card" style="flex:1;min-width:0">
<div class="card-header">
<div class="card-title">Offene Belege</div>
<span class="text-muted text-sm"><?= count($offeneBelege) ?> ungebuchte Belege</span>
@ -97,31 +100,29 @@ $vorschauHoehe = (int)($settings['beleg_vorschau_hoehe'] ?? 300);
<th>Belegnr.</th>
<th>Datum</th>
<th>Typ</th>
<th>Lieferant / Notiz</th>
<th>Lieferant</th>
<th class="td-right">Brutto</th>
<th></th>
</tr>
</thead>
<tbody>
<?php foreach ($offeneBelege as $b): ?>
<tr>
<td class="td-mono">
<a href="/belege/<?= (int)$b['id'] ?>" target="_blank"
class="beleg-preview-trigger"
data-beleg-id="<?= (int)$b['id'] ?>"><?= $h($b['beleg_nr']) ?></a>
<tr class="beleg-row"
data-beleg-id="<?= (int)$b['id'] ?>"
style="cursor:pointer"
title="Klicken zum Vorschau anzeigen">
<td class="td-mono" onclick="event.stopPropagation()">
<a href="/belege/<?= (int)$b['id'] ?>" target="_blank"><?= $h($b['beleg_nr']) ?></a>
</td>
<td class="td-mono"><?= $h(View::formatDate($b['beleg_datum'])) ?></td>
<td><span class="badge badge-gray"><?= $h($b['belegtyp']) ?></span></td>
<td>
<?= $b['supplier_name'] ? $h($b['supplier_name']) : '<span class="text-muted">–</span>' ?>
<?php if ($b['notes']): ?>
<span class="text-muted text-sm"> · <?= $h(mb_substr($b['notes'], 0, 40)) ?></span>
<?php endif; ?>
</td>
<td class="td-right td-mono">
<?= $b['betrag_brutto'] ? $fmt($b['betrag_brutto']) : '<span class="text-muted">–</span>' ?>
</td>
<td>
<td onclick="event.stopPropagation()">
<form method="post" action="/bank/<?= (int)$transaction['id'] ?>/link" style="display:inline">
<input type="hidden" name="beleg_id" value="<?= (int)$b['id'] ?>">
<button type="submit" class="btn btn-primary btn-sm">Verknüpfen</button>
@ -135,62 +136,50 @@ $vorschauHoehe = (int)($settings['beleg_vorschau_hoehe'] ?? 300);
<?php endif; ?>
</div>
<!-- Beleg-Vorschau Tooltip -->
<div id="beleg-tooltip" style="
display:none;
position:fixed;
z-index:9999;
pointer-events:none;
<!-- Rechte Hälfte: Vorschau-Panel -->
<div id="beleg-preview-panel" style="
flex:1;
min-width:0;
position:sticky;
top:1rem;
border:1px solid var(--color-border,#e2e8f0);
border-radius:var(--radius,6px);
background:#fff;
box-shadow:0 4px 20px rgba(0,0,0,.18);
background:var(--color-surface,#f8fafc);
overflow:hidden;
width:<?= $vorschauBreite ?>px;
height:<?= $vorschauHoehe ?>px;
"></div>
display:flex;
align-items:center;
justify-content:center;
">
<span class="text-muted text-sm" id="beleg-preview-hint">Zeile anklicken für Vorschau</span>
<iframe id="beleg-preview-frame"
style="display:none;width:100%;height:100%;border:none"
src=""></iframe>
</div>
</div>
<script>
(function () {
const tooltip = document.getElementById('beleg-tooltip');
const W = <?= $vorschauBreite ?>;
const H = <?= $vorschauHoehe ?>;
let currentId = null;
let timer = null;
const frame = document.getElementById('beleg-preview-frame');
const hint = document.getElementById('beleg-preview-hint');
let activeRow = null;
document.querySelectorAll('.beleg-preview-trigger').forEach(function (link) {
link.addEventListener('mouseenter', function (e) {
const id = link.dataset.belegId;
document.querySelectorAll('.beleg-row').forEach(function (row) {
row.addEventListener('click', function () {
const id = row.dataset.belegId;
if (!id) return;
timer = setTimeout(function () {
if (currentId !== id) {
currentId = id;
tooltip.innerHTML = '<iframe src="/belege/' + id + '/file" style="width:100%;height:100%;border:none" loading="lazy"></iframe>';
}
positionTooltip(e);
tooltip.style.display = 'block';
}, 120);
});
// Hervorhebung wechseln
if (activeRow) activeRow.style.background = '';
activeRow = row;
row.style.background = 'var(--color-primary-light, #eff6ff)';
link.addEventListener('mousemove', positionTooltip);
link.addEventListener('mouseleave', function () {
clearTimeout(timer);
tooltip.style.display = 'none';
// Vorschau laden
hint.style.display = 'none';
frame.style.display = 'block';
frame.src = '/belege/' + id + '/file';
});
});
function positionTooltip(e) {
const margin = 12;
let x = e.clientX + margin;
let y = e.clientY + margin;
if (x + W > window.innerWidth - margin) x = e.clientX - W - margin;
if (y + H > window.innerHeight - margin) y = e.clientY - H - margin;
tooltip.style.left = Math.max(0, x) + 'px';
tooltip.style.top = Math.max(0, y) + 'px';
}
})();
</script>