Steuerkram/public/static/js/beleg-ui.js

153 lines
6.3 KiB
JavaScript
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.

'use strict';
// ── Lieferanten-Autospeicherung ─────────────────────────────────
document.addEventListener('DOMContentLoaded', function() {
const _sup = document.getElementById('supplier-persistent-input');
if (!_sup) return;
const _bar = _sup.closest('[data-beleg-id]');
async function _saveSupplier() {
const newValue = _sup.value.trim();
if (!_bar) return;
const body = new URLSearchParams({
rechnungs_nr: _bar.dataset.rechnungsNr || '',
belegtyp: _bar.dataset.belegtyp || '',
beleg_datum: _bar.dataset.belegDatum || '',
betrag_brutto: _bar.dataset.betragBrutto || '',
supplier_name: newValue,
});
try {
const res = await fetch('/belege/' + _bar.dataset.belegId + '/meta', {
method: 'POST',
headers: {'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/x-www-form-urlencoded'},
body: body.toString(),
});
if (!res.ok) throw new Error();
if (newValue) {
_bar.dataset.supplierName = newValue;
// Hidden-Metaformular synchron halten
const hiddenInput = document.getElementById('supplier_name_input');
if (hiddenInput) hiddenInput.value = newValue;
// Persistentes Input durch Inline-Trigger ersetzen (= visuelle Bestätigung)
const span = document.createElement('span');
span.className = 'inline-edit-trigger';
span.id = 'supplier-inline-trigger';
span.dataset.field = 'supplier_name';
span.dataset.type = 'text';
span.dataset.raw = newValue;
span.title = 'Klicken zum Bearbeiten';
span.textContent = newValue;
_sup.replaceWith(span);
}
} catch (_) {
// Speichern fehlgeschlagen – Feld bleibt editierbar
}
}
_sup.addEventListener('blur', _saveSupplier);
_sup.addEventListener('keydown', function(e) {
if (e.key === 'Enter') { e.preventDefault(); _sup.blur(); }
});
});
// ── Verschiebbarer Trenner (Split-Pane) ──────────────────────────
(function () {
const STORAGE_KEY = 'beleg_split_width';
const layout = document.getElementById('beleg-split-layout');
const preview = document.getElementById('beleg-preview-pane');
const handle = document.getElementById('beleg-split-handle');
if (!layout || !preview || !handle) return;
function applyWidth(px) {
preview.style.width = px + 'px';
preview.style.setProperty('--beleg-preview-width', px + 'px');
}
function savedWidth() {
const stored = parseInt(localStorage.getItem(STORAGE_KEY), 10);
if (!isNaN(stored) && stored > 0) return stored;
return Math.round(layout.offsetWidth * 0.55);
}
applyWidth(savedWidth());
let dragging = false;
let startX = 0;
let startW = 0;
handle.addEventListener('mousedown', function (e) {
e.preventDefault();
dragging = true;
startX = e.clientX;
startW = preview.offsetWidth;
handle.classList.add('dragging');
document.body.style.cursor = 'col-resize';
document.body.style.userSelect = 'none';
});
document.addEventListener('mousemove', function (e) {
if (!dragging) return;
const delta = e.clientX - startX;
const total = layout.offsetWidth;
const minR = 320;
const maxW = total - minR - handle.offsetWidth;
const newW = Math.max(200, Math.min(maxW, startW + delta));
applyWidth(newW);
});
document.addEventListener('mouseup', function () {
if (!dragging) return;
dragging = false;
handle.classList.remove('dragging');
document.body.style.cursor = '';
document.body.style.userSelect = '';
localStorage.setItem(STORAGE_KEY, preview.offsetWidth);
});
}());
// ── Bildzoom ──────────────────────────────────────────────────
(function () {
const ZOOM_KEY = 'beleg_img_zoom';
const STEP = 1.25;
const MIN = 0.25;
const MAX = 5;
const img = document.getElementById('beleg-img');
const wrap = document.getElementById('img-zoom-wrap');
const lvl = document.getElementById('img-zoom-level');
if (!img || !wrap) return;
let scale = 1;
function applyScale(s) {
scale = Math.max(MIN, Math.min(MAX, s));
img.style.width = Math.round(scale * 100) + '%';
if (lvl) lvl.textContent = Math.round(scale * 100) + ' %';
wrap.style.cursor = scale > 1 ? 'grab' : 'zoom-in';
localStorage.setItem(ZOOM_KEY, scale);
}
window.imgZoom = function (dir) { applyScale(dir > 0 ? scale * STEP : scale / STEP); };
window.imgZoomReset = function () { applyScale(1); };
const saved = parseFloat(localStorage.getItem(ZOOM_KEY));
if (!isNaN(saved) && saved > 0) applyScale(saved);
wrap.addEventListener('wheel', function (e) {
if (!e.ctrlKey) return;
e.preventDefault();
applyScale(e.deltaY < 0 ? scale * STEP : scale / STEP);
}, { passive: false });
document.addEventListener('keydown', function (e) {
if (!e.ctrlKey || !document.getElementById('beleg-img')) return;
if (e.key === '+' || e.key === '=') { e.preventDefault(); imgZoom(+1); }
if (e.key === '-') { e.preventDefault(); imgZoom(-1); }
if (e.key === '0') { e.preventDefault(); imgZoomReset(); }
});
const zoomOutBtn = document.getElementById('img-zoom-out-btn');
const zoomInBtn = document.getElementById('img-zoom-in-btn');
const zoomResetBtn = document.getElementById('img-zoom-reset-btn');
if (zoomOutBtn) zoomOutBtn.addEventListener('click', function () { imgZoom(-1); });
if (zoomInBtn) zoomInBtn.addEventListener('click', function () { imgZoom(+1); });
if (zoomResetBtn) zoomResetBtn.addEventListener('click', function () { imgZoomReset(); });
}());