Files
GoNtech/web/templates/stranice/popis.html
T

345 lines
16 KiB
HTML

{{template "base" .}}
{{define "naslov"}}Popis — NTech{{end}}
{{define "dodatni-css"}}
<style>
.popis-input {
width: 90px;
text-align: right;
font-family: monospace;
font-size: 14px;
padding: 5px 8px;
}
.popis-input.izmenjeno {
border-color: #f97316;
background: rgba(249,115,22,0.06);
}
.popis-razlika, .popis-vrednost-razlika {
font-family: monospace;
font-size: 13px;
font-weight: 600;
min-width: 40px;
text-align: right;
}
.red-kriticno td { background: rgba(220,38,38,0.04); }
.popis-suma {
display: flex;
gap: 24px;
flex-wrap: wrap;
font-size: 13px;
}
.popis-suma-stavka { display: flex; flex-direction: column; gap: 2px; }
.popis-suma-labela { color: var(--tekst-slabi); font-size: 12px; }
.popis-suma-vrednost { font-weight: 600; font-family: monospace; font-size: 14px; }
.boja-manjak { color: #dc2626; }
.boja-visak { color: #22c55e; }
/* ── MOBILNI (≤768px): tabela → kartice ──────────────────── */
@media (max-width: 768px) {
/* zaglavlje forme: Tip i Napomena u svoj red, jednake pune širine */
.popis-polje { width: 100%; }
#tip-popisa, #napomena-polje { width: 100% !important; }
#tip-popisa { padding-right: 28px; }
/* sakrij sporedne kolone i zbirni red (ukupno je u karticama ispod) */
#popis-tabela .kol-sek { display: none !important; }
#popis-tabela tfoot { display: none !important; }
/* svaki red postaje kartica, svaka ćelija je labela:vrednost */
#popis-tabela, #popis-tabela tbody, #popis-tabela tr, #popis-tabela td { display: block; width: auto; }
#popis-tabela thead { display: none; }
#popis-tabela tr {
border: 0.5px solid var(--ivica);
border-radius: 10px;
padding: 10px 14px;
margin-bottom: 10px;
}
#popis-tabela td {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
text-align: right !important;
padding: 5px 0 !important;
border: none !important;
font-size: 14px;
}
#popis-tabela td::before {
content: attr(data-label);
font-weight: 500;
color: var(--tekst-sporedni);
text-align: left;
white-space: nowrap;
}
/* prva ćelija (naziv) je naslov kartice */
#popis-tabela td.kart-naslov {
justify-content: flex-start;
text-align: left !important;
font-size: 15px;
font-weight: 600;
border-bottom: 0.5px solid var(--ivica) !important;
padding-bottom: 9px !important;
margin-bottom: 5px;
}
#popis-tabela td.kart-naslov::before { content: none; }
/* „Stvarno kol." input — bez spiner strelica (Firefox seče broj) */
.popis-input {
width: 130px;
-moz-appearance: textfield;
appearance: textfield;
}
.popis-input::-webkit-outer-spin-button,
.popis-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
}
</style>
{{end}}
{{define "sadrzaj"}}
<div class="kolona" style="gap:16px;">
{{if .Sacuvano}}
<div class="poruka-uspeh poruka-animacija">Popis je uspešno sačuvan. Korekcije su upisane u magacinsku evidenciju.</div>
{{end}}
{{if .Greska}}
<div class="poruka-greska greska-animacija">{{.Greska}}</div>
{{end}}
<!-- uputstvo -->
<div class="kartica animiraj" style="padding:14px 18px;">
<div style="display:flex;align-items:flex-start;gap:12px;flex-wrap:wrap;">
<div style="flex:1;min-width:260px;">
<div style="font-size:14px;font-weight:500;color:var(--tekst-glavni);margin-bottom:4px;">Popis magacina</div>
<div style="font-size:13px;color:var(--tekst-slabi);line-height:1.6;">
Unesite stvarno prebrojano stanje za svaki artikal. Polja sa razlikom biće istaknuta narandžasto.
Samo artikli sa izmenjenom količinom biće korigovani — ostali ostaju nepromenjeni.
</div>
<div style="font-size:12px;color:var(--tekst-slabi);margin-top:6px;">
Datum popisa: <strong style="color:var(--tekst-glavni);">{{.DatumPopisa}}</strong>
&nbsp;|&nbsp; Sačinio: <strong style="color:var(--tekst-glavni);">{{.KorisnikIme}}</strong>
</div>
</div>
<a hx-boost="true" hx-target="#glavni-sadrzaj" hx-select="#glavni-sadrzaj" hx-swap="outerHTML" href="/izvestaji" class="btn-sekundarno" style="white-space:nowrap;">← Izveštaji</a>
</div>
</div>
<!-- forma -->
<form method="POST" action="/izvestaji/popis">
<input type="hidden" name="csrf_token" value="{{.CsrfToken}}">
<div class="kartica animiraj" style="padding:0;overflow:hidden;">
<div style="padding:12px 20px;border-bottom:0.5px solid var(--ivica);display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:10px;">
<span style="font-size:15px;font-weight:500;color:var(--tekst-glavni);">Artikli</span>
<div style="display:flex;gap:10px;align-items:center;flex-wrap:wrap;">
<div class="popis-polje">
<label class="polje-labela" style="display:inline;margin-right:6px;">Tip:</label>
<select name="tip_popisa" id="tip-popisa" style="width:auto;height:auto;font-size:13px;padding:5px 28px 5px 8px;" onchange="azurirajNapomenu()">
<option value="godišnji"{{if eq .TipPopisa "godišnji"}} selected{{end}}>Godišnji</option>
<option value="vanredni"{{if eq .TipPopisa "vanredni"}} selected{{end}}>Vanredni</option>
<option value="preuzimanje"{{if eq .TipPopisa "preuzimanje"}} selected{{end}}>Preuzimanje dužnosti</option>
</select>
</div>
<div class="popis-polje">
<label class="polje-labela" style="display:inline;margin-right:6px;">Napomena:</label>
<input type="text" name="napomena" id="napomena-polje" value="Godišnji popis" style="width:220px;font-size:13px;padding:5px 8px;">
</div>
<button type="submit" class="btn-primarno">Sačuvaj popis</button>
</div>
</div>
{{if not .Artikli}}
<div style="padding:40px;text-align:center;color:var(--tekst-slabi);font-size:14px;">
Nema artikala u magacinu.
</div>
{{else}}
<div style="overflow-x:auto;">
<table class="tabela" id="popis-tabela">
<thead>
<tr>
<th>Artikal</th>
<th class="kol-sek">Šifra</th>
<th class="kol-sek">Kategorija</th>
<th class="kol-sek" style="text-align:right;">JM</th>
<th class="kol-sek" style="text-align:right;">Nab. cena</th>
<th style="text-align:right;">Knj. kol.</th>
<th class="kol-sek" style="text-align:right;">Knj. vrednost</th>
<th style="text-align:right;">Stvarno kol.</th>
<th style="text-align:right;">Razlika kol.</th>
<th class="kol-sek" style="text-align:right;">Razlika vrednost</th>
</tr>
</thead>
<tbody>
{{range .Artikli}}
<tr class="{{if le .Kolicina .KolicinMin}}red-kriticno{{end}}" id="red-{{.ID}}">
<td class="kart-naslov" style="font-weight:500;">{{.Naziv}}</td>
<td class="kol-sek" data-label="Šifra" style="font-family:monospace;font-size:12px;color:var(--tekst-slabi);">{{if .Sifra}}{{.Sifra}}{{else}}—{{end}}</td>
<td class="kol-sek" data-label="Kategorija" style="font-size:12px;color:var(--tekst-slabi);">{{if .KategorijaNaziv}}{{.KategorijaNaziv}}{{else}}—{{end}}</td>
<td class="kol-sek" data-label="JM" style="text-align:right;font-size:12px;color:var(--tekst-slabi);">{{if .JedinicaMere}}{{.JedinicaMere}}{{else}}kom{{end}}</td>
<td class="kol-sek" data-label="Nab. cena" style="text-align:right;font-family:monospace;font-size:13px;">{{dinariCeli .NabavnaCena}}</td>
<td data-label="Knj. kol." style="text-align:right;font-family:monospace;font-weight:600;" id="knjizno-{{.ID}}">{{.Kolicina}}</td>
<td class="kol-sek" data-label="Knj. vrednost" style="text-align:right;font-family:monospace;font-size:13px;" id="knjvred-{{.ID}}"></td>
<td data-label="Stvarno kol." style="text-align:right;">
<input type="number"
class="popis-input"
name="kolicina_{{.ID}}"
id="input-{{.ID}}"
value="{{.Kolicina}}"
min="0"
data-knjizno="{{.Kolicina}}"
data-cena="{{printf "%.4f" .NabavnaCena}}"
data-id="{{.ID}}"
oninput="azurirajRed(this)">
</td>
<td data-label="Razlika kol." style="text-align:right;">
<span class="popis-razlika" id="razlika-{{.ID}}"></span>
</td>
<td class="kol-sek" data-label="Razlika vrednost" style="text-align:right;">
<span class="popis-vrednost-razlika" id="vrazlika-{{.ID}}"></span>
</td>
</tr>
{{end}}
</tbody>
<tfoot>
<tr style="font-weight:600;background:var(--pozadina);">
<td colspan="5" style="text-align:right;font-size:12px;color:var(--tekst-slabi);">UKUPNO:</td>
<td style="text-align:right;font-family:monospace;" id="suma-knjizno-kol"></td>
<td style="text-align:right;font-family:monospace;" id="suma-knjizno-vred"></td>
<td style="text-align:right;font-family:monospace;" id="suma-stvarno-kol"></td>
<td style="text-align:right;font-family:monospace;" id="suma-razlika-kol"></td>
<td style="text-align:right;font-family:monospace;" id="suma-razlika-vred"></td>
</tr>
</tfoot>
</table>
</div>
<!-- sumarni pregled manjkova/viškova -->
<div style="padding:14px 20px;border-top:0.5px solid var(--ivica);">
<div class="popis-suma">
<div class="popis-suma-stavka">
<span class="popis-suma-labela">Manjkovi (kom)</span>
<span class="popis-suma-vrednost boja-manjak" id="sum-manjak-kol">0</span>
</div>
<div class="popis-suma-stavka">
<span class="popis-suma-labela">Manjkovi (vrednost)</span>
<span class="popis-suma-vrednost boja-manjak" id="sum-manjak-vred">0,00</span>
</div>
<div class="popis-suma-stavka">
<span class="popis-suma-labela">Viškovi (kom)</span>
<span class="popis-suma-vrednost boja-visak" id="sum-visak-kol">0</span>
</div>
<div class="popis-suma-stavka">
<span class="popis-suma-labela">Viškovi (vrednost)</span>
<span class="popis-suma-vrednost boja-visak" id="sum-visak-vred">0,00</span>
</div>
</div>
</div>
<!-- dugme na dnu -->
<div style="padding:14px 20px;border-top:0.5px solid var(--ivica);display:flex;justify-content:flex-end;">
<button type="submit" class="btn-primarno">Sačuvaj popis</button>
</div>
{{end}}
</div>
</form>
</div>
<script>
var napomePoTipu = {
"godišnji": "Godišnji popis",
"vanredni": "Vanredni popis",
"preuzimanje": "Popis pri preuzimanju dužnosti"
};
function azurirajNapomenu() {
var tip = document.getElementById('tip-popisa').value;
document.getElementById('napomena-polje').value = napomePoTipu[tip] || "Godišnji popis";
}
function fmt(n) {
return n.toLocaleString('sr-RS', {minimumFractionDigits: 2, maximumFractionDigits: 2});
}
function azurirajRed(input) {
var id = input.dataset.id;
var knjizno = parseInt(input.dataset.knjizno, 10);
var cena = parseFloat(input.dataset.cena) || 0;
var stvarno = parseInt(input.value, 10);
var spanKol = document.getElementById('razlika-' + id);
var spanVred = document.getElementById('vrazlika-' + id);
if (isNaN(stvarno)) {
spanKol.textContent = '—'; spanVred.textContent = '—';
spanKol.style.color = ''; spanVred.style.color = '';
input.classList.remove('izmenjeno');
} else {
var razlika = stvarno - knjizno;
if (razlika === 0) {
spanKol.textContent = '—'; spanVred.textContent = '—';
spanKol.style.color = ''; spanVred.style.color = '';
input.classList.remove('izmenjeno');
} else {
var boja = razlika > 0 ? '#22c55e' : '#dc2626';
spanKol.textContent = (razlika > 0 ? '+' : '') + razlika;
spanVred.textContent = (razlika > 0 ? '+' : '') + fmt(razlika * cena);
spanKol.style.color = boja; spanVred.style.color = boja;
input.classList.add('izmenjeno');
}
}
azurirajSumu();
}
function azurirajSumu() {
var inputs = document.querySelectorAll('.popis-input');
var knjiznoKol = 0, knjiznoVred = 0, stvarnoKol = 0;
var manjKol = 0, manjVred = 0, visakKol = 0, visakVred = 0;
inputs.forEach(function(inp) {
var kn = parseInt(inp.dataset.knjizno, 10) || 0;
var cena = parseFloat(inp.dataset.cena) || 0;
var st = parseInt(inp.value, 10);
if (isNaN(st)) st = kn;
knjiznoKol += kn;
knjiznoVred += kn * cena;
stvarnoKol += st;
var r = st - kn;
if (r < 0) { manjKol += Math.abs(r); manjVred += Math.abs(r) * cena; }
if (r > 0) { visakKol += r; visakVred += r * cena; }
});
var razlikaKol = stvarnoKol - knjiznoKol;
var razlikaVred = visakVred - manjVred;
var el = function(id) { return document.getElementById(id); };
if (el('suma-knjizno-kol')) el('suma-knjizno-kol').textContent = knjiznoKol;
if (el('suma-knjizno-vred')) el('suma-knjizno-vred').textContent = fmt(knjiznoVred);
if (el('suma-stvarno-kol')) el('suma-stvarno-kol').textContent = stvarnoKol;
if (el('suma-razlika-kol')) {
el('suma-razlika-kol').textContent = (razlikaKol >= 0 ? '+' : '') + razlikaKol;
el('suma-razlika-kol').style.color = razlikaKol === 0 ? '' : (razlikaKol > 0 ? '#22c55e' : '#dc2626');
}
if (el('suma-razlika-vred')) {
el('suma-razlika-vred').textContent = (razlikaVred >= 0 ? '+' : '') + fmt(razlikaVred);
el('suma-razlika-vred').style.color = razlikaVred === 0 ? '' : (razlikaVred > 0 ? '#22c55e' : '#dc2626');
}
if (el('sum-manjak-kol')) el('sum-manjak-kol').textContent = manjKol;
if (el('sum-manjak-vred')) el('sum-manjak-vred').textContent = fmt(manjVred);
if (el('sum-visak-kol')) el('sum-visak-kol').textContent = visakKol;
if (el('sum-visak-vred')) el('sum-visak-vred').textContent = fmt(visakVred);
}
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.popis-input').forEach(function(inp) {
var id = inp.dataset.id;
var kn = parseInt(inp.dataset.knjizno, 10) || 0;
var cena = parseFloat(inp.dataset.cena) || 0;
var el = document.getElementById('knjvred-' + id);
if (el) el.textContent = fmt(kn * cena);
});
azurirajSumu();
});
</script>
{{end}}