Bezbednost: ispravke kontrole pristupa u admin i handler sloju

This commit is contained in:
2026-06-05 22:41:20 +02:00
parent ccc08aee08
commit 2b3636528f
44 changed files with 1310 additions and 480 deletions
+13 -1
View File
@@ -75,11 +75,13 @@
<span class="nav-tooltip">Dobavljači</span>
</a>
{{if index .Dozvole "izvestaj.pregled"}}
<a href="/izvestaji" class="nav-stavka {{if eq .Stranica "izvestaji"}}aktivan{{end}}">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg>
<span>Izveštaji</span>
<span class="nav-tooltip">Izveštaji</span>
</a>
{{end}}
<div class="nav-separator"></div>
<div class="nav-oznaka">Nalog</div>
@@ -90,7 +92,7 @@
<span class="nav-tooltip">Moj profil</span>
</a>
{{if eq .KorisnikUloga "superadmin"}}
{{if or (eq .KorisnikUloga "superadmin") (eq .KorisnikUloga "admin")}}
<a href="/admin/korisnici" class="nav-stavka {{if eq .Stranica "admin"}}aktivan{{end}}">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
<span>Korisnici</span>
@@ -98,14 +100,24 @@
</a>
{{end}}
{{if eq .KorisnikUloga "superadmin"}}
<a href="/admin/dozvole" class="nav-stavka {{if eq .Stranica "dozvole"}}aktivan{{end}}">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
<span>Dozvole</span>
<span class="nav-tooltip">Dozvole</span>
</a>
{{end}}
<div class="nav-separator"></div>
<div class="nav-oznaka">Sistem</div>
{{if index .Dozvole "podesavanja.pregled"}}
<a href="/podesavanja" class="nav-stavka {{if eq .Stranica "podesavanja"}}aktivan{{end}}">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06-.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
<span>Podešavanja</span>
<span class="nav-tooltip">Podešavanja</span>
</a>
{{end}}
</nav>
<div class="sidebar-dno">
+358
View File
@@ -0,0 +1,358 @@
{{template "base" .}}
{{define "naslov"}}Dozvole — NTech{{end}}
{{define "dodatni-css"}}
<style>
.dozvole-tabela tbody tr:nth-child(1) { animation-delay: 0.04s; }
.dozvole-tabela tbody tr:nth-child(2) { animation-delay: 0.08s; }
.dozvole-tabela tbody tr:nth-child(3) { animation-delay: 0.12s; }
.dozvole-tabela tbody tr:nth-child(4) { animation-delay: 0.16s; }
.dozvole-tabela tbody tr:nth-child(5) { animation-delay: 0.20s; }
.matrica-modul td {
padding: 8px 16px;
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--tekst-sporedni);
background: var(--pozadina);
border-top: 0.5px solid var(--ivica);
}
.matrica-checkbox { text-align: center; padding: 8px 16px; }
.matrica-checkbox input[type=checkbox] { width: 16px; height: 16px; cursor: pointer; accent-color: var(--sb-akcent); }
.matrica-checkbox input[type=checkbox]:disabled { cursor: default; opacity: 0.5; }
</style>
{{end}}
{{define "sadrzaj"}}
<div style="display:flex;flex-direction:column;gap:20px;">
{{if .Sacuvano}}
<div class="poruka-uspeh">Promene su uspešno sačuvane.</div>
{{end}}
{{if .Greska}}
<div class="poruka-greska">Greška pri čuvanju promena.</div>
{{end}}
<!-- matrica dozvola — editabilna forma -->
<div class="kartica animiraj" style="padding:0;overflow:hidden;">
<div style="padding:14px 16px;border-bottom:0.5px solid var(--ivica);">
<span style="font-size:15px;font-weight:500;color:var(--tekst-glavni);">Dozvole po ulogama</span>
</div>
<form method="POST" action="/admin/dozvole/sacuvaj">
<div style="overflow-x:auto;">
<table style="width:100%;border-collapse:collapse;">
<thead>
<tr style="border-bottom:0.5px solid var(--ivica);">
<th style="padding:10px 16px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-sporedni);min-width:200px;">Akcija</th>
<th style="padding:10px 16px;text-align:center;font-size:12px;font-weight:500;color:var(--tekst-sporedni);width:110px;">Radnik</th>
<th style="padding:10px 16px;text-align:center;font-size:12px;font-weight:500;color:var(--tekst-sporedni);width:110px;">Admin</th>
</tr>
</thead>
<tbody>
<!-- Magacin -->
<tr class="matrica-modul"><td colspan="3">Magacin</td></tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Pregled artikala</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__artikal.pregled" {{if index .DozvoleRadnik "artikal.pregled"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__artikal.pregled" {{if index .DozvoleAdmin "artikal.pregled"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Dodavanje artikala</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__artikal.dodaj" {{if index .DozvoleRadnik "artikal.dodaj"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__artikal.dodaj" {{if index .DozvoleAdmin "artikal.dodaj"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Izmena artikala</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__artikal.izmeni" {{if index .DozvoleRadnik "artikal.izmeni"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__artikal.izmeni" {{if index .DozvoleAdmin "artikal.izmeni"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Brisanje artikala</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__artikal.obrisi" {{if index .DozvoleRadnik "artikal.obrisi"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__artikal.obrisi" {{if index .DozvoleAdmin "artikal.obrisi"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Premeštanje artikala</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__artikal.premesti" {{if index .DozvoleRadnik "artikal.premesti"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__artikal.premesti" {{if index .DozvoleAdmin "artikal.premesti"}}checked{{end}}></td>
</tr>
<!-- Kategorije -->
<tr class="matrica-modul"><td colspan="3">Kategorije</td></tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Pregled kategorija</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__kategorija.pregled" {{if index .DozvoleRadnik "kategorija.pregled"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__kategorija.pregled" {{if index .DozvoleAdmin "kategorija.pregled"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Dodavanje kategorija</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__kategorija.dodaj" {{if index .DozvoleRadnik "kategorija.dodaj"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__kategorija.dodaj" {{if index .DozvoleAdmin "kategorija.dodaj"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Izmena kategorija</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__kategorija.izmeni" {{if index .DozvoleRadnik "kategorija.izmeni"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__kategorija.izmeni" {{if index .DozvoleAdmin "kategorija.izmeni"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Brisanje kategorija</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__kategorija.obrisi" {{if index .DozvoleRadnik "kategorija.obrisi"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__kategorija.obrisi" {{if index .DozvoleAdmin "kategorija.obrisi"}}checked{{end}}></td>
</tr>
<!-- Nabavke -->
<tr class="matrica-modul"><td colspan="3">Nabavke</td></tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Pregled nabavki</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__nabavka.pregled" {{if index .DozvoleRadnik "nabavka.pregled"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__nabavka.pregled" {{if index .DozvoleAdmin "nabavka.pregled"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Dodavanje nabavki</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__nabavka.dodaj" {{if index .DozvoleRadnik "nabavka.dodaj"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__nabavka.dodaj" {{if index .DozvoleAdmin "nabavka.dodaj"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Brisanje nabavki</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__nabavka.obrisi" {{if index .DozvoleRadnik "nabavka.obrisi"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__nabavka.obrisi" {{if index .DozvoleAdmin "nabavka.obrisi"}}checked{{end}}></td>
</tr>
<!-- Dobavljači -->
<tr class="matrica-modul"><td colspan="3">Dobavljači</td></tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Pregled dobavljača</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__dobavljac.pregled" {{if index .DozvoleRadnik "dobavljac.pregled"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__dobavljac.pregled" {{if index .DozvoleAdmin "dobavljac.pregled"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Dodavanje dobavljača</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__dobavljac.dodaj" {{if index .DozvoleRadnik "dobavljac.dodaj"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__dobavljac.dodaj" {{if index .DozvoleAdmin "dobavljac.dodaj"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Izmena dobavljača</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__dobavljac.izmeni" {{if index .DozvoleRadnik "dobavljac.izmeni"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__dobavljac.izmeni" {{if index .DozvoleAdmin "dobavljac.izmeni"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Brisanje dobavljača</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__dobavljac.obrisi" {{if index .DozvoleRadnik "dobavljac.obrisi"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__dobavljac.obrisi" {{if index .DozvoleAdmin "dobavljac.obrisi"}}checked{{end}}></td>
</tr>
<!-- Servis -->
<tr class="matrica-modul"><td colspan="3">Servis</td></tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Pregled servisnih naloga</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__servis.pregled" {{if index .DozvoleRadnik "servis.pregled"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__servis.pregled" {{if index .DozvoleAdmin "servis.pregled"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Dodavanje servisnih naloga</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__servis.dodaj" {{if index .DozvoleRadnik "servis.dodaj"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__servis.dodaj" {{if index .DozvoleAdmin "servis.dodaj"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Izmena servisnih naloga</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__servis.izmeni" {{if index .DozvoleRadnik "servis.izmeni"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__servis.izmeni" {{if index .DozvoleAdmin "servis.izmeni"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Brisanje servisnih naloga</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__servis.obrisi" {{if index .DozvoleRadnik "servis.obrisi"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__servis.obrisi" {{if index .DozvoleAdmin "servis.obrisi"}}checked{{end}}></td>
</tr>
<!-- Prodaja -->
<tr class="matrica-modul"><td colspan="3">Prodaja</td></tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Pregled prodaje</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__prodaja.pregled" {{if index .DozvoleRadnik "prodaja.pregled"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__prodaja.pregled" {{if index .DozvoleAdmin "prodaja.pregled"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Dodavanje prodaje</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__prodaja.dodaj" {{if index .DozvoleRadnik "prodaja.dodaj"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__prodaja.dodaj" {{if index .DozvoleAdmin "prodaja.dodaj"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Brisanje prodaje</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__prodaja.obrisi" {{if index .DozvoleRadnik "prodaja.obrisi"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__prodaja.obrisi" {{if index .DozvoleAdmin "prodaja.obrisi"}}checked{{end}}></td>
</tr>
<!-- Klijenti -->
<tr class="matrica-modul"><td colspan="3">Klijenti</td></tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Pregled klijenata</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__klijent.pregled" {{if index .DozvoleRadnik "klijent.pregled"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__klijent.pregled" {{if index .DozvoleAdmin "klijent.pregled"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Dodavanje klijenata</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__klijent.dodaj" {{if index .DozvoleRadnik "klijent.dodaj"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__klijent.dodaj" {{if index .DozvoleAdmin "klijent.dodaj"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Izmena klijenata</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__klijent.izmeni" {{if index .DozvoleRadnik "klijent.izmeni"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__klijent.izmeni" {{if index .DozvoleAdmin "klijent.izmeni"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Brisanje klijenata</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__klijent.obrisi" {{if index .DozvoleRadnik "klijent.obrisi"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__klijent.obrisi" {{if index .DozvoleAdmin "klijent.obrisi"}}checked{{end}}></td>
</tr>
<!-- Podsetnici -->
<tr class="matrica-modul"><td colspan="3">Podsetnici</td></tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Pregled podsetnika</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__podsetnik.pregled" {{if index .DozvoleRadnik "podsetnik.pregled"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__podsetnik.pregled" {{if index .DozvoleAdmin "podsetnik.pregled"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Dodavanje podsetnika</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__podsetnik.dodaj" {{if index .DozvoleRadnik "podsetnik.dodaj"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__podsetnik.dodaj" {{if index .DozvoleAdmin "podsetnik.dodaj"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Izmena podsetnika</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__podsetnik.izmeni" {{if index .DozvoleRadnik "podsetnik.izmeni"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__podsetnik.izmeni" {{if index .DozvoleAdmin "podsetnik.izmeni"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Brisanje podsetnika</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__podsetnik.obrisi" {{if index .DozvoleRadnik "podsetnik.obrisi"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__podsetnik.obrisi" {{if index .DozvoleAdmin "podsetnik.obrisi"}}checked{{end}}></td>
</tr>
<!-- Izveštaji -->
<tr class="matrica-modul"><td colspan="3">Izveštaji</td></tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Pregled izveštaja</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__izvestaj.pregled" {{if index .DozvoleRadnik "izvestaj.pregled"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__izvestaj.pregled" {{if index .DozvoleAdmin "izvestaj.pregled"}}checked{{end}}></td>
</tr>
<!-- Podešavanja -->
<tr class="matrica-modul"><td colspan="3">Podešavanja</td></tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Pregled podešavanja</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__podesavanja.pregled" {{if index .DozvoleRadnik "podesavanja.pregled"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__podesavanja.pregled" {{if index .DozvoleAdmin "podesavanja.pregled"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Izmena podešavanja</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__podesavanja.izmeni" {{if index .DozvoleRadnik "podesavanja.izmeni"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__podesavanja.izmeni" {{if index .DozvoleAdmin "podesavanja.izmeni"}}checked{{end}}></td>
</tr>
<!-- Korisnici -->
<tr class="matrica-modul"><td colspan="3">Korisnici</td></tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Pregled korisnika</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__korisnik.pregled" {{if index .DozvoleRadnik "korisnik.pregled"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__korisnik.pregled" {{if index .DozvoleAdmin "korisnik.pregled"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Dodavanje korisnika</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__korisnik.dodaj" {{if index .DozvoleRadnik "korisnik.dodaj"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__korisnik.dodaj" {{if index .DozvoleAdmin "korisnik.dodaj"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Izmena korisnika</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__korisnik.izmeni" {{if index .DozvoleRadnik "korisnik.izmeni"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__korisnik.izmeni" {{if index .DozvoleAdmin "korisnik.izmeni"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Brisanje korisnika</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__korisnik.obrisi" {{if index .DozvoleRadnik "korisnik.obrisi"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__korisnik.obrisi" {{if index .DozvoleAdmin "korisnik.obrisi"}}checked{{end}}></td>
</tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Promena uloge korisnika</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__korisnik.uloga" {{if index .DozvoleRadnik "korisnik.uloga"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__korisnik.uloga" {{if index .DozvoleAdmin "korisnik.uloga"}}checked{{end}}></td>
</tr>
<!-- Backup -->
<tr class="matrica-modul"><td colspan="3">Backup</td></tr>
<tr style="border-bottom:0.5px solid var(--ivica);">
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Pregled rezervnih kopija</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__backup.pregled" {{if index .DozvoleRadnik "backup.pregled"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__backup.pregled" {{if index .DozvoleAdmin "backup.pregled"}}checked{{end}}></td>
</tr>
<tr>
<td style="padding:9px 16px;font-size:13px;color:var(--tekst-glavni);">Pokretanje bekapa</td>
<td class="matrica-checkbox"><input type="checkbox" name="radnik__backup.pokreni" {{if index .DozvoleRadnik "backup.pokreni"}}checked{{end}}></td>
<td class="matrica-checkbox"><input type="checkbox" name="admin__backup.pokreni" {{if index .DozvoleAdmin "backup.pokreni"}}checked{{end}}></td>
</tr>
</tbody>
</table>
</div>
<!-- dugmad za čuvanje i reset -->
<div style="display:flex;justify-content:flex-end;gap:10px;padding:16px;border-top:0.5px solid var(--ivica);">
<button type="submit" form="forma-reset" class="btn-sekundarno"
data-potvrda="Resetovati sve dozvole na podrazumevane vrednosti? Ovo će poništiti sve prilagođene promene.">
Reset na podrazumevano
</button>
<button type="submit" class="btn-primarno">Sačuvaj promene</button>
</div>
</form>
<!-- zasebna forma za reset, bez vidljivih elemenata -->
<form id="forma-reset" method="POST" action="/admin/dozvole/reset"></form>
</div>
</div>
{{end}}
@@ -4,10 +4,6 @@
{{define "dodatni-css"}}
<style>
@keyframes slideDown {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}
.poruka-animacija { animation: slideDown 0.3s ease forwards; }
.korisnici-tabela tbody tr:nth-child(1) { animation-delay: 0.04s; }
+3
View File
@@ -17,6 +17,9 @@
{{end}}
{{define "sadrzaj"}}
{{if .FlashGreska}}
<div class="poruka-greska animiraj" style="margin-bottom:16px;">{{.FlashGreska}}</div>
{{end}}
<div class="grid grid-cols-2 md:grid-cols-5 gap-3 mb-6">
<!-- stat kartice -->
<div class="kartica dash-stat animiraj">
+6 -19
View File
@@ -4,9 +4,7 @@
{{define "dodatni-css"}}
<style>
.greska-animacija {
animation: shake 0.4s ease;
}
.greska-animacija { animation: shake 0.4s ease; }
</style>
{{end}}
@@ -14,10 +12,8 @@
<div style="width:100%;">
<!-- nazad dugme -->
<a href="/dobavljaci"
style="display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--tekst-sporedni);text-decoration:none;margin-bottom:20px;transition:color 0.2s;"
onmouseover="this.style.color='var(--tekst-glavni)'" onmouseout="this.style.color='var(--tekst-sporedni)'">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
<a href="/dobavljaci" class="nazad-link">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="15 18 9 12 15 6"/></svg>
Nazad na dobavljače
</a>
@@ -29,10 +25,7 @@
</div>
{{if .Greska}}
<div class="greska-animacija"
style="background:var(--kartica);border:0.5px solid #dc2626;border-radius:8px;padding:10px 14px;margin-bottom:16px;font-size:13px;color:#dc2626;">
{{.Greska}}
</div>
<div class="poruka-greska greska-animacija">{{.Greska}}</div>
{{end}}
<form method="POST" action="{{if .Izmena}}/dobavljaci/izmeni/{{.Dobavljac.ID}}{{else}}/dobavljaci/novi{{end}}">
@@ -82,14 +75,8 @@
<!-- dugmad -->
<div style="display:flex;justify-content:flex-end;gap:10px;margin-top:6px;">
<a href="/dobavljaci"
style="padding:9px 20px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;color:var(--tekst-sporedni);text-decoration:none;transition:background 0.2s;"
onmouseover="this.style.background='var(--pozadina)'" onmouseout="this.style.background=''">
Odustani
</a>
<button type="submit"
style="padding:9px 20px;background:var(--sb-akcent);color:#fff;border:none;border-radius:8px;font-size:14px;font-weight:500;cursor:pointer;transition:opacity 0.2s;"
onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">
<a href="/dobavljaci" class="btn-sekundarno">Odustani</a>
<button type="submit" class="btn-primarno">
{{if .Izmena}}Sačuvaj izmene{{else}}Dodaj dobavljača{{end}}
</button>
</div>
+11 -23
View File
@@ -4,14 +4,7 @@
{{define "dodatni-css"}}
<style>
@keyframes slideDown {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}
.poruka-animacija {
animation: slideDown 0.3s ease forwards;
}
.poruka-animacija { animation: slideDown 0.3s ease forwards; }
/* stagger — svaki red se pojavljuje malo kasnije */
.dobavljaci-tabela tbody tr:nth-child(1) { animation-delay: 0.04s; }
@@ -56,11 +49,7 @@
<!-- gornja traka: dugme + pretraga -->
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:center;">
<a href="/dobavljaci/novi"
style="padding:8px 16px;background:var(--sb-akcent);color:#fff;border-radius:8px;font-size:14px;font-weight:500;text-decoration:none;white-space:nowrap;transition:opacity 0.2s;"
onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">
+ Novi dobavljač
</a>
<a href="/dobavljaci/novi" class="btn-primarno">+ Novi dobavljač</a>
<form method="GET" action="/dobavljaci" style="display:flex;gap:8px;flex:1;min-width:200px;">
<input type="text" name="pretraga" value="{{.Pretraga}}"
placeholder="Pretraži dobavljače..."
@@ -86,9 +75,7 @@
</thead>
<tbody>
{{range .Dobavljaci}}
<tr class="animiraj" style="border-bottom:0.5px solid var(--ivica);transition:background 0.15s;"
onmouseover="this.style.background='var(--pozadina)'"
onmouseout="this.style.background=''">
<tr class="animiraj red-tabele">
<td style="padding:12px 16px;font-size:14px;font-weight:500;color:var(--tekst-glavni);">{{.Naziv}}</td>
<td style="padding:12px 16px;font-size:13px;color:var(--tekst-sporedni);">
{{if .KontaktOsoba}}{{.KontaktOsoba}}{{else}}—{{end}}
@@ -104,14 +91,14 @@
<a href="/dobavljaci/izmeni/{{.ID}}" class="btn-primarno-malo">
Izmeni
</a>
{{if index $.Dozvole "dobavljac.obrisi"}}
<form method="POST" action="/dobavljaci/obrisi/{{.ID}}" style="display:inline;">
<button type="submit"
onclick="return confirm('Da li ste sigurni da želite da obrišete dobavljača {{.Naziv}}?')"
style="padding:4px 10px;background:#dc2626;color:#fff;border:none;border-radius:6px;font-size:12px;cursor:pointer;transition:opacity 0.2s;"
onmouseover="this.style.opacity='0.8'" onmouseout="this.style.opacity='1'">
<button type="submit" class="btn-obrisi-malo"
data-potvrda="Da li ste sigurni da želite da obrišete dobavljača {{.Naziv}}?">
Obriši
</button>
</form>
{{end}}
</div>
</td>
</tr>
@@ -137,13 +124,14 @@
<a href="/dobavljaci/izmeni/{{.ID}}" class="btn-primarno-malo">
Izmeni
</a>
{{if index $.Dozvole "dobavljac.obrisi"}}
<form method="POST" action="/dobavljaci/obrisi/{{.ID}}" style="display:inline;">
<button type="submit"
onclick="return confirm('Da li ste sigurni da želite da obrišete dobavljača {{.Naziv}}?')"
style="padding:4px 10px;background:#dc2626;color:#fff;border:none;border-radius:6px;font-size:12px;cursor:pointer;">
<button type="submit" class="btn-obrisi-malo"
data-potvrda="Da li ste sigurni da želite da obrišete dobavljača {{.Naziv}}?">
Obriši
</button>
</form>
{{end}}
</div>
</div>
<div style="display:flex;flex-direction:column;gap:6px;">
+6 -7
View File
@@ -4,10 +4,6 @@
{{define "dodatni-css"}}
<style>
@keyframes slideDown {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}
.poruka-animacija { animation: slideDown 0.3s ease forwards; }
.kat-forma-kartica {
@@ -41,6 +37,7 @@
Nazad na magacin
</a>
{{if index $.Dozvole "kategorija.dodaj"}}
<!-- forma za novu kategoriju -->
<div class="kartica kat-forma-kartica animiraj">
<div style="margin-bottom:16px;padding-bottom:12px;border-bottom:0.5px solid var(--ivica);">
@@ -69,6 +66,7 @@
</div>
</form>
</div>
{{end}}
<!-- lista kategorija -->
<div class="kartica" style="padding:0;overflow:hidden;">
@@ -83,11 +81,12 @@
<div style="font-size:12px;color:var(--tekst-sporedni);margin-top:2px;">{{.Opis}}</div>
{{end}}
</div>
<a href="/magacin/kategorije/obrisi/{{.ID}}"
onclick="return confirm('Da li ste sigurni da želite da obrišete ovu kategoriju?')"
style="padding:4px 10px;background:#dc2626;color:#fff;border-radius:6px;font-size:12px;text-decoration:none;white-space:nowrap;">
{{if index $.Dozvole "kategorija.obrisi"}}
<a href="/magacin/kategorije/obrisi/{{.ID}}" class="btn-obrisi-malo"
data-potvrda="Da li ste sigurni da želite da obrišete ovu kategoriju?">
Obriši
</a>
{{end}}
</div>
{{else}}
<div style="padding:24px;text-align:center;font-size:14px;color:var(--tekst-sporedni);">
+6 -23
View File
@@ -4,13 +4,7 @@
{{define "dodatni-css"}}
<style>
.greska-animacija {
animation: shake 0.4s ease;
}
@media (max-width: 768px) {
.forma-grid-2 { grid-template-columns: 1fr !important; }
}
.greska-animacija { animation: shake 0.4s ease; }
</style>
{{end}}
@@ -18,10 +12,8 @@
<div style="width:100%;">
<!-- nazad dugme -->
<a href="/klijenti"
style="display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--tekst-sporedni);text-decoration:none;margin-bottom:20px;transition:color 0.2s;"
onmouseover="this.style.color='var(--tekst-glavni)'" onmouseout="this.style.color='var(--tekst-sporedni)'">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
<a href="/klijenti" class="nazad-link">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="15 18 9 12 15 6"/></svg>
Nazad na klijente
</a>
@@ -33,10 +25,7 @@
</div>
{{if .Greska}}
<div class="greska-animacija"
style="background:var(--kartica);border:0.5px solid #dc2626;border-radius:8px;padding:10px 14px;margin-bottom:16px;font-size:13px;color:#dc2626;">
{{.Greska}}
</div>
<div class="poruka-greska greska-animacija">{{.Greska}}</div>
{{end}}
<form method="POST" action="{{if .Izmena}}/klijenti/izmeni/{{.Klijent.ID}}{{else}}/klijenti/novi{{end}}">
@@ -120,14 +109,8 @@
<!-- dugmad -->
<div style="display:flex;justify-content:flex-end;gap:10px;margin-top:6px;">
<a href="/klijenti"
style="padding:9px 20px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;color:var(--tekst-sporedni);text-decoration:none;transition:background 0.2s;"
onmouseover="this.style.background='var(--pozadina)'" onmouseout="this.style.background=''">
Odustani
</a>
<button type="submit"
style="padding:9px 20px;background:var(--sb-akcent);color:#fff;border:none;border-radius:8px;font-size:14px;font-weight:500;cursor:pointer;transition:opacity 0.2s;"
onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">
<a href="/klijenti" class="btn-sekundarno">Odustani</a>
<button type="submit" class="btn-primarno">
{{if .Izmena}}Sačuvaj izmene{{else}}Dodaj klijenta{{end}}
</button>
</div>
+11 -23
View File
@@ -4,14 +4,7 @@
{{define "dodatni-css"}}
<style>
@keyframes slideDown {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}
.poruka-animacija {
animation: slideDown 0.3s ease forwards;
}
.poruka-animacija { animation: slideDown 0.3s ease forwards; }
.klijenti-tabela tbody tr:nth-child(1) { animation-delay: 0.04s; }
.klijenti-tabela tbody tr:nth-child(2) { animation-delay: 0.08s; }
@@ -55,11 +48,7 @@
<!-- gornja traka: dugme + pretraga -->
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:center;">
<a href="/klijenti/novi"
style="padding:8px 16px;background:var(--sb-akcent);color:#fff;border-radius:8px;font-size:14px;font-weight:500;text-decoration:none;white-space:nowrap;transition:opacity 0.2s;"
onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">
+ Novi klijent
</a>
<a href="/klijenti/novi" class="btn-primarno">+ Novi klijent</a>
<form method="GET" action="/klijenti" style="display:flex;gap:8px;flex:1;min-width:200px;">
<input type="text" name="pretraga" value="{{.Pretraga}}"
placeholder="Pretraži po imenu ili nazivu firme..."
@@ -85,9 +74,7 @@
</thead>
<tbody>
{{range .Klijenti}}
<tr class="animiraj" style="border-bottom:0.5px solid var(--ivica);transition:background 0.15s;"
onmouseover="this.style.background='var(--pozadina)'"
onmouseout="this.style.background=''">
<tr class="animiraj red-tabele">
<td style="padding:12px 16px;">
{{if .NazivFirme}}
<div style="font-size:14px;font-weight:500;color:var(--tekst-glavni);">{{.NazivFirme}}</div>
@@ -112,14 +99,14 @@
<a href="/klijenti/izmeni/{{.ID}}" class="btn-primarno-malo">
Izmeni
</a>
{{if index $.Dozvole "klijent.obrisi"}}
<form method="POST" action="/klijenti/obrisi/{{.ID}}" style="display:inline;">
<button type="submit"
onclick="return confirm('Da li ste sigurni da želite da obrišete klijenta?')"
style="padding:4px 10px;background:#dc2626;color:#fff;border:none;border-radius:6px;font-size:12px;cursor:pointer;transition:opacity 0.2s;"
onmouseover="this.style.opacity='0.8'" onmouseout="this.style.opacity='1'">
<button type="submit" class="btn-obrisi-malo"
data-potvrda="Da li ste sigurni da želite da obrišete klijenta?">
Obriši
</button>
</form>
{{end}}
</div>
</td>
</tr>
@@ -154,13 +141,14 @@
<a href="/klijenti/izmeni/{{.ID}}" class="btn-primarno-malo">
Izmeni
</a>
{{if index $.Dozvole "klijent.obrisi"}}
<form method="POST" action="/klijenti/obrisi/{{.ID}}" style="display:inline;">
<button type="submit"
onclick="return confirm('Da li ste sigurni da želite da obrišete klijenta?')"
style="padding:4px 10px;background:#dc2626;color:#fff;border:none;border-radius:6px;font-size:12px;cursor:pointer;">
<button type="submit" class="btn-obrisi-malo"
data-potvrda="Da li ste sigurni da želite da obrišete klijenta?">
Obriši
</button>
</form>
{{end}}
</div>
</div>
<div style="display:flex;flex-direction:column;gap:6px;">
+67 -13
View File
@@ -14,6 +14,23 @@
.magacin-tabela tbody tr:nth-child(8) { animation-delay: 0.32s; }
.magacin-tabela tbody tr:nth-child(9) { animation-delay: 0.36s; }
.magacin-tabela tbody tr:nth-child(10) { animation-delay: 0.40s; }
.magacin-kartice {
display: none;
flex-direction: column;
gap: 12px;
}
.magacin-kartica:nth-child(1) { animation-delay: 0.04s; }
.magacin-kartica:nth-child(2) { animation-delay: 0.10s; }
.magacin-kartica:nth-child(3) { animation-delay: 0.16s; }
.magacin-kartica:nth-child(4) { animation-delay: 0.22s; }
.magacin-kartica:nth-child(5) { animation-delay: 0.28s; }
@media (max-width: 768px) {
.magacin-tabela { display: none; }
.magacin-kartice { display: flex; }
}
</style>
{{end}}
@@ -29,13 +46,8 @@
<!-- dugmad -->
<div style="display:flex;gap:10px;flex-wrap:wrap;">
<a href="/magacin/novi"
style="padding:8px 16px;background:var(--sb-akcent);color:#fff;border-radius:8px;font-size:14px;font-weight:500;text-decoration:none;white-space:nowrap;">
+ Novi artikal
</a>
<a href="/magacin/kategorije" class="btn-primarno">
Kategorije
</a>
<a href="/magacin/novi" class="btn-primarno">+ Novi artikal</a>
<a href="/magacin/kategorije" class="btn-primarno">Kategorije</a>
</div>
<!-- pretraga i filteri -->
@@ -76,9 +88,7 @@
</thead>
<tbody>
{{range .Artikli}}
<tr class="animiraj" style="border-bottom:0.5px solid var(--ivica);transition:background 0.15s;"
onmouseover="this.style.background='var(--pozadina)'"
onmouseout="this.style.background=''">
<tr class="animiraj red-tabele">
<td style="padding:12px 16px;font-size:14px;color:var(--tekst-glavni);">{{.Naziv}}</td>
<td style="padding:12px 16px;font-size:13px;color:var(--tekst-sporedni);">
{{if .KategorijaNaziv}}{{.KategorijaNaziv}}{{else}}—{{end}}
@@ -97,11 +107,12 @@
<a href="/magacin/izmeni/{{.ID}}" class="btn-primarno-malo">
Izmeni
</a>
<a href="/magacin/obrisi/{{.ID}}"
onclick="return confirm('Da li ste sigurni da želite da obrišete ovaj artikal?')"
style="padding:4px 10px;background:#dc2626;color:#fff;border-radius:6px;font-size:12px;text-decoration:none;">
{{if index $.Dozvole "artikal.obrisi"}}
<a href="/magacin/obrisi/{{.ID}}" class="btn-obrisi-malo"
data-potvrda="Da li ste sigurni da želite da obrišete ovaj artikal?">
Obriši
</a>
{{end}}
</div>
</td>
</tr>
@@ -117,5 +128,48 @@
</div>
</div>
<!-- mobilne kartice -->
<div class="magacin-kartice">
{{range .Artikli}}
<div class="kartica magacin-kartica animiraj">
<div style="display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:10px;">
<div>
<div style="font-size:15px;font-weight:500;color:var(--tekst-glavni);">{{.Naziv}}</div>
{{if .KategorijaNaziv}}
<div style="font-size:12px;color:var(--tekst-sporedni);margin-top:2px;">{{.KategorijaNaziv}}</div>
{{end}}
</div>
<div style="display:flex;gap:8px;flex-shrink:0;">
<a href="/magacin/izmeni/{{.ID}}" class="btn-primarno-malo">Izmeni</a>
{{if index $.Dozvole "artikal.obrisi"}}
<a href="/magacin/obrisi/{{.ID}}" class="btn-obrisi-malo"
data-potvrda="Da li ste sigurni da želite da obrišete ovaj artikal?">
Obriši
</a>
{{end}}
</div>
</div>
<div style="display:flex;flex-wrap:wrap;gap:10px;">
<div style="font-size:13px;color:var(--tekst-sporedni);">
<span style="color:var(--tekst-glavni);font-weight:500;">Količina:</span>
<span style="font-weight:500;color:{{if .KriticnaZaliha}}#dc2626{{else}}#16a34a{{end}};">{{.Kolicina}}</span>
</div>
<div style="font-size:13px;color:var(--tekst-sporedni);">
<span style="color:var(--tekst-glavni);font-weight:500;">Cena:</span> {{printf "%.0f" .ProdajnaCena}} din
</div>
{{if .Lokacija}}
<div style="font-size:13px;color:var(--tekst-sporedni);">
<span style="color:var(--tekst-glavni);font-weight:500;">Lokacija:</span> {{.Lokacija}}
</div>
{{end}}
</div>
</div>
{{else}}
<div style="padding:32px;text-align:center;font-size:14px;color:var(--tekst-sporedni);">
Nema artikala. <a href="/magacin/novi" style="color:var(--sb-akcent);">Dodaj prvi artikal.</a>
</div>
{{end}}
</div>
</div>
{{end}}
+11 -11
View File
@@ -2,12 +2,18 @@
{{define "naslov"}}{{if .Izmena}}Izmeni artikal{{else}}Novi artikal{{end}} — NTech{{end}}
{{define "dodatni-css"}}
<style>
.greska-animacija { animation: shake 0.4s ease; }
</style>
{{end}}
{{define "sadrzaj"}}
<div style="width:100%;">
<!-- nazad dugme -->
<a href="/magacin" style="display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--tekst-sporedni);text-decoration:none;margin-bottom:20px;">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
<a href="/magacin" class="nazad-link">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="15 18 9 12 15 6"/></svg>
Nazad na magacin
</a>
@@ -19,9 +25,7 @@
</div>
{{if .Greska}}
<div style="background:var(--kartica);border:0.5px solid #dc2626;border-radius:8px;padding:10px 14px;margin-bottom:16px;font-size:13px;color:#dc2626;">
{{.Greska}}
</div>
<div class="poruka-greska greska-animacija">{{.Greska}}</div>
{{end}}
<form method="POST" action="{{if .Izmena}}/magacin/izmeni/{{.Artikal.ID}}{{else}}/magacin/novi{{end}}">
@@ -91,12 +95,8 @@
<!-- dugmad -->
<div style="display:flex;justify-content:flex-end;gap:10px;margin-top:6px;">
<a href="/magacin"
style="padding:9px 20px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;color:var(--tekst-sporedni);text-decoration:none;">
Odustani
</a>
<button type="submit"
style="padding:9px 20px;background:var(--sb-akcent);color:#fff;border:none;border-radius:8px;font-size:14px;font-weight:500;cursor:pointer;">
<a href="/magacin" class="btn-sekundarno">Odustani</a>
<button type="submit" class="btn-primarno">
{{if .Izmena}}Sačuvaj izmene{{else}}Dodaj artikal{{end}}
</button>
</div>
+5 -11
View File
@@ -31,10 +31,8 @@
<div style="display:flex;flex-direction:column;gap:16px;">
<!-- nazad dugme -->
<a href="/nabavke"
style="display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--tekst-sporedni);text-decoration:none;transition:color 0.2s;"
onmouseover="this.style.color='var(--tekst-glavni)'" onmouseout="this.style.color='var(--tekst-sporedni)'">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
<a href="/nabavke" class="nazad-link">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="15 18 9 12 15 6"/></svg>
Nazad na nabavke
</a>
@@ -86,9 +84,7 @@
</thead>
<tbody>
{{range .Stavke}}
<tr class="animiraj" style="border-bottom:0.5px solid var(--ivica);transition:background 0.15s;"
onmouseover="this.style.background='var(--pozadina)'"
onmouseout="this.style.background=''">
<tr class="animiraj red-tabele">
<td style="padding:10px 16px;font-size:14px;color:var(--tekst-glavni);">{{.ArtikalNaziv}}</td>
<td style="padding:10px 16px;text-align:center;font-size:14px;color:var(--tekst-glavni);">{{.Kolicina}}</td>
<td style="padding:10px 16px;text-align:right;font-size:14px;color:var(--tekst-sporedni);">{{printf "%.2f" .CenaPoKomadu}} din</td>
@@ -152,10 +148,8 @@
</div>
</div>
<form method="POST" action="/nabavke/obrisi/{{.Nabavka.ID}}">
<button type="submit"
onclick="return confirm('Da li ste sigurni da želite da obrišete ovu nabavku?\n\nBrisanje ne vraća količine artikala u magacin.')"
style="padding:9px 20px;background:#dc2626;color:#fff;border:none;border-radius:8px;font-size:14px;font-weight:500;cursor:pointer;white-space:nowrap;transition:opacity 0.2s;"
onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">
<button type="submit" class="btn-primarno" style="background:#dc2626;"
data-potvrda="Da li ste sigurni da želite da obrišete ovu nabavku? Brisanje ne vraća količine artikala u magacin.">
Obriši nabavku
</button>
</form>
+13 -35
View File
@@ -18,7 +18,7 @@
@media (max-width: 768px) {
.stavke-tabela-wrapper { display: none; }
.stavke-kartice { display: flex !important; }
.stavke-kartice { display: flex !important; }
}
</style>
{{end}}
@@ -84,7 +84,7 @@
params.append('naziv', this.modalNaziv.trim());
if (this.modalKategorijaID) params.append('kategorija_id', this.modalKategorijaID);
if (this.modalCena) params.append('prodajna_cena', this.modalCena);
params.append('_csrf', document.querySelector('meta[name="csrf-token"]')?.content || '');
params.append('_csrf', document.querySelector('meta[name=csrf-token]')?.content || '');
try {
const odgovor = await fetch('/magacin/novi', {
@@ -113,20 +113,15 @@
}">
<!-- nazad dugme -->
<a href="/nabavke"
style="display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--tekst-sporedni);text-decoration:none;margin-bottom:20px;transition:color 0.2s;"
onmouseover="this.style.color='var(--tekst-glavni)'" onmouseout="this.style.color='var(--tekst-sporedni)'">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
<a href="/nabavke" class="nazad-link">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="15 18 9 12 15 6"/></svg>
Nazad na nabavke
</a>
<form method="POST" action="/nabavke/nova">
{{if .Greska}}
<div class="greska-animacija"
style="background:var(--kartica);border:0.5px solid #dc2626;border-radius:8px;padding:10px 14px;margin-bottom:16px;font-size:13px;color:#dc2626;">
{{.Greska}}
</div>
<div class="poruka-greska greska-animacija">{{.Greska}}</div>
{{end}}
<!-- zaglavlje nabavke -->
@@ -275,16 +270,8 @@
<!-- dugmad forme -->
<div style="display:flex;justify-content:flex-end;gap:10px;">
<a href="/nabavke"
style="padding:9px 20px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;color:var(--tekst-sporedni);text-decoration:none;transition:background 0.2s;"
onmouseover="this.style.background='var(--pozadina)'" onmouseout="this.style.background=''">
Odustani
</a>
<button type="submit"
style="padding:9px 20px;background:var(--sb-akcent);color:#fff;border:none;border-radius:8px;font-size:14px;font-weight:500;cursor:pointer;transition:opacity 0.2s;"
onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">
Sačuvaj nabavku
</button>
<a href="/nabavke" class="btn-sekundarno">Odustani</a>
<button type="submit" class="btn-primarno">Sačuvaj nabavku</button>
</div>
</form>
@@ -301,14 +288,11 @@
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;padding-bottom:14px;border-bottom:0.5px solid var(--ivica);">
<span style="font-size:16px;font-weight:500;color:var(--tekst-glavni);">Novi artikal</span>
<button type="button" @click="zatvoriModal()"
style="background:none;border:none;cursor:pointer;color:var(--tekst-sporedni);font-size:20px;line-height:1;padding:2px 6px;border-radius:4px;transition:background 0.15s;"
onmouseover="this.style.background='var(--pozadina)'" onmouseout="this.style.background='none'">×</button>
<button type="button" @click="zatvoriModal()" aria-label="Zatvori"
style="background:none;border:none;cursor:pointer;color:var(--tekst-sporedni);font-size:20px;line-height:1;padding:2px 6px;border-radius:4px;transition:background 0.15s;">×</button>
</div>
<div x-show="modalGreska" class="greska-animacija"
style="background:var(--kartica);border:0.5px solid #dc2626;border-radius:8px;padding:10px 14px;margin-bottom:14px;font-size:13px;color:#dc2626;"
x-text="modalGreska"></div>
<div x-show="modalGreska" class="poruka-greska greska-animacija" x-text="modalGreska"></div>
<div style="display:flex;flex-direction:column;gap:14px;">
<div>
@@ -340,15 +324,9 @@
</div>
<div style="display:flex;justify-content:flex-end;gap:10px;margin-top:20px;padding-top:14px;border-top:0.5px solid var(--ivica);">
<button type="button" @click="zatvoriModal()"
style="padding:9px 20px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;color:var(--tekst-sporedni);background:none;cursor:pointer;transition:background 0.2s;"
onmouseover="this.style.background='var(--pozadina)'" onmouseout="this.style.background='none'">
Odustani
</button>
<button type="button" @click="sacuvajArtikal()" :disabled="modalUcitavanje"
style="padding:9px 20px;background:var(--sb-akcent);color:#fff;border:none;border-radius:8px;font-size:14px;font-weight:500;cursor:pointer;transition:opacity 0.2s;"
:style="modalUcitavanje ? 'opacity:0.6;cursor:not-allowed' : ''"
@mouseover="if(!modalUcitavanje) $el.style.opacity='0.85'" @mouseout="$el.style.opacity='1'">
<button type="button" @click="zatvoriModal()" class="btn-sekundarno">Odustani</button>
<button type="button" @click="sacuvajArtikal()" :disabled="modalUcitavanje" class="btn-primarno"
:style="modalUcitavanje ? 'opacity:0.6;cursor:not-allowed' : ''">
<span x-text="modalUcitavanje ? 'Čuvanje...' : 'Dodaj artikal'"></span>
</button>
</div>
+11 -23
View File
@@ -4,14 +4,7 @@
{{define "dodatni-css"}}
<style>
@keyframes slideDown {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}
.poruka-animacija {
animation: slideDown 0.3s ease forwards;
}
.poruka-animacija { animation: slideDown 0.3s ease forwards; }
.nabavke-tabela tbody tr:nth-child(1) { animation-delay: 0.04s; }
.nabavke-tabela tbody tr:nth-child(2) { animation-delay: 0.08s; }
@@ -55,11 +48,7 @@
<!-- dugme nova nabavka -->
<div>
<a href="/nabavke/nova"
style="display:inline-block;padding:8px 16px;background:var(--sb-akcent);color:#fff;border-radius:8px;font-size:14px;font-weight:500;text-decoration:none;transition:opacity 0.2s;"
onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">
+ Nova nabavka
</a>
<a href="/nabavke/nova" class="btn-primarno">+ Nova nabavka</a>
</div>
<!-- desktop tabela -->
@@ -77,9 +66,7 @@
</thead>
<tbody>
{{range .Nabavke}}
<tr class="animiraj" style="border-bottom:0.5px solid var(--ivica);transition:background 0.15s;"
onmouseover="this.style.background='var(--pozadina)'"
onmouseout="this.style.background=''">
<tr class="animiraj red-tabele">
<td style="padding:12px 16px;font-size:13px;color:var(--tekst-sporedni);white-space:nowrap;">
{{.Datum.Format "02.01.2006."}}
</td>
@@ -97,14 +84,14 @@
<a href="/nabavke/{{.ID}}" class="btn-primarno-malo">
Detalji
</a>
{{if index $.Dozvole "nabavka.obrisi"}}
<form method="POST" action="/nabavke/obrisi/{{.ID}}" style="display:inline;">
<button type="submit"
onclick="return confirm('Da li ste sigurni?\n\nBrisanje nabavke ne vraća količine artikala u magacin.')"
style="padding:4px 10px;background:#dc2626;color:#fff;border:none;border-radius:6px;font-size:12px;cursor:pointer;transition:opacity 0.2s;"
onmouseover="this.style.opacity='0.8'" onmouseout="this.style.opacity='1'">
<button type="submit" class="btn-obrisi-malo"
data-potvrda="Da li ste sigurni? Brisanje nabavke ne vraća količine artikala u magacin.">
Obriši
</button>
</form>
{{end}}
</div>
</td>
</tr>
@@ -144,13 +131,14 @@
<a href="/nabavke/{{.ID}}" class="btn-primarno-malo" style="flex:1;justify-content:center;">
Detalji
</a>
{{if index $.Dozvole "nabavka.obrisi"}}
<form method="POST" action="/nabavke/obrisi/{{.ID}}" style="flex:1;">
<button type="submit"
onclick="return confirm('Da li ste sigurni?\n\nBrisanje nabavke ne vraća količine artikala u magacin.')"
style="width:100%;padding:7px;background:#dc2626;color:#fff;border:none;border-radius:6px;font-size:13px;cursor:pointer;">
<button type="submit" class="btn-obrisi-malo" style="width:100%;justify-content:center;"
data-potvrda="Da li ste sigurni? Brisanje nabavke ne vraća količine artikala u magacin.">
Obriši
</button>
</form>
{{end}}
</div>
</div>
{{else}}
+11 -38
View File
@@ -4,14 +4,7 @@
{{define "dodatni-css"}}
<style>
@keyframes slideDown {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}
.poruka-animacija {
animation: slideDown 0.3s ease forwards;
}
.poruka-animacija { animation: slideDown 0.3s ease forwards; }
.pod-tabela tbody tr:nth-child(1) { animation-delay: 0.04s; }
.pod-tabela tbody tr:nth-child(2) { animation-delay: 0.08s; }
@@ -59,11 +52,7 @@
<!-- gornja traka -->
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:center;">
<a href="/podsetnici/novi"
style="padding:8px 16px;background:var(--sb-akcent);color:#fff;border-radius:8px;font-size:14px;font-weight:500;text-decoration:none;white-space:nowrap;transition:opacity 0.2s;"
onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">
+ Novi podsetnik
</a>
<a href="/podsetnici/novi" class="btn-primarno">+ Novi podsetnik</a>
<form method="GET" action="/podsetnici" style="display:flex;gap:8px;align-items:center;flex:1;min-width:200px;flex-wrap:wrap;">
<label style="display:flex;align-items:center;gap:6px;font-size:14px;color:var(--tekst-sporedni);cursor:pointer;white-space:nowrap;">
<input type="checkbox" name="samo_aktivni" value="1" {{if .SamoAktivni}}checked{{end}}
@@ -88,10 +77,7 @@
</thead>
<tbody>
{{range .Podsetnici}}
<tr class="animiraj {{if .JePrekoracen}}red-prekoracen{{end}}"
style="border-bottom:0.5px solid var(--ivica);transition:background 0.15s;"
onmouseover="this.style.background='var(--pozadina)'"
onmouseout="this.style.background=''">
<tr class="animiraj red-tabele {{if .JePrekoracen}}red-prekoracen{{end}}">
<td style="padding:12px 16px;">
<div style="font-size:14px;font-weight:500;color:var(--tekst-glavni);">{{.Naslov}}</div>
{{if .Napomena}}
@@ -112,23 +98,15 @@
</td>
<td style="padding:12px 16px;text-align:center;">
<div style="display:flex;align-items:center;justify-content:center;gap:8px;">
<a href="/podsetnici/izmeni/{{.ID}}"
style="padding:4px 10px;background:var(--sb-aktivan);color:var(--tekst-jak);border-radius:6px;font-size:12px;text-decoration:none;transition:opacity 0.2s;"
onmouseover="this.style.opacity='0.8'" onmouseout="this.style.opacity='1'">
Izmeni
</a>
<a href="/podsetnici/izmeni/{{.ID}}" class="btn-primarno-malo">Izmeni</a>
<form method="POST" action="/podsetnici/zavrseno/{{.ID}}" style="display:inline;">
<button type="submit"
style="padding:4px 10px;background:var(--sb-aktivan);color:var(--tekst-jak);border:none;border-radius:6px;font-size:12px;cursor:pointer;transition:opacity 0.2s;"
onmouseover="this.style.opacity='0.8'" onmouseout="this.style.opacity='1'">
<button type="submit" class="btn-primarno-malo">
{{if .Zavrseno}}Aktiviraj{{else}}Završi{{end}}
</button>
</form>
<form method="POST" action="/podsetnici/obrisi/{{.ID}}" style="display:inline;">
<button type="submit"
onclick="return confirm('Da li ste sigurni da želite da obrišete podsetnik?')"
style="padding:4px 10px;background:#dc2626;color:#fff;border:none;border-radius:6px;font-size:12px;cursor:pointer;transition:opacity 0.2s;"
onmouseover="this.style.opacity='0.8'" onmouseout="this.style.opacity='1'">
<button type="submit" class="btn-obrisi-malo"
data-potvrda="Da li ste sigurni da želite da obrišete podsetnik?">
Obriši
</button>
</form>
@@ -172,20 +150,15 @@
{{.DatumPodsecanja.Format "02.01.2006."}}
</div>
<div style="display:flex;gap:8px;flex-wrap:wrap;">
<a href="/podsetnici/izmeni/{{.ID}}"
style="padding:6px 14px;background:var(--sb-aktivan);color:var(--tekst-jak);border-radius:6px;font-size:13px;text-decoration:none;">
Izmeni
</a>
<a href="/podsetnici/izmeni/{{.ID}}" class="btn-primarno-malo">Izmeni</a>
<form method="POST" action="/podsetnici/zavrseno/{{.ID}}" style="display:inline;">
<button type="submit"
style="padding:6px 14px;background:var(--sb-aktivan);color:var(--tekst-jak);border:none;border-radius:6px;font-size:13px;cursor:pointer;">
<button type="submit" class="btn-primarno-malo">
{{if .Zavrseno}}Aktiviraj{{else}}Završi{{end}}
</button>
</form>
<form method="POST" action="/podsetnici/obrisi/{{.ID}}" style="display:inline;">
<button type="submit"
onclick="return confirm('Da li ste sigurni da želite da obrišete podsetnik?')"
style="padding:6px 14px;background:#dc2626;color:#fff;border:none;border-radius:6px;font-size:13px;cursor:pointer;">
<button type="submit" class="btn-obrisi-malo"
data-potvrda="Da li ste sigurni da želite da obrišete podsetnik?">
Obriši
</button>
</form>
+5 -16
View File
@@ -13,10 +13,8 @@
{{define "sadrzaj"}}
<div style="width:100%;">
<a href="/podsetnici"
style="display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--tekst-sporedni);text-decoration:none;margin-bottom:20px;transition:color 0.2s;"
onmouseover="this.style.color='var(--tekst-glavni)'" onmouseout="this.style.color='var(--tekst-sporedni)'">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
<a href="/podsetnici" class="nazad-link">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="15 18 9 12 15 6"/></svg>
Nazad na podsetnik
</a>
@@ -28,10 +26,7 @@
</div>
{{if .Greska}}
<div class="greska-animacija"
style="background:var(--kartica);border:0.5px solid var(--greska);border-radius:8px;padding:10px 14px;margin-bottom:16px;font-size:13px;color:var(--greska);">
{{.Greska}}
</div>
<div class="poruka-greska greska-animacija">{{.Greska}}</div>
{{end}}
<form method="POST" action="{{if .Izmena}}/podsetnici/izmeni/{{.Podsetnik.ID}}{{else}}/podsetnici/novi{{end}}">
@@ -63,14 +58,8 @@
</div>
<div style="display:flex;justify-content:flex-end;gap:10px;margin-top:4px;">
<a href="/podsetnici"
style="padding:9px 20px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;color:var(--tekst-sporedni);text-decoration:none;transition:background 0.2s;"
onmouseover="this.style.background='var(--pozadina)'" onmouseout="this.style.background=''">
Odustani
</a>
<button type="submit"
style="padding:9px 20px;background:var(--sb-akcent);color:#fff;border:none;border-radius:8px;font-size:14px;font-weight:500;cursor:pointer;transition:opacity 0.2s;"
onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">
<a href="/podsetnici" class="btn-sekundarno">Odustani</a>
<button type="submit" class="btn-primarno">
{{if .Izmena}}Sačuvaj izmene{{else}}Dodaj podsetnik{{end}}
</button>
</div>
+4 -23
View File
@@ -4,11 +4,6 @@
{{define "dodatni-css"}}
<style>
@keyframes slideDown {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}
.poruka-animacija { animation: slideDown 0.3s ease forwards; }
.prodaja-tabela tbody tr:nth-child(1) { animation-delay: 0.04s; }
@@ -57,24 +52,12 @@
<input type="text" name="pretraga" value="{{.Pretraga}}"
placeholder="Pretraži po broju naloga..."
style="flex:1;">
<button type="submit"
style="padding:8px 14px;background:var(--kartica);border:0.5px solid var(--ivica);border-radius:8px;font-size:13px;color:var(--tekst-sporedni);cursor:pointer;white-space:nowrap;transition:background 0.2s;"
onmouseover="this.style.background='var(--pozadina)'" onmouseout="this.style.background='var(--kartica)'">
Pretraži
</button>
<button type="submit" class="btn-sekundarno" style="white-space:nowrap;">Pretraži</button>
{{if .Pretraga}}
<a href="/prodaja"
style="padding:8px 14px;border:0.5px solid var(--ivica);border-radius:8px;font-size:13px;color:var(--tekst-sporedni);text-decoration:none;white-space:nowrap;transition:background 0.2s;"
onmouseover="this.style.background='var(--pozadina)'" onmouseout="this.style.background=''">
✕ Resetuj
</a>
<a href="/prodaja" class="btn-sekundarno" style="white-space:nowrap;">✕ Resetuj</a>
{{end}}
</form>
<a href="/prodaja/nova"
style="padding:8px 16px;background:var(--sb-akcent);color:#fff;border-radius:8px;font-size:14px;font-weight:500;text-decoration:none;white-space:nowrap;transition:opacity 0.2s;"
onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">
+ Nova prodaja
</a>
<a href="/prodaja/nova" class="btn-primarno">+ Nova prodaja</a>
</div>
<!-- desktop tabela -->
@@ -92,9 +75,7 @@
</thead>
<tbody>
{{range .Nalozi}}
<tr class="animiraj" style="border-bottom:0.5px solid var(--ivica);transition:background 0.15s;"
onmouseover="this.style.background='var(--pozadina)'"
onmouseout="this.style.background=''">
<tr class="animiraj red-tabele">
<td style="padding:12px 16px;font-size:13px;font-family:monospace;color:var(--tekst-glavni);">
{{.BrojNaloga}}
</td>
+8 -12
View File
@@ -20,10 +20,8 @@
{{end}}
<!-- nazad dugme -->
<a href="/prodaja"
style="display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--tekst-sporedni);text-decoration:none;transition:color 0.2s;"
onmouseover="this.style.color='var(--tekst-glavni)'" onmouseout="this.style.color='var(--tekst-sporedni)'">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
<a href="/prodaja" class="nazad-link">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="15 18 9 12 15 6"/></svg>
Nazad na prodaju
</a>
@@ -33,10 +31,8 @@
<span style="font-size:20px;font-weight:600;color:var(--tekst-glavni);font-family:monospace;">
{{.Nalog.BrojNaloga}}
</span>
<a href="/prodaja/{{.Nalog.ID}}/stampa" target="_blank"
style="display:inline-flex;align-items:center;gap:6px;padding:8px 16px;background:var(--kartica);border:0.5px solid var(--ivica);border-radius:8px;font-size:13px;color:var(--tekst-sporedni);text-decoration:none;transition:background 0.2s;"
onmouseover="this.style.background='var(--pozadina)'" onmouseout="this.style.background='var(--kartica)'">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 6 2 18 2 18 9"/><path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"/><rect x="6" y="14" width="12" height="8"/></svg>
<a href="/prodaja/{{.Nalog.ID}}/stampa" target="_blank" class="btn-sekundarno" style="gap:6px;">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="6 9 6 2 18 2 18 9"/><path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"/><rect x="6" y="14" width="12" height="8"/></svg>
Štampaj
</a>
</div>
@@ -99,6 +95,7 @@
</div>
</div>
{{if index $.Dozvole "prodaja.obrisi"}}
<!-- zona za brisanje -->
<div class="kartica detalji-kartica animiraj" style="border-color:#dc262633;">
<div style="display:flex;align-items:flex-start;gap:12px;flex-wrap:wrap;">
@@ -109,15 +106,14 @@
</div>
</div>
<form method="POST" action="/prodaja/obrisi/{{.Nalog.ID}}">
<button type="submit"
onclick="return confirm('Da li ste sigurni da želite da obrišete nalog {{.Nalog.BrojNaloga}}?\n\nKoličine artikala biće vraćene na stanje.')"
style="padding:9px 20px;background:#dc2626;color:#fff;border:none;border-radius:8px;font-size:14px;font-weight:500;cursor:pointer;white-space:nowrap;transition:opacity 0.2s;"
onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">
<button type="submit" class="btn-primarno" style="background:#dc2626;"
data-potvrda="Da li ste sigurni da želite da obrišete nalog {{.Nalog.BrojNaloga}}? Količine artikala biće vraćene na stanje.">
Obriši nalog
</button>
</form>
</div>
</div>
{{end}}
</div>
{{end}}
+7 -19
View File
@@ -11,7 +11,7 @@
@media (max-width: 768px) {
.stavke-tabela-wrapper { display: none; }
.stavke-kartice { display: flex !important; }
.stavke-kartice { display: flex !important; }
}
</style>
{{end}}
@@ -68,20 +68,15 @@
}">
<!-- nazad dugme -->
<a href="/prodaja"
style="display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--tekst-sporedni);text-decoration:none;margin-bottom:20px;transition:color 0.2s;"
onmouseover="this.style.color='var(--tekst-glavni)'" onmouseout="this.style.color='var(--tekst-sporedni)'">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
<a href="/prodaja" class="nazad-link">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="15 18 9 12 15 6"/></svg>
Nazad na prodaju
</a>
<form method="POST" action="/prodaja/nova">
{{if .Greska}}
<div class="greska-animacija"
style="background:var(--kartica);border:0.5px solid #dc2626;border-radius:8px;padding:10px 14px;margin-bottom:16px;font-size:13px;color:#dc2626;">
{{.Greska}}
</div>
<div class="poruka-greska greska-animacija">{{.Greska}}</div>
{{end}}
<!-- zaglavlje prodaje -->
@@ -246,17 +241,10 @@
<!-- dugmad forme -->
<div style="display:flex;justify-content:flex-end;gap:10px;">
<a href="/prodaja"
style="padding:9px 20px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;color:var(--tekst-sporedni);text-decoration:none;transition:background 0.2s;"
onmouseover="this.style.background='var(--pozadina)'" onmouseout="this.style.background=''">
Odustani
</a>
<button type="submit"
<a href="/prodaja" class="btn-sekundarno">Odustani</a>
<button type="submit" class="btn-primarno"
:disabled="imaPrekoracenja()"
:style="imaPrekoracenja() ? 'opacity:0.4;cursor:not-allowed;' : ''"
style="padding:9px 20px;background:var(--sb-akcent);color:#fff;border:none;border-radius:8px;font-size:14px;font-weight:500;cursor:pointer;transition:opacity 0.2s;"
@mouseover="if(!imaPrekoracenja()) $el.style.opacity='0.85'"
@mouseout="$el.style.opacity=imaPrekoracenja()?'0.4':'1'">
:style="imaPrekoracenja() ? 'opacity:0.4;cursor:not-allowed;' : ''">
Sačuvaj prodaju
</button>
</div>
+19 -31
View File
@@ -4,11 +4,6 @@
{{define "dodatni-css"}}
<style>
@keyframes slideDown {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}
.poruka-animacija { animation: slideDown 0.3s ease forwards; }
.servis-tabela tbody tr:nth-child(1) { animation-delay: 0.04s; }
@@ -78,14 +73,9 @@
<div class="poruka-uspeh poruka-animacija">Nalog je uspešno obrisan.</div>
{{end}}
<!-- gornja traka: dugme + pretraga + filter statusa -->
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:center;">
<a href="/servis/novi"
style="padding:8px 16px;background:var(--sb-akcent);color:#fff;border-radius:8px;font-size:14px;font-weight:500;text-decoration:none;white-space:nowrap;transition:opacity 0.2s;"
onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">
+ Novi nalog
</a>
<form method="GET" action="/servis" style="display:flex;gap:8px;flex:1;flex-wrap:wrap;min-width:200px;">
<!-- gornja traka: pretraga + dugme nova, ispod toga dugme traži -->
<form method="GET" action="/servis" style="display:flex;flex-direction:column;gap:8px;">
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center;">
<input type="text" name="pretraga" value="{{.Pretraga}}"
placeholder="Pretraži po broju naloga ili uređaju..."
style="flex:1;min-width:160px;">
@@ -95,11 +85,12 @@
<option value="{{.}}" {{if eq . $.FilterStatus}}selected{{end}}>{{.}}</option>
{{end}}
</select>
<button type="submit" class="btn-primarno">
Traži
</button>
</form>
</div>
<a href="/servis/novi" class="btn-primarno" style="white-space:nowrap;flex-shrink:0;">+ Novi nalog</a>
</div>
<div>
<button type="submit" class="btn-primarno" style="white-space:nowrap;">Traži</button>
</div>
</form>
<!-- desktop tabela -->
<div class="kartica servis-tabela animiraj" style="padding:0;overflow:hidden;">
@@ -117,14 +108,10 @@
</thead>
<tbody>
{{range .Nalozi}}
<tr class="animiraj" style="border-bottom:0.5px solid var(--ivica);transition:background 0.15s;"
onmouseover="this.style.background='var(--pozadina)'"
onmouseout="this.style.background=''">
<tr class="animiraj red-tabele">
<td style="padding:12px 16px;">
<a href="/servis/{{.ID}}"
style="font-size:14px;font-weight:500;color:var(--sb-akcent);text-decoration:none;font-family:monospace;"
onmouseover="this.style.textDecoration='underline'"
onmouseout="this.style.textDecoration='none'">
style="font-size:14px;font-weight:500;color:var(--sb-akcent);text-decoration:none;font-family:monospace;">
{{.BrojNaloga}}
</a>
</td>
@@ -143,14 +130,14 @@
<a href="/servis/izmeni/{{.ID}}" class="btn-primarno-malo">
Izmeni
</a>
{{if index $.Dozvole "servis.obrisi"}}
<form method="POST" action="/servis/obrisi/{{.ID}}" style="display:inline;">
<button type="submit"
onclick="return confirm('Da li ste sigurni da želite da obrišete nalog {{.BrojNaloga}}?')"
style="padding:4px 10px;background:#dc2626;color:#fff;border:none;border-radius:6px;font-size:12px;cursor:pointer;transition:opacity 0.2s;"
onmouseover="this.style.opacity='0.8'" onmouseout="this.style.opacity='1'">
<button type="submit" class="btn-obrisi-malo"
data-potvrda="Da li ste sigurni da želite da obrišete nalog {{.BrojNaloga}}?">
Obriši
</button>
</form>
{{end}}
</div>
</td>
</tr>
@@ -196,13 +183,14 @@
<a href="/servis/izmeni/{{.ID}}" class="btn-primarno-malo">
Izmeni
</a>
{{if index $.Dozvole "servis.obrisi"}}
<form method="POST" action="/servis/obrisi/{{.ID}}" style="display:inline;">
<button type="submit"
onclick="return confirm('Da li ste sigurni da želite da obrišete nalog {{.BrojNaloga}}?')"
style="padding:6px 14px;background:#dc2626;color:#fff;border:none;border-radius:6px;font-size:13px;cursor:pointer;">
<button type="submit" class="btn-obrisi-malo"
data-potvrda="Da li ste sigurni da želite da obrišete nalog {{.BrojNaloga}}?">
Obriši
</button>
</form>
{{end}}
</div>
</div>
{{else}}
+4 -8
View File
@@ -49,10 +49,8 @@
{{end}}
<!-- nazad dugme -->
<a href="/servis"
style="display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--tekst-sporedni);text-decoration:none;transition:color 0.2s;"
onmouseover="this.style.color='var(--tekst-glavni)'" onmouseout="this.style.color='var(--tekst-sporedni)'">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
<a href="/servis" class="nazad-link">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="15 18 9 12 15 6"/></svg>
Nazad na servis
</a>
@@ -171,10 +169,8 @@
</div>
</div>
<form method="POST" action="/servis/obrisi/{{.Nalog.ID}}">
<button type="submit"
onclick="return confirm('Da li ste sigurni da želite da obrišete nalog {{.Nalog.BrojNaloga}}?')"
style="padding:9px 20px;background:#dc2626;color:#fff;border:none;border-radius:8px;font-size:14px;font-weight:500;cursor:pointer;white-space:nowrap;transition:opacity 0.2s;"
onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">
<button type="submit" class="btn-primarno" style="background:#dc2626;"
data-potvrda="Da li ste sigurni da želite da obrišete nalog {{.Nalog.BrojNaloga}}?">
Obriši nalog
</button>
</form>
+5 -26
View File
@@ -6,17 +6,7 @@
<style>
.greska-animacija { animation: shake 0.4s ease; }
.sekcija-naslov {
font-size: 12px;
font-weight: 500;
color: var(--tekst-sporedni);
text-transform: uppercase;
letter-spacing: 0.05em;
margin-bottom: 10px;
}
@media (max-width: 768px) {
.forma-grid-2 { grid-template-columns: 1fr !important; }
.forma-grid-4 { grid-template-columns: 1fr 1fr !important; }
}
</style>
@@ -26,10 +16,8 @@
<div style="width:100%;">
<!-- nazad dugme -->
<a href="/servis"
style="display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--tekst-sporedni);text-decoration:none;margin-bottom:20px;transition:color 0.2s;"
onmouseover="this.style.color='var(--tekst-glavni)'" onmouseout="this.style.color='var(--tekst-sporedni)'">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
<a href="/servis" class="nazad-link">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="15 18 9 12 15 6"/></svg>
Nazad na servis
</a>
@@ -44,10 +32,7 @@
</div>
{{if .Greska}}
<div class="greska-animacija"
style="background:var(--kartica);border:0.5px solid #dc2626;border-radius:8px;padding:10px 14px;margin-bottom:16px;font-size:13px;color:#dc2626;">
{{.Greska}}
</div>
<div class="poruka-greska greska-animacija">{{.Greska}}</div>
{{end}}
<form method="POST" action="{{if .Izmena}}/servis/izmeni/{{.Nalog.ID}}{{else}}/servis/novi{{end}}">
@@ -164,14 +149,8 @@
<!-- dugmad -->
<div style="display:flex;justify-content:flex-end;gap:10px;margin-top:6px;">
<a href="/servis"
style="padding:9px 20px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;color:var(--tekst-sporedni);text-decoration:none;transition:background 0.2s;"
onmouseover="this.style.background='var(--pozadina)'" onmouseout="this.style.background=''">
Odustani
</a>
<button type="submit"
style="padding:9px 20px;background:var(--sb-akcent);color:#fff;border:none;border-radius:8px;font-size:14px;font-weight:500;cursor:pointer;transition:opacity 0.2s;"
onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">
<a href="/servis" class="btn-sekundarno">Odustani</a>
<button type="submit" class="btn-primarno">
{{if .Izmena}}Sačuvaj izmene{{else}}Sačuvaj nalog{{end}}
</button>
</div>
@@ -102,6 +102,15 @@
i.type = 'hidden'; i.name = '_csrf'; i.value = m.content;
f.appendChild(i);
});
// data-potvrda: sigurna alternativa za onclick=confirm() na dugmadima i linkovima
// Vrednost atributa je poruka koja se prikazuje korisniku. Go template je HTML-escape-uje,
// JS čita originalnu vrednost — nema problema sa specijalnim karakterima u imenima.
document.querySelectorAll('[data-potvrda]').forEach(function(el) {
el.addEventListener('click', function(e) {
if (!confirm(el.getAttribute('data-potvrda'))) e.preventDefault();
});
});
});
</script>
</body>