diff --git a/static/css/custom.css b/static/css/custom.css index 9d0e379..4fa1465 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -303,4 +303,82 @@ select.form-select:focus { /* kursor */ .CodeMirror-cursor { border-left: 1px solid #e0e0e0 !important; +} + +.nav-pills .nav-link.active { + background: var(--accent); + color: #111; +} + +.nav-pills .nav-link { + color: inherit; +} + +/* sticky tylko od md wzwyż, by na mobile nie przyklejać */ +@media (min-width: 768px) { + .sticky-md { + position: sticky; + } +} + +:root { + --sticky-offset: 1rem; +} + +/* Rząd kopiowania: czytelny, łatwy klik w przycisk */ +.copy-row { + display: grid; + grid-template-columns: 1fr auto; + grid-template-rows: auto auto; + gap: .25rem .5rem; + align-items: center; + padding: .5rem .75rem; + border: 1px solid var(--border, rgba(255, 255, 255, .15)); + border-radius: .75rem; + background: rgba(255, 255, 255, .02); +} + +.copy-row+.copy-row { + margin-top: .5rem; +} + +.copy-row__label { + grid-column: 1 / 2; + grid-row: 1 / 2; + font-weight: 600; + font-size: .9rem; + opacity: .85; +} + +.copy-row__value { + grid-column: 1 / 2; + grid-row: 2 / 3; + font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace; + letter-spacing: .02em; + user-select: text; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.copy-row__btn { + grid-column: 2 / 3; + grid-row: 1 / 3; + height: fit-content; + align-self: center; +} + +@media (max-width: 575.98px) { + + /* na XS przycisk pod spodem – łatwiej trafić kciukiem */ + .copy-row { + grid-template-columns: 1fr; + grid-template-rows: auto auto auto; + } + + .copy-row__btn { + grid-column: 1 / -1; + grid-row: 3 / 4; + width: 100%; + } } \ No newline at end of file diff --git a/static/js/edytuj_stan.js b/static/js/edytuj_stan.js index 8170509..f1e3224 100644 --- a/static/js/edytuj_stan.js +++ b/static/js/edytuj_stan.js @@ -26,15 +26,20 @@ const val = clamp(Number(input.value)); const p = Math.max(0, Math.min(100, pct(val))); - if (previewPct) previewPct.textContent = pct(val).toFixed(1); - if (previewBar) previewBar.style.setProperty('--progress-width', p + '%'); + if (previewPct) previewPct.textContent = p.toFixed(1); + + if (previewBar) { + previewBar.style.width = p + '%'; + previewBar.setAttribute('aria-valuenow', p.toFixed(2)); + } if (previewNote) { if (cel > 0) { const diff = cel - val; - if (diff > 0) { + const isZero = Math.abs(diff) < 0.005; // float-safe + if (diff > 0 && !isZero) { previewNote.textContent = 'Do celu brakuje: ' + diff.toFixed(2) + ' PLN'; - } else if (diff === 0) { + } else if (isZero) { previewNote.textContent = 'Cel osiągnięty.'; } else { previewNote.textContent = 'Przekroczono cel o: ' + Math.abs(diff).toFixed(2) + ' PLN'; @@ -45,6 +50,7 @@ } } + // Zmiana ręczna if (input) { input.addEventListener('input', updatePreview); diff --git a/static/js/zbiorka.js b/static/js/zbiorka.js index f83e927..a5515e1 100644 --- a/static/js/zbiorka.js +++ b/static/js/zbiorka.js @@ -1,38 +1,66 @@ + (function () { - const ibanEl = document.getElementById('ibanDisplay'); + // --- Formatowanie IBAN --- + const ibanEl = document.getElementById('ibanInput') || document.getElementById('ibanDisplay'); if (ibanEl) { - const digits = (ibanEl.textContent || '').replace(/\s+/g, '').replace(/^PL/i, '').replace(/\D/g, '').slice(0, 26); - if (digits) ibanEl.textContent = 'PL ' + digits.replace(/(.{4})/g, '$1 ').trim(); - } - const blikEl = document.getElementById('blikDisplay'); - if (blikEl) { - const d = (blikEl.textContent || '').replace(/\D/g, '').slice(0, 9); - const parts = [d.slice(0, 3), d.slice(3, 6), d.slice(6, 9)].filter(Boolean).join(' '); - if (parts) blikEl.textContent = parts; + const raw = (('value' in ibanEl ? ibanEl.value : ibanEl.textContent) || '') + .toString().replace(/\s+/g, '').toUpperCase(); + const digits = raw.replace(/^PL/, '').replace(/\D/g, '').slice(0, 26); + if (digits) { + const pretty = 'PL ' + digits.replace(/(.{4})/g, '$1 ').trim(); + if ('value' in ibanEl) ibanEl.value = pretty; else ibanEl.textContent = pretty; + } } - document.querySelectorAll('[data-copy-target]').forEach(btn => { + // --- Formatowanie BLIK --- + const blikEl = document.getElementById('blikInput') || document.getElementById('blikDisplay'); + if (blikEl) { + const raw = (('value' in blikEl ? blikEl.value : blikEl.textContent) || '') + .toString().replace(/\D/g, '').slice(0, 9); + if (raw) { + const pretty = [raw.slice(0, 3), raw.slice(3, 6), raw.slice(6, 9)] + .filter(Boolean).join(' '); + if ('value' in blikEl) blikEl.value = pretty; else blikEl.textContent = pretty; + } + } + + // --- Kopiowanie: wspiera data-copy-input i data-copy-target --- + const buttons = document.querySelectorAll('[data-copy-input], [data-copy-target]'); + buttons.forEach(btn => { btn.addEventListener('click', async () => { - const sel = btn.getAttribute('data-copy-target'); + const sel = btn.getAttribute('data-copy-input') || btn.getAttribute('data-copy-target'); const el = sel ? document.querySelector(sel) : null; if (!el) return; - const raw = el.textContent.replace(/\u00A0/g, ' ').trim(); - try { - await navigator.clipboard.writeText(raw); - const original = btn.textContent; + + const textRaw = ('value' in el ? el.value : el.textContent || '') + .toString().replace(/\u00A0/g, ' ').trim(); + + const copyWithFallback = async (text) => { + try { + await navigator.clipboard.writeText(text); + return true; + } catch { + // Fallback: tymczasowy textarea + const ta = document.createElement('textarea'); + ta.value = text; + ta.style.position = 'fixed'; + ta.style.top = '-1000px'; + ta.setAttribute('readonly', ''); + document.body.appendChild(ta); + ta.select(); + try { document.execCommand('copy'); } catch { /* ignore */ } + document.body.removeChild(ta); + return true; + } + }; + + const original = btn.textContent; + const ok = await copyWithFallback(textRaw); + if (ok) { btn.textContent = 'Skopiowano!'; btn.disabled = true; setTimeout(() => { btn.textContent = original; btn.disabled = false; }, 1200); - } catch { - // fallback - const r = document.createRange(); - r.selectNodeContents(el); - const selObj = window.getSelection(); - selObj.removeAllRanges(); - selObj.addRange(r); - try { document.execCommand('copy'); } catch { } - selObj.removeAllRanges(); } }); }); -})(); \ No newline at end of file +})(); diff --git a/templates/admin/edytuj_stan.html b/templates/admin/edytuj_stan.html index 855f77b..f83beea 100644 --- a/templates/admin/edytuj_stan.html +++ b/templates/admin/edytuj_stan.html @@ -81,10 +81,7 @@ {% set brakujace = (zbiorka.cel - zbiorka.stan) if (zbiorka.cel - zbiorka.stan) > 0 else 0 %} - {% if brakujace > 0 %} - Brakuje: {{ brakujace|round(2) }} - PLN - {% endif %} + {% endif %} @@ -105,8 +102,7 @@
Gdy pojawią się pierwsze wpłaty lub wydatki, zobaczysz je tutaj.
+ {% if current_user.is_authenticated and current_user.is_admin %} + + Zarządzaj + + {% endif %} +Gdy pojawią się pierwsze wpłaty lub wydatki, zobaczysz je tutaj.
+