Bezbednosni audit i refaktoring: HP popravke, RBAC, flash poruke, go:embed, CSP
This commit is contained in:
+20
-136
@@ -4,142 +4,26 @@
|
||||
<meta charset="UTF-8" />
|
||||
<title>NTech — Konfiguracija</title>
|
||||
<style>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
background: #1a1a2e;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.kartica {
|
||||
background: #16213e;
|
||||
padding: 2rem;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
||||
width: 410px;
|
||||
border: 1px solid #0f3460;
|
||||
}
|
||||
|
||||
.zaglavlje {
|
||||
text-align: center;
|
||||
margin-bottom: 1.3rem;
|
||||
}
|
||||
|
||||
.zaglavlje h1 {
|
||||
color: #f8e45c;
|
||||
font-size: 1.4rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.zaglavlje p {
|
||||
color: #a0a0b0;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.sekcija-naslov {
|
||||
color: #a0a0b0;
|
||||
font-size: 0.75rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
margin-bottom: 0.4rem;
|
||||
}
|
||||
|
||||
.port-opcija {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0.5rem 0.75rem;
|
||||
margin: 0.25rem 0;
|
||||
border: 2px solid #0f3460;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
.port-opcija:hover {
|
||||
border-color: #e94560;
|
||||
}
|
||||
|
||||
.port-opcija.izabran {
|
||||
border-color: #e94560;
|
||||
background: rgba(233, 69, 96, 0.1);
|
||||
}
|
||||
|
||||
.port-opcija.zauzet {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.slobodan {
|
||||
color: #2ecc71;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.zauzet-tekst {
|
||||
color: #e74c3c;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.razdvojnik {
|
||||
border: none;
|
||||
border-top: 1px solid #0f3460;
|
||||
margin: 0.75rem 0;
|
||||
}
|
||||
|
||||
input[type="number"] {
|
||||
width: 100%;
|
||||
padding: 0.5rem 0.75rem;
|
||||
background: #0f3460;
|
||||
border: 2px solid #0f3460;
|
||||
border-radius: 8px;
|
||||
font-size: 0.9rem;
|
||||
color: #e0e0e0;
|
||||
outline: none;
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
|
||||
input[type="number"]:focus {
|
||||
border-color: #e94560;
|
||||
}
|
||||
|
||||
input[type="number"]::placeholder {
|
||||
color: #606080;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
padding: 0.65rem;
|
||||
margin-top: 0.75rem;
|
||||
background: #e94560;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background: #c73652;
|
||||
}
|
||||
|
||||
.poruka {
|
||||
text-align: center;
|
||||
padding: 0.5rem;
|
||||
font-size: 0.85rem;
|
||||
color: #2ecc71;
|
||||
display: none;
|
||||
}
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: #1a1a2e; display: flex; justify-content: center; align-items: center; height: 100vh; }
|
||||
.kartica { background: #16213e; padding: 2rem; border-radius: 12px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4); width: 410px; border: 1px solid #0f3460; }
|
||||
.zaglavlje { text-align: center; margin-bottom: 1.3rem; }
|
||||
.zaglavlje h1 { color: #f8e45c; font-size: 1.4rem; margin-bottom: 0.25rem; }
|
||||
.zaglavlje p { color: #a0a0b0; font-size: 0.85rem; }
|
||||
.sekcija-naslov { color: #a0a0b0; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.4rem; }
|
||||
.port-opcija { display: flex; justify-content: space-between; align-items: center; padding: 0.5rem 0.75rem; margin: 0.25rem 0; border: 2px solid #0f3460; border-radius: 8px; cursor: pointer; transition: all 0.2s; color: #e0e0e0; }
|
||||
.port-opcija:hover { border-color: #e94560; }
|
||||
.port-opcija.izabran { border-color: #e94560; background: rgba(233, 69, 96, 0.1); }
|
||||
.port-opcija.zauzet { opacity: 0.5; cursor: not-allowed; }
|
||||
.slobodan { color: #2ecc71; font-size: 0.85rem; }
|
||||
.zauzet-tekst { color: #e74c3c; font-size: 0.85rem; }
|
||||
.razdvojnik { border: none; border-top: 1px solid #0f3460; margin: 0.75rem 0; }
|
||||
input[type="number"] { width: 100%; padding: 0.5rem 0.75rem; background: #0f3460; border: 2px solid #0f3460; border-radius: 8px; font-size: 0.9rem; color: #e0e0e0; outline: none; transition: border-color 0.2s; }
|
||||
input[type="number"]:focus { border-color: #e94560; }
|
||||
input[type="number"]::placeholder { color: #606080; }
|
||||
button { width: 100%; padding: 0.65rem; margin-top: 0.75rem; background: #e94560; color: white; border: none; border-radius: 8px; font-size: 0.95rem; font-weight: 600; cursor: pointer; transition: background 0.2s; }
|
||||
button:hover { background: #c73652; }
|
||||
.poruka { text-align: center; padding: 0.5rem; font-size: 0.85rem; color: #2ecc71; display: none; }
|
||||
</style>
|
||||
</head>
|
||||
|
||||
|
||||
@@ -10,16 +10,7 @@
|
||||
.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-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); }
|
||||
|
||||
@@ -17,9 +17,7 @@
|
||||
.korisnici-tabela tbody tr:nth-child(9) { animation-delay: 0.36s; }
|
||||
.korisnici-tabela tbody tr:nth-child(10) { animation-delay: 0.40s; }
|
||||
|
||||
.nova-forma-kartica {
|
||||
animation-delay: 0.30s;
|
||||
}
|
||||
.nova-forma-kartica { animation-delay: 0.30s; }
|
||||
</style>
|
||||
{{end}}
|
||||
|
||||
|
||||
@@ -1,86 +1,59 @@
|
||||
{{template "base" .}}
|
||||
|
||||
{{define "naslov"}}Istorija prijava — NTech{{end}}
|
||||
|
||||
{{define "dodatni-css"}}
|
||||
{{template "base" .}} {{define "naslov"}}Istorija prijava — NTech{{end}} {{define "dodatni-css"}}
|
||||
<style>
|
||||
.animiraj:nth-child(1) { animation-delay: 0.10s; }
|
||||
.animiraj:nth-child(2) { animation-delay: 0.16s; }
|
||||
.animiraj:nth-child(3) { animation-delay: 0.22s; }
|
||||
.animiraj:nth-child(4) { animation-delay: 0.28s; }
|
||||
.animiraj:nth-child(1) { animation-delay: 0.1s; }
|
||||
.animiraj:nth-child(2) { animation-delay: 0.16s; }
|
||||
.animiraj:nth-child(3) { animation-delay: 0.22s; }
|
||||
.animiraj:nth-child(4) { animation-delay: 0.28s; }
|
||||
</style>
|
||||
{{end}}
|
||||
{{end}} {{define "sadrzaj"}}
|
||||
<div style="display: flex; flex-direction: column; gap: 16px">
|
||||
<div style="display: flex; align-items: center; gap: 12px; flex-wrap: wrap">
|
||||
<a href="/admin/korisnici" style="display: inline-flex; align-items: center; gap: 6px; padding: 7px 14px; border: 0.5px solid var(--ivica); border-radius: 8px; color: var(--tekst-sporedni); font-size: 13px; text-decoration: none">← Nazad</a>
|
||||
<span style="font-size: 15px; font-weight: 500; color: var(--tekst-glavni)">Istorija prijava — {{.PrikazKorisnik.KorisnickoIme}}</span>
|
||||
</div>
|
||||
|
||||
{{define "sadrzaj"}}
|
||||
<div style="display:flex;flex-direction:column;gap:16px;">
|
||||
|
||||
<div style="display:flex;align-items:center;gap:12px;flex-wrap:wrap;">
|
||||
<a href="/admin/korisnici"
|
||||
style="display:inline-flex;align-items:center;gap:6px;padding:7px 14px;border:0.5px solid var(--ivica);border-radius:8px;color:var(--tekst-sporedni);font-size:13px;text-decoration:none;">
|
||||
← Nazad
|
||||
</a>
|
||||
<span style="font-size:15px;font-weight:500;color:var(--tekst-glavni);">
|
||||
Istorija prijava — {{.PrikazKorisnik.KorisnickoIme}}
|
||||
</span>
|
||||
<div class="kartica animiraj" style="padding: 0; overflow: hidden">
|
||||
<div style="padding: 16px 20px; border-bottom: 0.5px solid var(--ivica); display: flex; align-items: center; justify-content: space-between">
|
||||
<span style="font-size: 15px; font-weight: 500; color: var(--tekst-glavni)">Poslednjih 50 pokušaja</span>
|
||||
<span style="font-size: 12px; color: var(--tekst-sporedni)">Vreme prikazano po lokalnom vremenu servera</span>
|
||||
</div>
|
||||
|
||||
<div class="kartica animiraj" style="padding:0;overflow:hidden;">
|
||||
<div style="padding:16px 20px;border-bottom:0.5px solid var(--ivica);display:flex;align-items:center;justify-content:space-between;">
|
||||
<span style="font-size:15px;font-weight:500;color:var(--tekst-glavni);">Poslednjih 50 pokušaja</span>
|
||||
<span style="font-size:12px;color:var(--tekst-sporedni);">Vreme prikazano po lokalnom vremenu servera</span>
|
||||
</div>
|
||||
|
||||
{{if .Istorija}}
|
||||
<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 20px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-sporedni);white-space:nowrap;">Datum i vreme</th>
|
||||
<th style="padding:10px 20px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">IP adresa</th>
|
||||
<th style="padding:10px 20px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Pregledač</th>
|
||||
<th style="padding:10px 20px;text-align:center;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Status</th>
|
||||
<th style="padding:10px 20px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Razlog</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .Istorija}}
|
||||
<tr class="animiraj" style="border-bottom:0.5px solid var(--ivica);">
|
||||
<td style="padding:10px 20px;font-size:13px;color:var(--tekst-sporedni);white-space:nowrap;">
|
||||
{{.Vreme.Format "02.01.2006. 15:04:05"}}
|
||||
</td>
|
||||
<td style="padding:10px 20px;font-size:13px;color:var(--tekst-glavni);font-family:monospace;">
|
||||
{{.IP}}
|
||||
</td>
|
||||
<td style="padding:10px 20px;font-size:12px;color:var(--tekst-sporedni);max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">
|
||||
{{.UserAgent}}
|
||||
</td>
|
||||
<td style="padding:10px 20px;text-align:center;">
|
||||
{{if .Uspeh}}
|
||||
<span style="display:inline-block;padding:2px 10px;border-radius:20px;background:#f0fdf4;color:#16a34a;font-size:11px;font-weight:500;">Uspeh</span>
|
||||
{{else}}
|
||||
<span style="display:inline-block;padding:2px 10px;border-radius:20px;background:#fef2f2;color:#dc2626;font-size:11px;font-weight:500;">Neuspeh</span>
|
||||
{{end}}
|
||||
</td>
|
||||
<td style="padding:10px 20px;font-size:13px;color:var(--tekst-sporedni);">
|
||||
{{if eq .Razlog "korisnik_ne_postoji"}}Korisnik ne postoji
|
||||
{{else if eq .Razlog "nalog_neaktivan"}}Nalog neaktivan
|
||||
{{else if eq .Razlog "pogrešna_lozinka"}}Pogrešna lozinka
|
||||
{{else if eq .Razlog "ip_zaklucano"}}IP zaključano
|
||||
{{else if .Uspeh}}—
|
||||
{{else}}{{.Razlog}}
|
||||
{{end}}
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{else}}
|
||||
<div style="padding:40px 20px;text-align:center;color:var(--tekst-sporedni);font-size:14px;">
|
||||
Nema zabeleženih pokušaja prijave za ovog korisnika.
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .Istorija}}
|
||||
<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 20px; text-align: left; font-size: 12px; font-weight: 500; color: var(--tekst-sporedni); white-space: nowrap">Datum i vreme</th>
|
||||
<th style="padding: 10px 20px; text-align: left; font-size: 12px; font-weight: 500; color: var(--tekst-sporedni)">IP adresa</th>
|
||||
<th style="padding: 10px 20px; text-align: left; font-size: 12px; font-weight: 500; color: var(--tekst-sporedni)">Pregledač</th>
|
||||
<th style="padding: 10px 20px; text-align: center; font-size: 12px; font-weight: 500; color: var(--tekst-sporedni)">Status</th>
|
||||
<th style="padding: 10px 20px; text-align: left; font-size: 12px; font-weight: 500; color: var(--tekst-sporedni)">Razlog</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .Istorija}}
|
||||
<tr class="animiraj" style="border-bottom: 0.5px solid var(--ivica)">
|
||||
<td style="padding: 10px 20px; font-size: 13px; color: var(--tekst-sporedni); white-space: nowrap">{{.Vreme.Format "02.01.2006. 15:04:05"}}</td>
|
||||
<td style="padding: 10px 20px; font-size: 13px; color: var(--tekst-glavni); font-family: monospace">{{.IP}}</td>
|
||||
<td style="padding: 10px 20px; font-size: 12px; color: var(--tekst-sporedni); max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap">{{.UserAgent}}</td>
|
||||
<td style="padding: 10px 20px; text-align: center">
|
||||
{{if .Uspeh}}
|
||||
<span style="display: inline-block; padding: 2px 10px; border-radius: 20px; background: #035f1f; color: #16a34a; font-size: 11px; font-weight: 500">Uspeh</span>
|
||||
{{else}}
|
||||
<span style="display: inline-block; padding: 2px 10px; border-radius: 20px; background: #e21313; color: #dc2626; font-size: 11px; font-weight: 500">Neuspeh</span>
|
||||
{{end}}
|
||||
</td>
|
||||
<td style="padding: 10px 20px; font-size: 13px; color: var(--tekst-sporedni)">
|
||||
{{if eq .Razlog "korisnik_ne_postoji"}}Korisnik ne postoji {{else if eq .Razlog "nalog_neaktivan"}}Nalog neaktivan {{else if eq .Razlog "pogrešna_lozinka"}}Pogrešna lozinka {{else if eq .Razlog "ip_zaklucano"}}IP zaključano {{else if .Uspeh}}— {{else}}{{.Razlog}} {{end}}
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{{else}}
|
||||
<div style="padding: 40px 20px; text-align: center; color: var(--tekst-sporedni); font-size: 14px">Nema zabeleženih pokušaja prijave za ovog korisnika.</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
@@ -1,133 +1,111 @@
|
||||
{{template "base" .}}
|
||||
|
||||
{{define "naslov"}}Moj profil — NTech{{end}}
|
||||
|
||||
{{define "dodatni-css"}}
|
||||
{{ template "base" . }} {{ define "naslov" }}Moj profil — NTech{{ end }}
|
||||
{{ define "dodatni-css" }}
|
||||
<style>
|
||||
.animiraj:nth-child(1) { animation-delay: 0.10s; }
|
||||
.animiraj:nth-child(2) { animation-delay: 0.16s; }
|
||||
.animiraj:nth-child(3) { animation-delay: 0.22s; }
|
||||
.animiraj:nth-child(4) { animation-delay: 0.28s; }
|
||||
.animiraj:nth-child(5) { animation-delay: 0.34s; }
|
||||
.animiraj:nth-child(1) { animation-delay: 0.1s; }
|
||||
.animiraj:nth-child(2) { animation-delay: 0.16s; }
|
||||
.animiraj:nth-child(3) { animation-delay: 0.22s; }
|
||||
.animiraj:nth-child(4) { animation-delay: 0.28s; }
|
||||
.animiraj:nth-child(5) { animation-delay: 0.34s; }
|
||||
</style>
|
||||
{{end}}
|
||||
{{ end }}
|
||||
{{ define "sadrzaj" }}
|
||||
<div style="display: flex; flex-direction: column; gap: 16px; max-width: 560px">
|
||||
<!-- promena lozinke -->
|
||||
<div class="kartica animiraj">
|
||||
<div style="font-size: 15px; font-weight: 500; color: var(--tekst-glavni); margin-bottom: 16px; padding-bottom: 12px; border-bottom: 0.5px solid var(--ivica)">Promena lozinke</div>
|
||||
|
||||
{{define "sadrzaj"}}
|
||||
<div style="display:flex;flex-direction:column;gap:16px;max-width:560px;">
|
||||
<form method="POST" action="/admin/profil/lozinka">
|
||||
<div style="display: flex; flex-direction: column; gap: 12px">
|
||||
<div>
|
||||
<label style="font-size: 13px; color: var(--tekst-sporedni); display: block; margin-bottom: 6px">Trenutna lozinka</label>
|
||||
<input type="password" name="stara_lozinka" required style="width: 100%" />
|
||||
</div>
|
||||
<div>
|
||||
<label style="font-size: 13px; color: var(--tekst-sporedni); display: block; margin-bottom: 6px">Nova lozinka</label>
|
||||
<input type="password" name="nova_lozinka" required minlength="8" style="width: 100%" />
|
||||
</div>
|
||||
<div>
|
||||
<label style="font-size: 13px; color: var(--tekst-sporedni); display: block; margin-bottom: 6px">Potvrda nove lozinke</label>
|
||||
<input type="password" name="nova_lozinka_potvrda" required style="width: 100%" />
|
||||
</div>
|
||||
<div>
|
||||
<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">Sačuvaj novu lozinku</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- promena lozinke -->
|
||||
<div class="kartica animiraj">
|
||||
<div style="font-size:15px;font-weight:500;color:var(--tekst-glavni);margin-bottom:16px;padding-bottom:12px;border-bottom:0.5px solid var(--ivica);">
|
||||
Promena lozinke
|
||||
</div>
|
||||
<!-- TOTP / 2FA -->
|
||||
<div class="kartica animiraj">
|
||||
<div style="font-size: 15px; font-weight: 500; color: var(--tekst-glavni); margin-bottom: 16px; padding-bottom: 12px; border-bottom: 0.5px solid var(--ivica)">Dvostepena verifikacija (2FA)</div>
|
||||
|
||||
<form method="POST" action="/admin/profil/lozinka">
|
||||
<div style="display:flex;flex-direction:column;gap:12px;">
|
||||
<div>
|
||||
<label style="font-size:13px;color:var(--tekst-sporedni);display:block;margin-bottom:6px;">Trenutna lozinka</label>
|
||||
<input type="password" name="stara_lozinka" required style="width:100%;">
|
||||
</div>
|
||||
<div>
|
||||
<label style="font-size:13px;color:var(--tekst-sporedni);display:block;margin-bottom:6px;">Nova lozinka</label>
|
||||
<input type="password" name="nova_lozinka" required minlength="8" style="width:100%;">
|
||||
</div>
|
||||
<div>
|
||||
<label style="font-size:13px;color:var(--tekst-sporedni);display:block;margin-bottom:6px;">Potvrda nove lozinke</label>
|
||||
<input type="password" name="nova_lozinka_potvrda" required style="width:100%;">
|
||||
</div>
|
||||
<div>
|
||||
<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;">
|
||||
Sačuvaj novu lozinku
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{ if .TotpURI }}
|
||||
<!-- postavljanje TOTP -->
|
||||
{{ if eq .Greska "totp" }}
|
||||
<div class="poruka-greska" style="margin-bottom: 14px">Neispravan kod. Pokušajte ponovo.</div>
|
||||
{{ end }}
|
||||
|
||||
<!-- TOTP / 2FA -->
|
||||
<div class="kartica animiraj">
|
||||
<div style="font-size:15px;font-weight:500;color:var(--tekst-glavni);margin-bottom:16px;padding-bottom:12px;border-bottom:0.5px solid var(--ivica);">
|
||||
Dvostepena verifikacija (2FA)
|
||||
</div>
|
||||
<p style="font-size: 13px; color: var(--tekst-sporedni); margin-bottom: 16px; line-height: 1.5">Skenirajte QR kod u aplikaciji (Google Authenticator, Authy...), pa unesite generisani kod da potvrdite podešavanje.</p>
|
||||
|
||||
{{if .TotpURI}}
|
||||
<!-- postavljanje TOTP -->
|
||||
{{if eq .Greska "totp"}}
|
||||
<div class="poruka-greska" style="margin-bottom:14px;">Neispravan kod. Pokušajte ponovo.</div>
|
||||
{{end}}
|
||||
<div style="text-align: center; margin-bottom: 16px">
|
||||
<img src="{{ .TotpQR }}" alt="QR kod" style="width: 200px; height: 200px; border-radius: 8px; display: block; margin: 0 auto" />
|
||||
</div>
|
||||
|
||||
<p style="font-size:13px;color:var(--tekst-sporedni);margin-bottom:16px;line-height:1.5;">
|
||||
Skenirajte QR kod u aplikaciji (Google Authenticator, Authy...), pa unesite generisani kod da potvrdite podešavanje.
|
||||
</p>
|
||||
<details style="margin-bottom: 16px">
|
||||
<summary style="font-size: 12px; color: var(--tekst-sporedni); cursor: pointer">Prikaži tajnu ručno</summary>
|
||||
<code style="font-size: 12px; background: var(--pozadina); padding: 6px 10px; border-radius: 6px; display: block; margin-top: 8px; word-break: break-all; color: var(--tekst-glavni)">{{ .TotpTajna }}</code>
|
||||
</details>
|
||||
|
||||
<div style="text-align:center;margin-bottom:16px;">
|
||||
<img src="{{.TotpQR}}" alt="QR kod" style="width:200px;height:200px;border-radius:8px;display:block;margin:0 auto;">
|
||||
</div>
|
||||
<form method="POST" action="/admin/profil/totp/aktiviraj">
|
||||
<input type="hidden" name="totp_tajna" value="{{ .TotpTajna }}" />
|
||||
<div style="margin-bottom: 12px">
|
||||
<label style="font-size: 13px; color: var(--tekst-sporedni); display: block; margin-bottom: 6px">Verifikacioni kod</label>
|
||||
<input type="text" name="kod" inputmode="numeric" pattern="[0-9]{6}" maxlength="6" required autofocus style="width: 160px; font-size: 18px; text-align: center; letter-spacing: 4px" />
|
||||
</div>
|
||||
<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">Potvrdi i uključi 2FA</button>
|
||||
</form>
|
||||
|
||||
<details style="margin-bottom:16px;">
|
||||
<summary style="font-size:12px;color:var(--tekst-sporedni);cursor:pointer;">Prikaži tajnu ručno</summary>
|
||||
<code style="font-size:12px;background:var(--pozadina);padding:6px 10px;border-radius:6px;display:block;margin-top:8px;word-break:break-all;color:var(--tekst-glavni);">{{.TotpTajna}}</code>
|
||||
</details>
|
||||
{{ else if .TotpAktivan }}
|
||||
<!-- 2FA je uključena -->
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px">
|
||||
<div>
|
||||
<div style="font-size: 14px; color: #16a34a; margin-bottom: 4px; font-weight: 500">✓ Dvostepena verifikacija je uključena</div>
|
||||
<div style="font-size: 13px; color: var(--tekst-sporedni)">Prijava zahteva TOTP kod pored lozinke.</div>
|
||||
</div>
|
||||
<form method="POST" action="/admin/profil/totp/deaktiviraj" onsubmit="return confirm('Da li ste sigurni? Ovo će isključiti dvostepenu verifikaciju.');">
|
||||
<button type="submit" style="padding: 9px 18px; background: #dc2626; color: #fff; border: none; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer">Deaktiviraj 2FA</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<form method="POST" action="/admin/profil/totp/aktiviraj">
|
||||
<input type="hidden" name="totp_tajna" value="{{.TotpTajna}}">
|
||||
<div style="margin-bottom:12px;">
|
||||
<label style="font-size:13px;color:var(--tekst-sporedni);display:block;margin-bottom:6px;">Verifikacioni kod</label>
|
||||
<input type="text" name="kod" inputmode="numeric" pattern="[0-9]{6}"
|
||||
maxlength="6" required autofocus
|
||||
style="width:160px;font-size:18px;text-align:center;letter-spacing:4px;">
|
||||
</div>
|
||||
<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;">
|
||||
Potvrdi i uključi 2FA
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{{else if .TotpAktivan}}
|
||||
<!-- 2FA je uključena -->
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;">
|
||||
<div>
|
||||
<div style="font-size:14px;color:#16a34a;margin-bottom:4px;font-weight:500;">✓ Dvostepena verifikacija je uključena</div>
|
||||
<div style="font-size:13px;color:var(--tekst-sporedni);">Prijava zahteva TOTP kod pored lozinke.</div>
|
||||
</div>
|
||||
<form method="POST" action="/admin/profil/totp/deaktiviraj"
|
||||
onsubmit="return confirm('Da li ste sigurni? Ovo će isključiti dvostepenu verifikaciju.')">
|
||||
<button type="submit"
|
||||
style="padding:9px 18px;background:#dc2626;color:#fff;border:none;border-radius:8px;font-size:14px;font-weight:500;cursor:pointer;">
|
||||
Deaktiviraj 2FA
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{{else}}
|
||||
<!-- 2FA nije uključena -->
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;">
|
||||
<div>
|
||||
<div style="font-size:14px;color:var(--tekst-glavni);margin-bottom:4px;">Status: <strong>Isključena</strong></div>
|
||||
<div style="font-size:13px;color:var(--tekst-sporedni);">Preporučujemo uključivanje dvostepene verifikacije.</div>
|
||||
</div>
|
||||
<a href="/admin/profil/totp/pokreni"
|
||||
style="padding:9px 18px;background:var(--sb-akcent);color:#fff;border-radius:8px;font-size:14px;font-weight:500;text-decoration:none;">
|
||||
Podesi 2FA
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
{{if index .Dozvole "tema.lokalno"}}
|
||||
<div class="kartica animiraj" style="background:var(--pozadina);border:0.5px solid var(--ivica);">
|
||||
<div style="display:flex;align-items:center;gap:10px;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="var(--sb-akcent)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M12 1v4M12 19v4M4.22 4.22l2.83 2.83M16.95 16.95l2.83 2.83M1 12h4M19 12h4M4.22 19.78l2.83-2.83M16.95 7.05l2.83-2.83"/></svg>
|
||||
<span style="font-size:14px;color:var(--tekst-glavni);">
|
||||
Podešavanja teme i pozadine nalaze se na
|
||||
<a href="/profil/tema" style="color:var(--sb-akcent);text-decoration:none;font-weight:500;">stranici Tema</a>.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{ else }}
|
||||
<!-- 2FA nije uključena -->
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px">
|
||||
<div>
|
||||
<div style="font-size: 14px; color: var(--tekst-glavni); margin-bottom: 4px">
|
||||
Status:
|
||||
<strong>Isključena</strong>
|
||||
</div>
|
||||
<div style="font-size: 13px; color: var(--tekst-sporedni)">Preporučujemo uključivanje dvostepene verifikacije.</div>
|
||||
</div>
|
||||
<a href="/admin/profil/totp/pokreni" style="padding: 9px 18px; background: var(--sb-akcent); color: #fff; border-radius: 8px; font-size: 14px; font-weight: 500; text-decoration: none">Podesi 2FA</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
{{ if index .Dozvole "tema.lokalno" }}
|
||||
<div class="kartica animiraj" style="background: var(--pozadina); border: 0.5px solid var(--ivica)">
|
||||
<div style="display: flex; align-items: center; gap: 10px">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="var(--sb-akcent)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="3" />
|
||||
<path d="M12 1v4M12 19v4M4.22 4.22l2.83 2.83M16.95 16.95l2.83 2.83M1 12h4M19 12h4M4.22 19.78l2.83-2.83M16.95 7.05l2.83-2.83" />
|
||||
</svg>
|
||||
<span style="font-size: 14px; color: var(--tekst-glavni)">
|
||||
Podešavanja teme i pozadine nalaze se na
|
||||
<a href="/profil/tema" style="color: var(--sb-akcent); text-decoration: none; font-weight: 500">stranici Tema</a>
|
||||
.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{end}}
|
||||
{{ end }}
|
||||
@@ -1,125 +1,139 @@
|
||||
{{template "base" .}}
|
||||
{{ template "base" . }}
|
||||
|
||||
{{define "naslov"}}Dashboard — NTech{{end}}
|
||||
{{ define "naslov" }}Dashboard — NTech{{ end }}
|
||||
|
||||
{{define "dodatni-css"}}
|
||||
{{ define "dodatni-css" }}
|
||||
<style>
|
||||
.dash-stat:nth-child(1) { animation-delay: 0.04s; }
|
||||
.dash-stat:nth-child(2) { animation-delay: 0.10s; }
|
||||
.dash-stat:nth-child(3) { animation-delay: 0.16s; }
|
||||
.dash-stat:nth-child(4) { animation-delay: 0.22s; }
|
||||
.dash-stat:nth-child(5) { animation-delay: 0.28s; }
|
||||
|
||||
.dash-kartica:nth-child(1) { animation-delay: 0.20s; }
|
||||
.dash-kartica:nth-child(2) { animation-delay: 0.28s; }
|
||||
.dash-kartica:nth-child(3) { animation-delay: 0.36s; }
|
||||
.dash-stat:nth-child(1) { animation-delay: 0.04s; }
|
||||
.dash-stat:nth-child(2) { animation-delay: 0.10s; }
|
||||
.dash-stat:nth-child(3) { animation-delay: 0.16s; }
|
||||
.dash-stat:nth-child(4) { animation-delay: 0.22s; }
|
||||
.dash-stat:nth-child(5) { animation-delay: 0.28s; }
|
||||
.dash-kartica:nth-child(1) { animation-delay: 0.20s; }
|
||||
.dash-kartica:nth-child(2) { animation-delay: 0.28s; }
|
||||
.dash-kartica:nth-child(3) { animation-delay: 0.36s; }
|
||||
</style>
|
||||
{{end}}
|
||||
{{ end }}
|
||||
|
||||
{{define "sadrzaj"}}
|
||||
{{if .FlashGreska}}
|
||||
<div class="poruka-greska animiraj" style="margin-bottom:16px;">{{.FlashGreska}}</div>
|
||||
{{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">
|
||||
<div style="width:36px;height:36px;border-radius:8px;background:#eff2ff;display:flex;align-items:center;justify-content:center;margin-bottom:10px;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#4f7ef8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/></svg>
|
||||
</div>
|
||||
<div style="font-size:22px;font-weight:500;color:var(--tekst-glavni);">{{.BrojArtikala}}</div>
|
||||
<div style="font-size:12px;color:var(--tekst-sporedni);margin-top:4px;">Artikala na stanju</div>
|
||||
</div>
|
||||
<!-- stat kartice -->
|
||||
<div class="kartica dash-stat animiraj">
|
||||
<div style="width:36px;height:36px;border-radius:8px;background:#eff2ff;display:flex;align-items:center;justify-content:center;margin-bottom:10px;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#4f7ef8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div style="font-size:22px;font-weight:500;color:var(--tekst-glavni);">{{ .BrojArtikala }}</div>
|
||||
<div style="font-size:12px;color:var(--tekst-sporedni);margin-top:4px;">Artikala na stanju</div>
|
||||
</div>
|
||||
|
||||
<div class="kartica dash-stat animiraj">
|
||||
<div style="width:36px;height:36px;border-radius:8px;background:#f0fdf4;display:flex;align-items:center;justify-content:center;margin-bottom:10px;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#16a34a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg>
|
||||
</div>
|
||||
<div style="font-size:22px;font-weight:500;color:var(--tekst-glavni);">{{.AktivniServisi}}</div>
|
||||
<div style="font-size:12px;color:var(--tekst-sporedni);margin-top:4px;">Aktivnih servisa</div>
|
||||
</div>
|
||||
<div class="kartica dash-stat animiraj">
|
||||
<div style="width:36px;height:36px;border-radius:8px;background:#f0fdf4;display:flex;align-items:center;justify-content:center;margin-bottom:10px;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#16a34a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div style="font-size:22px;font-weight:500;color:var(--tekst-glavni);">{{ .AktivniServisi }}</div>
|
||||
<div style="font-size:12px;color:var(--tekst-sporedni);margin-top:4px;">Aktivnih servisa</div>
|
||||
</div>
|
||||
|
||||
{{if index .Dozvole "dashboard.prihod"}}
|
||||
<div class="kartica dash-stat animiraj">
|
||||
<div style="width:36px;height:36px;border-radius:8px;background:#fff7ed;display:flex;align-items:center;justify-content:center;margin-bottom:10px;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#ea580c" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/><path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"/></svg>
|
||||
</div>
|
||||
<div style="font-size:22px;font-weight:500;color:var(--tekst-glavni);">{{printf "%.0f" .PrihodOvogMeseca}} din</div>
|
||||
<div style="font-size:12px;color:var(--tekst-sporedni);margin-top:4px;">Prihod ovog meseca</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{ if index .Dozvole "dashboard.prihod" }}
|
||||
<div class="kartica dash-stat animiraj">
|
||||
<div style="width:36px;height:36px;border-radius:8px;background:#fff7ed;display:flex;align-items:center;justify-content:center;margin-bottom:10px;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#ea580c" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="9" cy="21" r="1" />
|
||||
<circle cx="20" cy="21" r="1" />
|
||||
<path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6" />
|
||||
</svg>
|
||||
</div>
|
||||
<div style="font-size:22px;font-weight:500;color:var(--tekst-glavni);">{{ printf "%.0f" .PrihodOvogMeseca }} din</div>
|
||||
<div style="font-size:12px;color:var(--tekst-sporedni);margin-top:4px;">Prihod ovog meseca</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
<div class="kartica dash-stat animiraj">
|
||||
<div style="width:36px;height:36px;border-radius:8px;background:#fef2f2;display:flex;align-items:center;justify-content:center;margin-bottom:10px;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#dc2626" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
|
||||
</div>
|
||||
<div style="font-size:22px;font-weight:500;color:var(--tekst-glavni);">{{.KriticnaZaliha}}</div>
|
||||
<div style="font-size:12px;color:var(--tekst-sporedni);margin-top:4px;">Kritično niska zaliha</div>
|
||||
</div>
|
||||
<div class="kartica dash-stat animiraj">
|
||||
<div style="width:36px;height:36px;border-radius:8px;background:#fef2f2;display:flex;align-items:center;justify-content:center;margin-bottom:10px;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#dc2626" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" />
|
||||
<line x1="12" y1="9" x2="12" y2="13" />
|
||||
<line x1="12" y1="17" x2="12.01" y2="17" />
|
||||
</svg>
|
||||
</div>
|
||||
<div style="font-size:22px;font-weight:500;color:var(--tekst-glavni);">{{ .KriticnaZaliha }}</div>
|
||||
<div style="font-size:12px;color:var(--tekst-sporedni);margin-top:4px;">Kritično niska zaliha</div>
|
||||
</div>
|
||||
|
||||
<a href="/podsetnici" class="kartica dash-stat animiraj" style="text-decoration:none;display:block;">
|
||||
<div style="width:36px;height:36px;border-radius:8px;background:#f0f9ff;display:flex;align-items:center;justify-content:center;margin-bottom:10px;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#0284c7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>
|
||||
</div>
|
||||
<div style="font-size:22px;font-weight:500;color:var(--tekst-glavni);">{{.AktivniPodsetnici}}</div>
|
||||
<div style="font-size:12px;color:var(--tekst-sporedni);margin-top:4px;">Aktivnih podsetnika</div>
|
||||
</a>
|
||||
<a href="/podsetnici" class="kartica dash-stat animiraj" style="text-decoration:none;display:block;">
|
||||
<div style="width:36px;height:36px;border-radius:8px;background:#f0f9ff;display:flex;align-items:center;justify-content:center;margin-bottom:10px;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#0284c7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" />
|
||||
<path d="M13.73 21a2 2 0 0 1-3.46 0" />
|
||||
</svg>
|
||||
</div>
|
||||
<div style="font-size:22px;font-weight:500;color:var(--tekst-glavni);">{{ .AktivniPodsetnici }}</div>
|
||||
<div style="font-size:12px;color:var(--tekst-sporedni);margin-top:4px;">Aktivnih podsetnika</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<!-- poslednji servisi -->
|
||||
<div class="kartica dash-kartica animiraj">
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:14px;">
|
||||
<span style="font-size:14px;font-weight:500;color:var(--tekst-glavni);">Poslednji servisi</span>
|
||||
</div>
|
||||
{{range .PoslednjiServisi}}
|
||||
<div style="display:flex;align-items:center;gap:10px;padding:8px 0;border-bottom:0.5px solid var(--ivica);">
|
||||
<div style="width:8px;height:8px;border-radius:50%;flex-shrink:0;background:{{.BojaTacke}};"></div>
|
||||
<span style="font-size:13px;color:var(--tekst-glavni);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">{{.Uredjaj}}</span>
|
||||
<span style="font-size:11px;color:var(--tekst-sporedni);white-space:nowrap;">{{.DatumPrijema}}</span>
|
||||
</div>
|
||||
{{else}}
|
||||
<div style="font-size:13px;color:var(--tekst-sporedni);padding:8px 0;">Nema servisnih naloga.</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<!-- poslednji servisi -->
|
||||
<div class="kartica dash-kartica animiraj">
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:14px;">
|
||||
<span style="font-size:14px;font-weight:500;color:var(--tekst-glavni);">Poslednji servisi</span>
|
||||
</div>
|
||||
{{ range .PoslednjiServisi }}
|
||||
<div style="display:flex;align-items:center;gap:10px;padding:8px 0;border-bottom:0.5px solid var(--ivica);">
|
||||
<div style="width:8px;height:8px;border-radius:50%;flex-shrink:0;background:{{ .BojaTacke }};"></div>
|
||||
<span style="font-size:13px;color:var(--tekst-glavni);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">{{ .Uredjaj }}</span>
|
||||
<span style="font-size:11px;color:var(--tekst-sporedni);white-space:nowrap;">{{ .DatumPrijema }}</span>
|
||||
</div>
|
||||
{{ else }}
|
||||
<div style="font-size:13px;color:var(--tekst-sporedni);padding:8px 0;">Nema servisnih naloga.</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
<!-- kritične zalihe -->
|
||||
<div class="kartica dash-kartica animiraj">
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:14px;">
|
||||
<span style="font-size:14px;font-weight:500;color:var(--tekst-glavni);">Kritične zalihe</span>
|
||||
<span style="font-size:11px;padding:2px 8px;border-radius:20px;background:rgba(220,38,38,0.15);color:#ef4444;font-weight:500;">Upozorenje</span>
|
||||
</div>
|
||||
{{range .KriticneZalihe}}
|
||||
<div style="display:flex;align-items:center;gap:10px;padding:8px 0;border-bottom:0.5px solid var(--ivica);">
|
||||
<div style="width:8px;height:8px;border-radius:50%;flex-shrink:0;background:{{.BojaTacke}};"></div>
|
||||
<span style="font-size:13px;color:var(--tekst-glavni);flex:1;">{{.Naziv}}</span>
|
||||
<span style="font-size:12px;color:var(--tekst-sporedni);">{{.Kolicina}} kom</span>
|
||||
</div>
|
||||
{{else}}
|
||||
<div style="font-size:13px;color:var(--tekst-sporedni);padding:8px 0;">Sve zalihe su uredne.</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<!-- kritične zalihe -->
|
||||
<div class="kartica dash-kartica animiraj">
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:14px;">
|
||||
<span style="font-size:14px;font-weight:500;color:var(--tekst-glavni);">Kritične zalihe</span>
|
||||
<span style="font-size:11px;padding:2px 8px;border-radius:20px;background:rgba(220,38,38,0.15);color:#ef4444;font-weight:500;">Upozorenje</span>
|
||||
</div>
|
||||
{{ range .KriticneZalihe }}
|
||||
<div style="display:flex;align-items:center;gap:10px;padding:8px 0;border-bottom:0.5px solid var(--ivica);">
|
||||
<div style="width:8px;height:8px;border-radius:50%;flex-shrink:0;background:{{ .BojaTacke }};"></div>
|
||||
<span style="font-size:13px;color:var(--tekst-glavni);flex:1;">{{ .Naziv }}</span>
|
||||
<span style="font-size:12px;color:var(--tekst-sporedni);">{{ .Kolicina }} kom</span>
|
||||
</div>
|
||||
{{ else }}
|
||||
<div style="font-size:13px;color:var(--tekst-sporedni);padding:8px 0;">Sve zalihe su uredne.</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
<!-- poslednje prodaje -->
|
||||
<div class="kartica dash-kartica animiraj">
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:14px;">
|
||||
<span style="font-size:14px;font-weight:500;color:var(--tekst-glavni);">Poslednje prodaje</span>
|
||||
</div>
|
||||
{{range .PoslednjeProdaje}}
|
||||
<div style="display:flex;align-items:center;gap:10px;padding:8px 0;border-bottom:0.5px solid var(--ivica);">
|
||||
<div style="flex:1;min-width:0;">
|
||||
<div style="font-size:13px;color:var(--tekst-glavni);font-family:monospace;">{{.BrojNaloga}}</div>
|
||||
{{if .KlijentNaziv}}
|
||||
<div style="font-size:11px;color:var(--tekst-sporedni);margin-top:1px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">{{.KlijentNaziv}}</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<div style="text-align:right;flex-shrink:0;">
|
||||
<div style="font-size:13px;font-weight:500;color:var(--tekst-glavni);">{{printf "%.0f" .Ukupno}} din</div>
|
||||
<div style="font-size:11px;color:var(--tekst-sporedni);margin-top:1px;">{{.Datum}}</div>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div style="font-size:13px;color:var(--tekst-sporedni);padding:8px 0;">Nema prodajnih naloga.</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<!-- poslednje prodaje -->
|
||||
<div class="kartica dash-kartica animiraj">
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:14px;">
|
||||
<span style="font-size:14px;font-weight:500;color:var(--tekst-glavni);">Poslednje prodaje</span>
|
||||
</div>
|
||||
{{ range .PoslednjeProdaje }}
|
||||
<div style="display:flex;align-items:center;gap:10px;padding:8px 0;border-bottom:0.5px solid var(--ivica);">
|
||||
<div style="flex:1;min-width:0;">
|
||||
<div style="font-size:13px;color:var(--tekst-glavni);font-family:monospace;">{{ .BrojNaloga }}</div>
|
||||
{{ if .KlijentNaziv }}
|
||||
<div style="font-size:11px;color:var(--tekst-sporedni);margin-top:1px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">{{ .KlijentNaziv }}</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div style="text-align:right;flex-shrink:0;">
|
||||
<div style="font-size:13px;font-weight:500;color:var(--tekst-glavni);">{{ printf "%.0f" .Ukupno }} din</div>
|
||||
<div style="font-size:11px;color:var(--tekst-sporedni);margin-top:1px;">{{ .Datum }}</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ else }}
|
||||
<div style="font-size:13px;color:var(--tekst-sporedni);padding:8px 0;">Nema prodajnih naloga.</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{ end }}
|
||||
@@ -4,35 +4,32 @@
|
||||
|
||||
{{define "dodatni-css"}}
|
||||
<style>
|
||||
.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; }
|
||||
.dobavljaci-tabela tbody tr:nth-child(2) { animation-delay: 0.08s; }
|
||||
.dobavljaci-tabela tbody tr:nth-child(3) { animation-delay: 0.12s; }
|
||||
.dobavljaci-tabela tbody tr:nth-child(4) { animation-delay: 0.16s; }
|
||||
.dobavljaci-tabela tbody tr:nth-child(5) { animation-delay: 0.20s; }
|
||||
.dobavljaci-tabela tbody tr:nth-child(6) { animation-delay: 0.24s; }
|
||||
.dobavljaci-tabela tbody tr:nth-child(7) { animation-delay: 0.28s; }
|
||||
.dobavljaci-tabela tbody tr:nth-child(8) { animation-delay: 0.32s; }
|
||||
.dobavljaci-tabela tbody tr:nth-child(9) { animation-delay: 0.36s; }
|
||||
.dobavljaci-tabela tbody tr:nth-child(10) { animation-delay: 0.40s; }
|
||||
|
||||
.dobavljaci-kartice {
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.dobavljac-kartica:nth-child(1) { animation-delay: 0.04s; }
|
||||
.dobavljac-kartica:nth-child(2) { animation-delay: 0.10s; }
|
||||
.dobavljac-kartica:nth-child(3) { animation-delay: 0.16s; }
|
||||
.dobavljac-kartica:nth-child(4) { animation-delay: 0.22s; }
|
||||
.dobavljac-kartica:nth-child(5) { animation-delay: 0.28s; }
|
||||
.poruka-animacija { animation: slideDown 0.3s ease forwards; }
|
||||
.dobavljaci-tabela tbody tr:nth-child(1) { animation-delay: 0.04s; }
|
||||
.dobavljaci-tabela tbody tr:nth-child(2) { animation-delay: 0.08s; }
|
||||
.dobavljaci-tabela tbody tr:nth-child(3) { animation-delay: 0.12s; }
|
||||
.dobavljaci-tabela tbody tr:nth-child(4) { animation-delay: 0.16s; }
|
||||
.dobavljaci-tabela tbody tr:nth-child(5) { animation-delay: 0.20s; }
|
||||
.dobavljaci-tabela tbody tr:nth-child(6) { animation-delay: 0.24s; }
|
||||
.dobavljaci-tabela tbody tr:nth-child(7) { animation-delay: 0.28s; }
|
||||
.dobavljaci-tabela tbody tr:nth-child(8) { animation-delay: 0.32s; }
|
||||
.dobavljaci-tabela tbody tr:nth-child(9) { animation-delay: 0.36s; }
|
||||
.dobavljaci-tabela tbody tr:nth-child(10) { animation-delay: 0.40s; }
|
||||
.dobavljaci-kartice { display: none; flex-direction: column; gap: 12px; }
|
||||
.dobavljac-kartica:nth-child(1) { animation-delay: 0.04s; }
|
||||
.dobavljac-kartica:nth-child(2) { animation-delay: 0.10s; }
|
||||
.dobavljac-kartica:nth-child(3) { animation-delay: 0.16s; }
|
||||
.dobavljac-kartica:nth-child(4) { animation-delay: 0.22s; }
|
||||
.dobavljac-kartica:nth-child(5) { animation-delay: 0.28s; }
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.dobavljaci-tabela { display: none; }
|
||||
.dobavljaci-kartice { display: flex; }
|
||||
.dobavljaci-tabela {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dobavljaci-kartice {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{{end}}
|
||||
@@ -163,4 +160,4 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
@@ -5,88 +5,22 @@
|
||||
{{define "dodatni-css"}}
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.4/dist/chart.umd.min.js"></script>
|
||||
<style>
|
||||
.izv-naslov {
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--tekst-sporedni);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.toggle-red {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.toggle-switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 40px;
|
||||
height: 22px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.izv-naslov { font-size: 13px; font-weight: 500; color: var(--tekst-sporedni); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 14px; }
|
||||
.toggle-red { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; }
|
||||
.toggle-switch { position: relative; display: inline-block; width: 40px; height: 22px; flex-shrink: 0; }
|
||||
.toggle-switch input { opacity: 0; width: 0; height: 0; }
|
||||
|
||||
.toggle-slider {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: var(--ivica);
|
||||
border-radius: 22px;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.toggle-slider::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
left: 3px;
|
||||
top: 3px;
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
|
||||
.toggle-slider { position: absolute; inset: 0; background: var(--ivica); border-radius: 22px; cursor: pointer; transition: background 0.2s; }
|
||||
.toggle-slider::before { content: ''; position: absolute; width: 16px; height: 16px; left: 3px; top: 3px; background: #fff; border-radius: 50%; transition: transform 0.2s; }
|
||||
.toggle-switch input:checked + .toggle-slider { background: var(--sb-akcent); }
|
||||
.toggle-switch input:checked + .toggle-slider::before { transform: translateX(18px); }
|
||||
|
||||
.rang-broj {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border-radius: 50%;
|
||||
background: var(--pozadina);
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: var(--tekst-sporedni);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.rang-broj { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 50%; background: var(--pozadina); font-size: 11px; font-weight: 600; color: var(--tekst-sporedni); flex-shrink: 0; }
|
||||
.rang-broj.zlatni { background: #fef3c7; color: #92400e; }
|
||||
|
||||
.badge-dana {
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
border-radius: 20px;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.badge-dana { display: inline-block; padding: 2px 8px; border-radius: 20px; font-size: 11px; font-weight: 500; white-space: nowrap; }
|
||||
.badge-dana.upozorenje { background: #fffbeb; color: #b45309; }
|
||||
.badge-dana.kritican { background: #fef2f2; color: #dc2626; }
|
||||
|
||||
.badge-dana.kritican { background: #fef2f2; color: #dc2626; }
|
||||
.izv-sekcija:nth-child(1) { animation-delay: 0.04s; }
|
||||
.izv-sekcija:nth-child(2) { animation-delay: 0.12s; }
|
||||
.izv-sekcija:nth-child(3) { animation-delay: 0.20s; }
|
||||
|
||||
.izv-grid-kartica:nth-child(1) { animation-delay: 0.24s; }
|
||||
.izv-grid-kartica:nth-child(2) { animation-delay: 0.32s; }
|
||||
</style>
|
||||
|
||||
@@ -5,11 +5,7 @@
|
||||
{{define "dodatni-css"}}
|
||||
<style>
|
||||
.poruka-animacija { animation: slideDown 0.3s ease forwards; }
|
||||
|
||||
.kat-forma-kartica {
|
||||
animation-delay: 0.04s;
|
||||
}
|
||||
|
||||
.kat-forma-kartica { animation-delay: 0.04s; }
|
||||
.kat-red:nth-child(1) { animation-delay: 0.12s; }
|
||||
.kat-red:nth-child(2) { animation-delay: 0.18s; }
|
||||
.kat-red:nth-child(3) { animation-delay: 0.24s; }
|
||||
|
||||
@@ -5,34 +5,23 @@
|
||||
{{define "dodatni-css"}}
|
||||
<style>
|
||||
.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; }
|
||||
.klijenti-tabela tbody tr:nth-child(3) { animation-delay: 0.12s; }
|
||||
.klijenti-tabela tbody tr:nth-child(4) { animation-delay: 0.16s; }
|
||||
.klijenti-tabela tbody tr:nth-child(5) { animation-delay: 0.20s; }
|
||||
.klijenti-tabela tbody tr:nth-child(6) { animation-delay: 0.24s; }
|
||||
.klijenti-tabela tbody tr:nth-child(7) { animation-delay: 0.28s; }
|
||||
.klijenti-tabela tbody tr:nth-child(8) { animation-delay: 0.32s; }
|
||||
.klijenti-tabela tbody tr:nth-child(9) { animation-delay: 0.36s; }
|
||||
.klijenti-tabela tbody tr:nth-child(1) { animation-delay: 0.04s; }
|
||||
.klijenti-tabela tbody tr:nth-child(2) { animation-delay: 0.08s; }
|
||||
.klijenti-tabela tbody tr:nth-child(3) { animation-delay: 0.12s; }
|
||||
.klijenti-tabela tbody tr:nth-child(4) { animation-delay: 0.16s; }
|
||||
.klijenti-tabela tbody tr:nth-child(5) { animation-delay: 0.20s; }
|
||||
.klijenti-tabela tbody tr:nth-child(6) { animation-delay: 0.24s; }
|
||||
.klijenti-tabela tbody tr:nth-child(7) { animation-delay: 0.28s; }
|
||||
.klijenti-tabela tbody tr:nth-child(8) { animation-delay: 0.32s; }
|
||||
.klijenti-tabela tbody tr:nth-child(9) { animation-delay: 0.36s; }
|
||||
.klijenti-tabela tbody tr:nth-child(10) { animation-delay: 0.40s; }
|
||||
|
||||
.klijenti-kartice {
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.klijent-kartica:nth-child(1) { animation-delay: 0.04s; }
|
||||
.klijent-kartica:nth-child(2) { animation-delay: 0.10s; }
|
||||
.klijent-kartica:nth-child(3) { animation-delay: 0.16s; }
|
||||
.klijent-kartica:nth-child(4) { animation-delay: 0.22s; }
|
||||
.klijent-kartica:nth-child(5) { animation-delay: 0.28s; }
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.klijenti-tabela { display: none; }
|
||||
.klijenti-kartice { display: flex; }
|
||||
}
|
||||
.klijenti-kartice { display: none; flex-direction: column; gap: 12px; }
|
||||
.klijent-kartica:nth-child(1) { animation-delay: 0.04s; }
|
||||
.klijent-kartica:nth-child(2) { animation-delay: 0.10s; }
|
||||
.klijent-kartica:nth-child(3) { animation-delay: 0.16s; }
|
||||
.klijent-kartica:nth-child(4) { animation-delay: 0.22s; }
|
||||
.klijent-kartica:nth-child(5) { animation-delay: 0.28s; }
|
||||
@media (max-width: 768px) { .klijenti-tabela { display: none; } .klijenti-kartice { display: flex; } }
|
||||
</style>
|
||||
{{end}}
|
||||
|
||||
|
||||
@@ -4,33 +4,23 @@
|
||||
|
||||
{{define "dodatni-css"}}
|
||||
<style>
|
||||
.magacin-tabela tbody tr:nth-child(1) { animation-delay: 0.04s; }
|
||||
.magacin-tabela tbody tr:nth-child(2) { animation-delay: 0.08s; }
|
||||
.magacin-tabela tbody tr:nth-child(3) { animation-delay: 0.12s; }
|
||||
.magacin-tabela tbody tr:nth-child(4) { animation-delay: 0.16s; }
|
||||
.magacin-tabela tbody tr:nth-child(5) { animation-delay: 0.20s; }
|
||||
.magacin-tabela tbody tr:nth-child(6) { animation-delay: 0.24s; }
|
||||
.magacin-tabela tbody tr:nth-child(7) { animation-delay: 0.28s; }
|
||||
.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(1) { animation-delay: 0.04s; }
|
||||
.magacin-tabela tbody tr:nth-child(2) { animation-delay: 0.08s; }
|
||||
.magacin-tabela tbody tr:nth-child(3) { animation-delay: 0.12s; }
|
||||
.magacin-tabela tbody tr:nth-child(4) { animation-delay: 0.16s; }
|
||||
.magacin-tabela tbody tr:nth-child(5) { animation-delay: 0.20s; }
|
||||
.magacin-tabela tbody tr:nth-child(6) { animation-delay: 0.24s; }
|
||||
.magacin-tabela tbody tr:nth-child(7) { animation-delay: 0.28s; }
|
||||
.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-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; }
|
||||
}
|
||||
@media (max-width: 768px) { .magacin-tabela { display: none; } .magacin-kartice { display: flex; } }
|
||||
</style>
|
||||
{{end}}
|
||||
|
||||
|
||||
@@ -7,23 +7,13 @@
|
||||
.detalji-kartica:nth-child(1) { animation-delay: 0.04s; }
|
||||
.detalji-kartica:nth-child(2) { animation-delay: 0.12s; }
|
||||
.detalji-kartica:nth-child(3) { animation-delay: 0.20s; }
|
||||
|
||||
.stavke-tabela tbody tr:nth-child(1) { animation-delay: 0.16s; }
|
||||
.stavke-tabela tbody tr:nth-child(2) { animation-delay: 0.20s; }
|
||||
.stavke-tabela tbody tr:nth-child(3) { animation-delay: 0.24s; }
|
||||
.stavke-tabela tbody tr:nth-child(4) { animation-delay: 0.28s; }
|
||||
.stavke-tabela tbody tr:nth-child(5) { animation-delay: 0.32s; }
|
||||
|
||||
.stavke-kartice {
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.stavke-tabela-wrapper { display: none; }
|
||||
.stavke-kartice { display: flex; }
|
||||
}
|
||||
.stavke-kartice { display: none; flex-direction: column; gap: 10px; }
|
||||
@media (max-width: 768px) { .stavke-tabela-wrapper { display: none; } .stavke-kartice { display: flex; } }
|
||||
</style>
|
||||
{{end}}
|
||||
|
||||
|
||||
@@ -4,22 +4,12 @@
|
||||
|
||||
{{define "dodatni-css"}}
|
||||
<style>
|
||||
@keyframes modalIn {
|
||||
from { opacity: 0; transform: translateY(-16px) scale(0.97); }
|
||||
to { opacity: 1; transform: translateY(0) scale(1); }
|
||||
}
|
||||
|
||||
@keyframes modalIn { from { opacity: 0; transform: translateY(-16px) scale(0.97); } to { opacity: 1; transform: translateY(0) scale(1); } }
|
||||
.forma-kartica:nth-child(1) { animation-delay: 0.04s; }
|
||||
.forma-kartica:nth-child(2) { animation-delay: 0.12s; }
|
||||
|
||||
.greska-animacija { animation: shake 0.4s ease; }
|
||||
|
||||
.modal-sadrzaj { animation: modalIn 0.25s ease forwards; }
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.stavke-tabela-wrapper { display: none; }
|
||||
.stavke-kartice { display: flex !important; }
|
||||
}
|
||||
@media (max-width: 768px) { .stavke-tabela-wrapper { display: none; } .stavke-kartice { display: flex !important; } }
|
||||
</style>
|
||||
{{end}}
|
||||
|
||||
|
||||
@@ -5,34 +5,23 @@
|
||||
{{define "dodatni-css"}}
|
||||
<style>
|
||||
.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; }
|
||||
.nabavke-tabela tbody tr:nth-child(3) { animation-delay: 0.12s; }
|
||||
.nabavke-tabela tbody tr:nth-child(4) { animation-delay: 0.16s; }
|
||||
.nabavke-tabela tbody tr:nth-child(5) { animation-delay: 0.20s; }
|
||||
.nabavke-tabela tbody tr:nth-child(6) { animation-delay: 0.24s; }
|
||||
.nabavke-tabela tbody tr:nth-child(7) { animation-delay: 0.28s; }
|
||||
.nabavke-tabela tbody tr:nth-child(8) { animation-delay: 0.32s; }
|
||||
.nabavke-tabela tbody tr:nth-child(9) { animation-delay: 0.36s; }
|
||||
.nabavke-tabela tbody tr:nth-child(1) { animation-delay: 0.04s; }
|
||||
.nabavke-tabela tbody tr:nth-child(2) { animation-delay: 0.08s; }
|
||||
.nabavke-tabela tbody tr:nth-child(3) { animation-delay: 0.12s; }
|
||||
.nabavke-tabela tbody tr:nth-child(4) { animation-delay: 0.16s; }
|
||||
.nabavke-tabela tbody tr:nth-child(5) { animation-delay: 0.20s; }
|
||||
.nabavke-tabela tbody tr:nth-child(6) { animation-delay: 0.24s; }
|
||||
.nabavke-tabela tbody tr:nth-child(7) { animation-delay: 0.28s; }
|
||||
.nabavke-tabela tbody tr:nth-child(8) { animation-delay: 0.32s; }
|
||||
.nabavke-tabela tbody tr:nth-child(9) { animation-delay: 0.36s; }
|
||||
.nabavke-tabela tbody tr:nth-child(10) { animation-delay: 0.40s; }
|
||||
|
||||
.nabavke-kartice {
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.nabavke-kartice { display: none; flex-direction: column; gap: 12px; }
|
||||
.nabavka-kartica:nth-child(1) { animation-delay: 0.04s; }
|
||||
.nabavka-kartica:nth-child(2) { animation-delay: 0.10s; }
|
||||
.nabavka-kartica:nth-child(3) { animation-delay: 0.16s; }
|
||||
.nabavka-kartica:nth-child(4) { animation-delay: 0.22s; }
|
||||
.nabavka-kartica:nth-child(5) { animation-delay: 0.28s; }
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.nabavke-tabela { display: none; }
|
||||
.nabavke-kartice { display: flex; }
|
||||
}
|
||||
@media (max-width: 768px) { .nabavke-tabela { display: none; } .nabavke-kartice { display: flex; } }
|
||||
</style>
|
||||
{{end}}
|
||||
|
||||
|
||||
@@ -8,74 +8,17 @@
|
||||
.animiraj:nth-child(2) { animation-delay: 0.16s; }
|
||||
.animiraj:nth-child(3) { animation-delay: 0.22s; }
|
||||
.animiraj:nth-child(4) { animation-delay: 0.28s; }
|
||||
|
||||
/* dvostupčani raspored za app pozadinu */
|
||||
.app-poz-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 20px;
|
||||
align-items: start;
|
||||
}
|
||||
@media (max-width: 680px) {
|
||||
.app-poz-grid { grid-template-columns: 1fr; }
|
||||
}
|
||||
|
||||
/* custom file input */
|
||||
.custom-file-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 12px;
|
||||
background: var(--pozadina);
|
||||
border: 0.5px solid var(--ivica);
|
||||
border-radius: 8px;
|
||||
font-size: 13px;
|
||||
color: var(--tekst-sporedni);
|
||||
cursor: pointer;
|
||||
transition: border-color 0.2s;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.app-poz-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: start; }
|
||||
@media (max-width: 680px) { .app-poz-grid { grid-template-columns: 1fr; } }
|
||||
.custom-file-label { display: flex; align-items: center; gap: 8px; padding: 8px 12px; background: var(--pozadina); border: 0.5px solid var(--ivica); border-radius: 8px; font-size: 13px; color: var(--tekst-sporedni); cursor: pointer; transition: border-color 0.2s; min-width: 0; overflow: hidden; }
|
||||
.custom-file-label:hover { border-color: var(--sb-akcent); color: var(--tekst-glavni); }
|
||||
.custom-file-label span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
|
||||
.toast {
|
||||
position: fixed;
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 18px;
|
||||
border-radius: 10px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
|
||||
animation: toastIn 0.3s ease forwards;
|
||||
max-width: 340px;
|
||||
}
|
||||
.toast-greska {
|
||||
background: #fef2f2;
|
||||
color: #dc2626;
|
||||
border: 0.5px solid #fca5a5;
|
||||
}
|
||||
.toast-uspeh {
|
||||
background: #f0fdf4;
|
||||
color: #16a34a;
|
||||
border: 0.5px solid #86efac;
|
||||
}
|
||||
@keyframes toastIn {
|
||||
from { opacity: 0; transform: translateY(12px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
@keyframes toastOut {
|
||||
from { opacity: 1; transform: translateY(0); }
|
||||
to { opacity: 0; transform: translateY(12px); }
|
||||
}
|
||||
.toast.nestaje {
|
||||
animation: toastOut 0.3s ease forwards;
|
||||
}
|
||||
.toast { position: fixed; bottom: 24px; right: 24px; z-index: 9999; display: flex; align-items: center; gap: 10px; padding: 12px 18px; border-radius: 10px; font-size: 13px; font-weight: 500; box-shadow: 0 4px 20px rgba(0,0,0,0.15); animation: toastIn 0.3s ease forwards; max-width: 340px; }
|
||||
.toast-greska { background: #fef2f2; color: #dc2626; border: 0.5px solid #fca5a5; }
|
||||
.toast-uspeh { background: #f0fdf4; color: #16a34a; border: 0.5px solid #86efac; }
|
||||
@keyframes toastIn { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
|
||||
@keyframes toastOut { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(12px); } }
|
||||
.toast.nestaje { animation: toastOut 0.3s ease forwards; }
|
||||
</style>
|
||||
{{end}}
|
||||
|
||||
|
||||
@@ -7,16 +7,8 @@
|
||||
.animiraj:nth-child(1) { animation-delay: 0.10s; }
|
||||
.animiraj:nth-child(2) { animation-delay: 0.16s; }
|
||||
.animiraj:nth-child(3) { animation-delay: 0.22s; }
|
||||
|
||||
.app-poz-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 20px;
|
||||
align-items: start;
|
||||
}
|
||||
@media (max-width: 680px) {
|
||||
.app-poz-grid { grid-template-columns: 1fr; }
|
||||
}
|
||||
.app-poz-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: start; }
|
||||
@media (max-width: 680px) { .app-poz-grid { grid-template-columns: 1fr; } }
|
||||
</style>
|
||||
{{end}}
|
||||
|
||||
|
||||
@@ -7,43 +7,12 @@
|
||||
.animiraj:nth-child(1) { animation-delay: 0.10s; }
|
||||
.animiraj:nth-child(2) { animation-delay: 0.16s; }
|
||||
|
||||
.toast {
|
||||
position: fixed;
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 18px;
|
||||
border-radius: 10px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
|
||||
animation: toastIn 0.3s ease forwards;
|
||||
max-width: 340px;
|
||||
}
|
||||
.toast-greska {
|
||||
background: #fef2f2;
|
||||
color: #dc2626;
|
||||
border: 0.5px solid #fca5a5;
|
||||
}
|
||||
.toast-uspeh {
|
||||
background: #f0fdf4;
|
||||
color: #16a34a;
|
||||
border: 0.5px solid #86efac;
|
||||
}
|
||||
@keyframes toastIn {
|
||||
from { opacity: 0; transform: translateY(12px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
@keyframes toastOut {
|
||||
from { opacity: 1; transform: translateY(0); }
|
||||
to { opacity: 0; transform: translateY(12px); }
|
||||
}
|
||||
.toast.nestaje {
|
||||
animation: toastOut 0.3s ease forwards;
|
||||
}
|
||||
.toast { position: fixed; bottom: 24px; right: 24px; z-index: 9999; display: flex; align-items: center; gap: 10px; padding: 12px 18px; border-radius: 10px; font-size: 13px; font-weight: 500; box-shadow: 0 4px 20px rgba(0,0,0,0.15); animation: toastIn 0.3s ease forwards; max-width: 340px; }
|
||||
.toast-greska { background: #fef2f2; color: #dc2626; border: 0.5px solid #fca5a5; }
|
||||
.toast-uspeh { background: #f0fdf4; color: #16a34a; border: 0.5px solid #86efac; }
|
||||
@keyframes toastIn { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
|
||||
@keyframes toastOut { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(12px); } }
|
||||
.toast.nestaje { animation: toastOut 0.3s ease forwards; }
|
||||
</style>
|
||||
{{end}}
|
||||
|
||||
|
||||
@@ -17,26 +17,14 @@
|
||||
.pod-tabela tbody tr:nth-child(9) { animation-delay: 0.36s; }
|
||||
.pod-tabela tbody tr:nth-child(10) { animation-delay: 0.40s; }
|
||||
|
||||
.pod-kartice {
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.pod-kartice { display: none; flex-direction: column; gap: 12px; }
|
||||
.pod-kartica:nth-child(1) { animation-delay: 0.04s; }
|
||||
.pod-kartica:nth-child(2) { animation-delay: 0.10s; }
|
||||
.pod-kartica:nth-child(3) { animation-delay: 0.16s; }
|
||||
.pod-kartica:nth-child(4) { animation-delay: 0.22s; }
|
||||
.pod-kartica:nth-child(5) { animation-delay: 0.28s; }
|
||||
|
||||
.red-prekoracen td {
|
||||
background: rgba(207, 87, 87, 0.06);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.pod-tabela { display: none; }
|
||||
.pod-kartice { display: flex; }
|
||||
}
|
||||
.red-prekoracen td { background: rgba(207, 87, 87, 0.06); }
|
||||
@media (max-width: 768px) { .pod-tabela { display: none; } .pod-kartice { display: flex; } }
|
||||
</style>
|
||||
{{end}}
|
||||
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
|
||||
{{define "dodatni-css"}}
|
||||
<style>
|
||||
.greska-animacija {
|
||||
animation: shake 0.4s ease;
|
||||
}
|
||||
.greska-animacija { animation: shake 0.4s ease; }
|
||||
</style>
|
||||
{{end}}
|
||||
|
||||
|
||||
@@ -1,160 +1,74 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="sr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Prijava — NTech</title>
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||
background: #0f1117;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 16px;
|
||||
position: relative;
|
||||
}
|
||||
.kartica {
|
||||
background: #1a1d27;
|
||||
border: 0.5px solid #2d3148;
|
||||
border-radius: 16px;
|
||||
padding: 40px;
|
||||
width: 100%;
|
||||
max-width: 380px;
|
||||
}
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Prijava — NTech</title>
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #0f1117; min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 16px; position: relative; }
|
||||
.kartica { background: #1a1d27; border: 0.5px solid #2d3148; border-radius: 16px; padding: 40px; width: 100%; max-width: 380px; }
|
||||
{{if .LoginPozadina}}.kartica { background: rgba(0, 0, 0, {{.LoginPozadinaZatamnjenjeKartice}}%) !important; backdrop-filter: blur({{.LoginPozadinaBlurKartice}}px); -webkit-backdrop-filter: blur({{.LoginPozadinaBlurKartice}}px); border: 1px solid rgba(255, 255, 255, 0.18) !important; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); }{{end}}
|
||||
.logo { text-align: center; margin-bottom: 32px; }
|
||||
.logo-naziv { font-size: 22px; font-weight: 600; color: #fff; letter-spacing: -0.3px; }
|
||||
.logo-podnazlov { font-size: 13px; color: #6b7280; margin-top: 4px; }
|
||||
h1 { font-size: 18px; font-weight: 600; color: #fff; margin-bottom: 24px; }
|
||||
.polje { margin-bottom: 16px; }
|
||||
label { display: block; font-size: 13px; color: #9ca3af; margin-bottom: 6px; }
|
||||
input { width: 100%; padding: 8px 12px; background: #0f1117; border: 0.5px solid #2d3148; border-radius: 8px; font-size: 14px; color: #fff; outline: none; transition: border-color 0.2s; }
|
||||
input:focus { border-color: #e53e3e; }
|
||||
.dugme { width: 100%; padding: 11px; background: #e53e3e; color: #fff; border: none; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; margin-top: 8px; transition: opacity 0.2s; }
|
||||
.dugme:hover { opacity: 0.88; }
|
||||
.greska { background: #fef2f2; border: 0.5px solid #fca5a5; color: #dc2626; border-radius: 8px; padding: 10px 14px; font-size: 13px; margin-bottom: 20px; }
|
||||
.uspeh { background: #f0fdf4; border: 0.5px solid #86efac; color: #16a34a; border-radius: 8px; padding: 10px 14px; font-size: 13px; margin-bottom: 20px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
{{if .LoginPozadina}}
|
||||
.kartica {
|
||||
background: rgba(0,0,0,{{.LoginPozadinaZatamnjenjeKartice}}%) !important;
|
||||
backdrop-filter: blur({{.LoginPozadinaBlurKartice}}px);
|
||||
-webkit-backdrop-filter: blur({{.LoginPozadinaBlurKartice}}px);
|
||||
border: 1px solid rgba(255,255,255,0.18) !important;
|
||||
box-shadow: 0 8px 32px rgba(0,0,0,0.3);
|
||||
}
|
||||
{{end}}
|
||||
.logo {
|
||||
text-align: center;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.logo-naziv {
|
||||
font-size: 22px;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
letter-spacing: -0.3px;
|
||||
}
|
||||
.logo-podnazlov {
|
||||
font-size: 13px;
|
||||
color: #6b7280;
|
||||
margin-top: 4px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.polje { margin-bottom: 16px; }
|
||||
label {
|
||||
display: block;
|
||||
font-size: 13px;
|
||||
color: #9ca3af;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
input {
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
background: #0f1117;
|
||||
border: 0.5px solid #2d3148;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
outline: none;
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
input:focus { border-color: #e53e3e; }
|
||||
.dugme {
|
||||
width: 100%;
|
||||
padding: 11px;
|
||||
background: #e53e3e;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
margin-top: 8px;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
.dugme:hover { opacity: 0.88; }
|
||||
.greska {
|
||||
background: #fef2f2;
|
||||
border: 0.5px solid #fca5a5;
|
||||
color: #dc2626;
|
||||
border-radius: 8px;
|
||||
padding: 10px 14px;
|
||||
font-size: 13px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.uspeh {
|
||||
background: #f0fdf4;
|
||||
border: 0.5px solid #86efac;
|
||||
color: #16a34a;
|
||||
border-radius: 8px;
|
||||
padding: 10px 14px;
|
||||
font-size: 13px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
{{if .LoginPozadina}}
|
||||
<div style="position:fixed;inset:0;z-index:-1;background-image:url('{{.LoginPozadina}}');background-size:cover;background-position:center;{{if ne .LoginPozadinaBlurPozadine "0"}}filter:blur({{.LoginPozadinaBlurPozadine}}px);transform:scale(1.05);{{end}}"></div>
|
||||
<div style="position:fixed;inset:0;z-index:0;background:rgba(0,0,0,{{.LoginPozadinaOpacity}}%);"></div>
|
||||
<div style="position:fixed;inset:0;display:flex;align-items:center;justify-content:center;z-index:1;padding:16px;">
|
||||
{{end}}
|
||||
<div style="position:fixed;inset:0;z-index:-1;background-image:url('{{.LoginPozadina}}');background-size:cover;background-position:center;{{if ne .LoginPozadinaBlurPozadine " 0"}}filter:blur({{.LoginPozadinaBlurPozadine}}px);transform:scale(1.05);{{end}}"></div>
|
||||
<div style="position:fixed;inset:0;z-index:0;background:rgba(0,0,0,{{.LoginPozadinaOpacity}}%);"></div>
|
||||
<div style="position:fixed;inset:0;display:flex;align-items:center;justify-content:center;z-index:1;padding:16px;">
|
||||
{{end}}
|
||||
|
||||
<div class="kartica animiraj">
|
||||
<div class="logo">
|
||||
<div class="logo-naziv">NTech</div>
|
||||
<div class="logo-podnazlov">Sistem za upravljanje</div>
|
||||
</div>
|
||||
<div class="kartica animiraj">
|
||||
<div class="logo">
|
||||
<div class="logo-naziv">NTech</div>
|
||||
<div class="logo-podnazlov">Sistem za upravljanje</div>
|
||||
</div>
|
||||
|
||||
<h1>Prijava</h1>
|
||||
<h1>Prijava</h1>
|
||||
|
||||
{{if eq .Greska "1"}}
|
||||
<div class="greska">Pogrešno korisničko ime ili lozinka.</div>
|
||||
{{else if eq .Greska "2"}}
|
||||
<div class="greska">Greška na serveru. Pokušajte ponovo.</div>
|
||||
{{else if eq .Greska "zakljucano"}}
|
||||
<div class="greska">
|
||||
Previše neuspelih pokušaja prijave. IP adresa je privremeno blokirana.
|
||||
{{if .Preostalo}}<br>Pokušajte ponovo za: <strong>{{.Preostalo}}</strong>{{end}}
|
||||
{{if eq .Greska "1"}}
|
||||
<div class="greska">Pogrešno korisničko ime ili lozinka.</div>
|
||||
{{else if eq .Greska "2"}}
|
||||
<div class="greska">Greška na serveru. Pokušajte ponovo.</div>
|
||||
{{else if eq .Greska "zakljucano"}}
|
||||
<div class="greska">
|
||||
Previše neuspelih pokušaja prijave. IP adresa je privremeno blokirana.
|
||||
{{if .Preostalo}}<br>Pokušajte ponovo za: <strong>{{.Preostalo}}</strong>{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if .Sacuvano}}
|
||||
<div class="uspeh">Nalog je kreiran. Možete se prijaviti.</div>
|
||||
{{end}}
|
||||
|
||||
<form method="POST" action="/prijava">
|
||||
<input type="hidden" name="_csrf" value="{{.CsrfToken}}">
|
||||
<div class="polje">
|
||||
<label for="korisnicko_ime">Korisničko ime</label>
|
||||
<input type="text" id="korisnicko_ime" name="korisnicko_ime" autocomplete="username" autofocus required>
|
||||
</div>
|
||||
<div class="polje">
|
||||
<label for="lozinka">Lozinka</label>
|
||||
<input type="password" id="lozinka" name="lozinka" autocomplete="current-password" required>
|
||||
</div>
|
||||
<button type="submit" class="dugme">Prijavi se</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{{if .LoginPozadina}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if .Sacuvano}}
|
||||
<div class="uspeh">Nalog je kreiran. Možete se prijaviti.</div>
|
||||
{{end}}
|
||||
|
||||
<form method="POST" action="/prijava">
|
||||
<input type="hidden" name="_csrf" value="{{.CsrfToken}}">
|
||||
<div class="polje">
|
||||
<label for="korisnicko_ime">Korisničko ime</label>
|
||||
<input type="text" id="korisnicko_ime" name="korisnicko_ime"
|
||||
autocomplete="username" autofocus required>
|
||||
</div>
|
||||
<div class="polje">
|
||||
<label for="lozinka">Lozinka</label>
|
||||
<input type="password" id="lozinka" name="lozinka"
|
||||
autocomplete="current-password" required>
|
||||
</div>
|
||||
<button type="submit" class="dugme">Prijavi se</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{{if .LoginPozadina}}
|
||||
</div>
|
||||
{{end}}
|
||||
</body>
|
||||
</html>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,103 +1,71 @@
|
||||
{{template "base" .}}
|
||||
|
||||
{{define "naslov"}}Prodaja — NTech{{end}}
|
||||
|
||||
{{define "dodatni-css"}}
|
||||
{{template "base" .}} {{define "naslov"}}Prodaja — NTech{{end}} {{define "dodatni-css"}}
|
||||
<style>
|
||||
.poruka-animacija { animation: slideDown 0.3s ease forwards; }
|
||||
|
||||
.prodaja-tabela tbody tr:nth-child(1) { animation-delay: 0.04s; }
|
||||
.prodaja-tabela tbody tr:nth-child(2) { animation-delay: 0.08s; }
|
||||
.prodaja-tabela tbody tr:nth-child(3) { animation-delay: 0.12s; }
|
||||
.prodaja-tabela tbody tr:nth-child(4) { animation-delay: 0.16s; }
|
||||
.prodaja-tabela tbody tr:nth-child(5) { animation-delay: 0.20s; }
|
||||
.prodaja-tabela tbody tr:nth-child(6) { animation-delay: 0.24s; }
|
||||
.prodaja-tabela tbody tr:nth-child(7) { animation-delay: 0.28s; }
|
||||
.prodaja-tabela tbody tr:nth-child(8) { animation-delay: 0.32s; }
|
||||
.prodaja-tabela tbody tr:nth-child(9) { animation-delay: 0.36s; }
|
||||
.prodaja-tabela tbody tr:nth-child(10) { animation-delay: 0.40s; }
|
||||
|
||||
.prodaja-kartice {
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.prodaja-kartica:nth-child(1) { animation-delay: 0.04s; }
|
||||
.prodaja-kartica:nth-child(2) { animation-delay: 0.10s; }
|
||||
.prodaja-kartica:nth-child(3) { animation-delay: 0.16s; }
|
||||
.prodaja-kartica:nth-child(4) { animation-delay: 0.22s; }
|
||||
.prodaja-kartica:nth-child(5) { animation-delay: 0.28s; }
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.prodaja-tabela { display: none; }
|
||||
.prodaja-kartice { display: flex; }
|
||||
}
|
||||
.poruka-animacija { animation: slideDown 0.3s ease forwards; }
|
||||
.prodaja-tabela tbody tr:nth-child(1) { animation-delay: 0.04s; }
|
||||
.prodaja-tabela tbody tr:nth-child(2) { animation-delay: 0.08s; }
|
||||
.prodaja-tabela tbody tr:nth-child(3) { animation-delay: 0.12s; }
|
||||
.prodaja-tabela tbody tr:nth-child(4) { animation-delay: 0.16s; }
|
||||
.prodaja-tabela tbody tr:nth-child(5) { animation-delay: 0.2s; }
|
||||
.prodaja-tabela tbody tr:nth-child(6) { animation-delay: 0.24s; }
|
||||
.prodaja-tabela tbody tr:nth-child(7) { animation-delay: 0.28s; }
|
||||
.prodaja-tabela tbody tr:nth-child(8) { animation-delay: 0.32s; }
|
||||
.prodaja-tabela tbody tr:nth-child(9) { animation-delay: 0.36s; }
|
||||
.prodaja-tabela tbody tr:nth-child(10) { animation-delay: 0.4s; }
|
||||
.prodaja-kartice { display: none; flex-direction: column; gap: 12px; }
|
||||
.prodaja-kartica:nth-child(1) { animation-delay: 0.04s; }
|
||||
.prodaja-kartica:nth-child(2) { animation-delay: 0.1s; }
|
||||
.prodaja-kartica:nth-child(3) { animation-delay: 0.16s; }
|
||||
.prodaja-kartica:nth-child(4) { animation-delay: 0.22s; }
|
||||
.prodaja-kartica:nth-child(5) { animation-delay: 0.28s; }
|
||||
@media (max-width: 768px) { .prodaja-tabela { display: none; } .prodaja-kartice { display: flex; } }
|
||||
</style>
|
||||
{{end}}
|
||||
|
||||
{{define "sadrzaj"}}
|
||||
<div style="display:flex;flex-direction:column;gap:16px;">
|
||||
|
||||
{{end}} {{define "sadrzaj"}}
|
||||
<div style="display: flex; flex-direction: column; gap: 16px">
|
||||
{{if .Sacuvano}}
|
||||
<div class="poruka-uspeh poruka-animacija">Prodaja je uspešno sačuvana.</div>
|
||||
{{end}}
|
||||
{{if .Obrisan}}
|
||||
{{end}} {{if .Obrisan}}
|
||||
<div class="poruka-uspeh poruka-animacija">Prodajni nalog je uspešno obrisan.</div>
|
||||
{{end}}
|
||||
|
||||
<!-- zaglavlje sa pretragom i dugmetom -->
|
||||
<div style="display:flex;align-items:center;gap:10px;flex-wrap:wrap;">
|
||||
<form method="GET" action="/prodaja" style="display:flex;gap:8px;flex:1;min-width:200px;">
|
||||
<input type="text" name="pretraga" value="{{.Pretraga}}"
|
||||
placeholder="Pretraži po broju naloga..."
|
||||
style="flex:1;">
|
||||
<button type="submit" class="btn-sekundarno" style="white-space:nowrap;">Pretraži</button>
|
||||
<div style="display: flex; align-items: center; gap: 10px; flex-wrap: wrap">
|
||||
<form method="GET" action="/prodaja" style="display: flex; gap: 8px; flex: 1; min-width: 200px">
|
||||
<input type="text" name="pretraga" value="{{.Pretraga}}" placeholder="Pretraži po broju naloga..." style="flex: 1" />
|
||||
<button type="submit" class="btn-sekundarno" style="white-space: nowrap">Pretraži</button>
|
||||
{{if .Pretraga}}
|
||||
<a href="/prodaja" class="btn-sekundarno" style="white-space:nowrap;">✕ Resetuj</a>
|
||||
<a href="/prodaja" class="btn-sekundarno" style="white-space: nowrap">✕ Resetuj</a>
|
||||
{{end}}
|
||||
</form>
|
||||
<a href="/prodaja/nova" class="btn-primarno">+ Nova prodaja</a>
|
||||
</div>
|
||||
|
||||
<!-- desktop tabela -->
|
||||
<div class="kartica prodaja-tabela animiraj" style="padding:0;overflow:hidden;">
|
||||
<div style="overflow-x:auto;">
|
||||
<table style="width:100%;border-collapse:collapse;">
|
||||
<div class="kartica prodaja-tabela animiraj" style="padding: 0; overflow: hidden">
|
||||
<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:12px 16px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Broj naloga</th>
|
||||
<th style="padding:12px 16px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Datum</th>
|
||||
<th style="padding:12px 16px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Klijent</th>
|
||||
<th style="padding:12px 16px;text-align:right;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Ukupno</th>
|
||||
<th style="padding:12px 16px;text-align:center;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Akcije</th>
|
||||
<tr style="border-bottom: 0.5px solid var(--ivica)">
|
||||
<th style="padding: 12px 16px; text-align: left; font-size: 12px; font-weight: 500; color: var(--tekst-sporedni)">Broj naloga</th>
|
||||
<th style="padding: 12px 16px; text-align: left; font-size: 12px; font-weight: 500; color: var(--tekst-sporedni)">Datum</th>
|
||||
<th style="padding: 12px 16px; text-align: left; font-size: 12px; font-weight: 500; color: var(--tekst-sporedni)">Klijent</th>
|
||||
<th style="padding: 12px 16px; text-align: right; font-size: 12px; font-weight: 500; color: var(--tekst-sporedni)">Ukupno</th>
|
||||
<th style="padding: 12px 16px; text-align: center; font-size: 12px; font-weight: 500; color: var(--tekst-sporedni)">Akcije</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .Nalozi}}
|
||||
<tr class="animiraj red-tabele">
|
||||
<td style="padding:12px 16px;font-size:13px;font-family:monospace;color:var(--tekst-glavni);">
|
||||
{{.BrojNaloga}}
|
||||
</td>
|
||||
<td style="padding:12px 16px;font-size:13px;color:var(--tekst-sporedni);white-space:nowrap;">
|
||||
{{.Datum.Format "02.01.2006."}}
|
||||
</td>
|
||||
<td style="padding:12px 16px;font-size:14px;font-weight:500;color:var(--tekst-glavni);">
|
||||
{{if .KlijentNaziv}}{{.KlijentNaziv}}{{else}}—{{end}}
|
||||
</td>
|
||||
<td style="padding:12px 16px;text-align:right;font-size:14px;font-weight:500;color:var(--tekst-glavni);">
|
||||
{{printf "%.2f" .Ukupno}} din
|
||||
</td>
|
||||
<td style="padding:12px 16px;text-align:center;">
|
||||
<div style="display:flex;align-items:center;justify-content:center;gap:8px;">
|
||||
<td style="padding: 12px 16px; font-size: 13px; font-family: monospace; color: var(--tekst-glavni)">{{.BrojNaloga}}</td>
|
||||
<td style="padding: 12px 16px; font-size: 13px; color: var(--tekst-sporedni); white-space: nowrap">{{.Datum.Format "02.01.2006."}}</td>
|
||||
<td style="padding: 12px 16px; font-size: 14px; font-weight: 500; color: var(--tekst-glavni)">{{if .KlijentNaziv}}{{.KlijentNaziv}}{{else}}—{{end}}</td>
|
||||
<td style="padding: 12px 16px; text-align: right; font-size: 14px; font-weight: 500; color: var(--tekst-glavni)">{{printf "%.2f" .Ukupno}} din</td>
|
||||
<td style="padding: 12px 16px; text-align: center">
|
||||
<div style="display: flex; align-items: center; justify-content: center; gap: 8px">
|
||||
<a href="/prodaja/{{.ID}}" class="btn-primarno-malo">Detalji</a>
|
||||
{{if index $.Dozvole "prodaja.storno"}}
|
||||
<form method="POST" action="/prodaja/storno/{{.ID}}" style="margin:0;padding:0;">
|
||||
<input type="hidden" name="_csrf" value="{{$.CsrfToken}}">
|
||||
<button type="submit" class="btn-obrisi-malo"
|
||||
data-potvrda="Da li ste sigurni da želite da stornirate ovaj nalog? Artikli će biti vraćeni na stanje.">
|
||||
Storno
|
||||
</button>
|
||||
<form method="POST" action="/prodaja/storno/{{.ID}}" style="margin: 0; padding: 0">
|
||||
<input type="hidden" name="_csrf" value="{{$.CsrfToken}}" />
|
||||
<button type="submit" class="btn-obrisi-malo" data-potvrda="Da li ste sigurni da želite da stornirate ovaj nalog? Artikli će biti vraćeni na stanje.">Storno</button>
|
||||
</form>
|
||||
{{end}}
|
||||
</div>
|
||||
@@ -105,11 +73,9 @@
|
||||
</tr>
|
||||
{{else}}
|
||||
<tr>
|
||||
<td colspan="5" style="padding:32px;text-align:center;font-size:14px;color:var(--tekst-sporedni);">
|
||||
{{if $.Pretraga}}
|
||||
Nema naloga koji odgovaraju pretrazi.
|
||||
{{else}}
|
||||
Nema prodajnih naloga. <a href="/prodaja/nova" style="color:var(--sb-akcent);">Dodaj prvu prodaju.</a>
|
||||
<td colspan="5" style="padding: 32px; text-align: center; font-size: 14px; color: var(--tekst-sporedni)">
|
||||
{{if $.Pretraga}} Nema naloga koji odgovaraju pretrazi. {{else}} Nema prodajnih naloga.
|
||||
<a href="/prodaja/nova" style="color: var(--sb-akcent)">Dodaj prvu prodaju.</a>
|
||||
{{end}}
|
||||
</td>
|
||||
</tr>
|
||||
@@ -123,34 +89,23 @@
|
||||
<div class="prodaja-kartice">
|
||||
{{range .Nalozi}}
|
||||
<div class="kartica prodaja-kartica animiraj">
|
||||
<div style="display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:10px;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; margin-bottom: 10px">
|
||||
<div>
|
||||
<div style="font-size:13px;font-family:monospace;color:var(--tekst-glavni);">{{.BrojNaloga}}</div>
|
||||
<div style="font-size:14px;font-weight:500;color:var(--tekst-glavni);margin-top:2px;">
|
||||
{{if .KlijentNaziv}}{{.KlijentNaziv}}{{else}}Bez klijenta{{end}}
|
||||
</div>
|
||||
<div style="font-size:12px;color:var(--tekst-sporedni);margin-top:2px;">
|
||||
{{.Datum.Format "02.01.2006."}}
|
||||
</div>
|
||||
</div>
|
||||
<div style="font-size:15px;font-weight:500;color:var(--tekst-glavni);white-space:nowrap;">
|
||||
{{printf "%.2f" .Ukupno}} din
|
||||
<div style="font-size: 13px; font-family: monospace; color: var(--tekst-glavni)">{{.BrojNaloga}}</div>
|
||||
<div style="font-size: 14px; font-weight: 500; color: var(--tekst-glavni); margin-top: 2px">{{if .KlijentNaziv}}{{.KlijentNaziv}}{{else}}Bez klijenta{{end}}</div>
|
||||
<div style="font-size: 12px; color: var(--tekst-sporedni); margin-top: 2px">{{.Datum.Format "02.01.2006."}}</div>
|
||||
</div>
|
||||
<div style="font-size: 15px; font-weight: 500; color: var(--tekst-glavni); white-space: nowrap">{{printf "%.2f" .Ukupno}} din</div>
|
||||
</div>
|
||||
<a href="/prodaja/{{.ID}}" class="btn-primarno-malo" style="justify-content:center;width:100%;box-sizing:border-box;">
|
||||
Detalji
|
||||
</a>
|
||||
<a href="/prodaja/{{.ID}}" class="btn-primarno-malo" style="justify-content: center; width: 100%; box-sizing: border-box">Detalji</a>
|
||||
</div>
|
||||
{{else}}
|
||||
<div style="padding:32px;text-align:center;font-size:14px;color:var(--tekst-sporedni);">
|
||||
{{if $.Pretraga}}
|
||||
Nema naloga koji odgovaraju pretrazi.
|
||||
{{else}}
|
||||
Nema prodajnih naloga. <a href="/prodaja/nova" style="color:var(--sb-akcent);">Dodaj prvu prodaju.</a>
|
||||
<div style="padding: 32px; text-align: center; font-size: 14px; color: var(--tekst-sporedni)">
|
||||
{{if $.Pretraga}} Nema naloga koji odgovaraju pretrazi. {{else}} Nema prodajnih naloga.
|
||||
<a href="/prodaja/nova" style="color: var(--sb-akcent)">Dodaj prvu prodaju.</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
@@ -1,119 +1,304 @@
|
||||
{{template "base" .}}
|
||||
|
||||
{{define "naslov"}}Detalji prodaje — NTech{{end}}
|
||||
|
||||
{{define "dodatni-css"}}
|
||||
{{template "base" .}} {{define "naslov"}}Detalji prodaje — NTech{{end}} {{define
|
||||
"dodatni-css"}}
|
||||
<style>
|
||||
.detalji-kartica:nth-child(1) { animation-delay: 0.04s; }
|
||||
.detalji-kartica:nth-child(2) { animation-delay: 0.12s; }
|
||||
.detalji-kartica:nth-child(3) { animation-delay: 0.20s; }
|
||||
|
||||
.poruka-animacija { animation: slideDown 0.3s ease forwards; }
|
||||
.detalji-kartica:nth-child(1) { animation-delay: 0.04s; }
|
||||
.detalji-kartica:nth-child(2) { animation-delay: 0.12s; }
|
||||
.detalji-kartica:nth-child(3) { animation-delay: 0.2s; }
|
||||
.poruka-animacija { animation: slideDown 0.3s ease forwards; }
|
||||
</style>
|
||||
{{end}}
|
||||
{{end}} {{define "sadrzaj"}}
|
||||
<div style="display: flex; flex-direction: column; gap: 16px">
|
||||
{{if .Sacuvano}}
|
||||
<div class="poruka-uspeh poruka-animacija">Prodaja je uspešno sačuvana.</div>
|
||||
{{end}}
|
||||
|
||||
{{define "sadrzaj"}}
|
||||
<div style="display:flex;flex-direction:column;gap:16px;">
|
||||
<!-- nazad dugme -->
|
||||
<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>
|
||||
|
||||
{{if .Sacuvano}}
|
||||
<div class="poruka-uspeh poruka-animacija">Prodaja je uspešno sačuvana.</div>
|
||||
{{end}}
|
||||
|
||||
<!-- nazad dugme -->
|
||||
<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>
|
||||
|
||||
<!-- zaglavlje naloga -->
|
||||
<div class="kartica detalji-kartica animiraj">
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:10px;margin-bottom:16px;padding-bottom:14px;border-bottom:0.5px solid var(--ivica);">
|
||||
<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" 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>
|
||||
<div style="display:grid;grid-template-columns:repeat(auto-fit, minmax(140px, 1fr));gap:16px;">
|
||||
<div>
|
||||
<div style="font-size:12px;color:var(--tekst-sporedni);margin-bottom:4px;">Datum prodaje</div>
|
||||
<div style="font-size:14px;color:var(--tekst-glavni);">{{.Nalog.Datum.Format "02.01.2006. u 15:04"}}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-size:12px;color:var(--tekst-sporedni);margin-bottom:4px;">Klijent</div>
|
||||
<div style="font-size:14px;font-weight:500;color:var(--tekst-glavni);">
|
||||
{{if .KlijentNaziv}}{{.KlijentNaziv}}{{else}}—{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-size:12px;color:var(--tekst-sporedni);margin-bottom:4px;">Ukupno</div>
|
||||
<div style="font-size:20px;font-weight:600;color:var(--sb-akcent);">{{printf "%.2f" .Nalog.Ukupno}} din</div>
|
||||
</div>
|
||||
{{if .Nalog.Napomena}}
|
||||
<div style="grid-column:1/-1;">
|
||||
<div style="font-size:12px;color:var(--tekst-sporedni);margin-bottom:4px;">Napomena</div>
|
||||
<div style="font-size:13px;color:var(--tekst-sporedni);">{{.Nalog.Napomena}}</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<!-- zaglavlje naloga -->
|
||||
<div class="kartica detalji-kartica animiraj">
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 14px;
|
||||
border-bottom: 0.5px solid var(--ivica);
|
||||
">
|
||||
<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"
|
||||
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>
|
||||
|
||||
<!-- stavke -->
|
||||
<div class="kartica detalji-kartica animiraj" style="padding:0;overflow:hidden;">
|
||||
<div style="padding:16px 20px;border-bottom:0.5px solid var(--ivica);">
|
||||
<span style="font-size:15px;font-weight:500;color:var(--tekst-glavni);">Stavke</span>
|
||||
<div
|
||||
style="
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
||||
gap: 16px;
|
||||
">
|
||||
<div>
|
||||
<div
|
||||
style="
|
||||
font-size: 12px;
|
||||
color: var(--tekst-sporedni);
|
||||
margin-bottom: 4px;
|
||||
">
|
||||
Datum prodaje
|
||||
</div>
|
||||
<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 20px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Artikal</th>
|
||||
<th style="padding:10px 20px;text-align:center;font-size:12px;font-weight:500;color:var(--tekst-sporedni);width:90px;">Količina</th>
|
||||
<th style="padding:10px 20px;text-align:right;font-size:12px;font-weight:500;color:var(--tekst-sporedni);width:140px;">Cena/kom</th>
|
||||
<th style="padding:10px 20px;text-align:right;font-size:12px;font-weight:500;color:var(--tekst-sporedni);width:120px;">Ukupno</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .Stavke}}
|
||||
<tr style="border-bottom:0.5px solid var(--ivica);">
|
||||
<td style="padding:10px 20px;font-size:14px;color:var(--tekst-glavni);">{{.ArtikalNaziv}}</td>
|
||||
<td style="padding:10px 20px;text-align:center;font-size:14px;color:var(--tekst-glavni);">{{.Kolicina}}</td>
|
||||
<td style="padding:10px 20px;text-align:right;font-size:14px;color:var(--tekst-sporedni);">{{printf "%.2f" .CenaPoKomadu}} din</td>
|
||||
<td style="padding:10px 20px;text-align:right;font-size:14px;font-weight:500;color:var(--tekst-glavni);">{{printf "%.2f" .Ukupno}} din</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr style="border-top:0.5px solid var(--ivica);">
|
||||
<td colspan="3" style="padding:12px 20px;text-align:right;font-size:13px;font-weight:500;color:var(--tekst-sporedni);">Ukupno:</td>
|
||||
<td style="padding:12px 20px;text-align:right;font-size:16px;font-weight:600;color:var(--sb-akcent);">{{printf "%.2f" .Nalog.Ukupno}} din</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<div style="font-size: 14px; color: var(--tekst-glavni)">
|
||||
{{.Nalog.Datum.Format "02.01.2006. u 15:04"}}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
style="
|
||||
font-size: 12px;
|
||||
color: var(--tekst-sporedni);
|
||||
margin-bottom: 4px;
|
||||
">
|
||||
Klijent
|
||||
</div>
|
||||
<div
|
||||
style="font-size: 14px; font-weight: 500; color: var(--tekst-glavni)">
|
||||
{{if .KlijentNaziv}}{{.KlijentNaziv}}{{else}}—{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
style="
|
||||
font-size: 12px;
|
||||
color: var(--tekst-sporedni);
|
||||
margin-bottom: 4px;
|
||||
">
|
||||
Ukupno
|
||||
</div>
|
||||
<div style="font-size: 20px; font-weight: 600; color: var(--sb-akcent)">
|
||||
{{printf "%.2f" .Nalog.Ukupno}} din
|
||||
</div>
|
||||
</div>
|
||||
{{if .Nalog.Napomena}}
|
||||
<div style="grid-column: 1/-1">
|
||||
<div
|
||||
style="
|
||||
font-size: 12px;
|
||||
color: var(--tekst-sporedni);
|
||||
margin-bottom: 4px;
|
||||
">
|
||||
Napomena
|
||||
</div>
|
||||
<div style="font-size: 13px; color: var(--tekst-sporedni)">
|
||||
{{.Nalog.Napomena}}
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</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;">
|
||||
<div style="flex:1;min-width:200px;">
|
||||
<div style="font-size:14px;font-weight:500;color:#dc2626;margin-bottom:4px;">Brisanje naloga</div>
|
||||
<div style="font-size:13px;color:var(--tekst-sporedni);">
|
||||
Brisanje je trajno. Količine artikala biće vraćene na stanje u magacinu.
|
||||
</div>
|
||||
</div>
|
||||
<form method="POST" action="/prodaja/obrisi/{{.Nalog.ID}}">
|
||||
<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>
|
||||
<!-- stavke -->
|
||||
<div
|
||||
class="kartica detalji-kartica animiraj"
|
||||
style="padding: 0; overflow: hidden">
|
||||
<div style="padding: 16px 20px; border-bottom: 0.5px solid var(--ivica)">
|
||||
<span
|
||||
style="font-size: 15px; font-weight: 500; color: var(--tekst-glavni)">Stavke</span>
|
||||
</div>
|
||||
{{end}}
|
||||
<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 20px;
|
||||
text-align: left;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--tekst-sporedni);
|
||||
">
|
||||
Artikal
|
||||
</th>
|
||||
<th
|
||||
style="
|
||||
padding: 10px 20px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--tekst-sporedni);
|
||||
width: 90px;
|
||||
">
|
||||
Količina
|
||||
</th>
|
||||
<th
|
||||
style="
|
||||
padding: 10px 20px;
|
||||
text-align: right;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--tekst-sporedni);
|
||||
width: 140px;
|
||||
">
|
||||
Cena/kom
|
||||
</th>
|
||||
<th
|
||||
style="
|
||||
padding: 10px 20px;
|
||||
text-align: right;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--tekst-sporedni);
|
||||
width: 120px;
|
||||
">
|
||||
Ukupno
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .Stavke}}
|
||||
<tr style="border-bottom: 0.5px solid var(--ivica)">
|
||||
<td
|
||||
style="
|
||||
padding: 10px 20px;
|
||||
font-size: 14px;
|
||||
color: var(--tekst-glavni);
|
||||
">
|
||||
{{.ArtikalNaziv}}
|
||||
</td>
|
||||
<td
|
||||
style="
|
||||
padding: 10px 20px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: var(--tekst-glavni);
|
||||
">
|
||||
{{.Kolicina}}
|
||||
</td>
|
||||
<td
|
||||
style="
|
||||
padding: 10px 20px;
|
||||
text-align: right;
|
||||
font-size: 14px;
|
||||
color: var(--tekst-sporedni);
|
||||
">
|
||||
{{printf "%.2f" .CenaPoKomadu}} din
|
||||
</td>
|
||||
<td
|
||||
style="
|
||||
padding: 10px 20px;
|
||||
text-align: right;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--tekst-glavni);
|
||||
">
|
||||
{{printf "%.2f" .Ukupno}} din
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr style="border-top: 0.5px solid var(--ivica)">
|
||||
<td
|
||||
colspan="3"
|
||||
style="
|
||||
padding: 12px 20px;
|
||||
text-align: right;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--tekst-sporedni);
|
||||
">
|
||||
Ukupno:
|
||||
</td>
|
||||
<td
|
||||
style="
|
||||
padding: 12px 20px;
|
||||
text-align: right;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--sb-akcent);
|
||||
">
|
||||
{{printf "%.2f" .Nalog.Ukupno}} din
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</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">
|
||||
<div style="flex: 1; min-width: 200px">
|
||||
<div
|
||||
style="
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #dc2626;
|
||||
margin-bottom: 4px;
|
||||
">
|
||||
Brisanje naloga
|
||||
</div>
|
||||
<div style="font-size: 13px; color: var(--tekst-sporedni)">
|
||||
Brisanje je trajno. Količine artikala biće vraćene na stanje u
|
||||
magacinu.
|
||||
</div>
|
||||
</div>
|
||||
<form method="POST" action="/prodaja/obrisi/{{.Nalog.ID}}">
|
||||
<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}}
|
||||
{{end}}
|
||||
@@ -1,28 +1,21 @@
|
||||
{{template "base" .}}
|
||||
|
||||
{{define "naslov"}}Nova prodaja — NTech{{end}}
|
||||
|
||||
{{define "dodatni-css"}}
|
||||
{{template "base" .}} {{define "naslov"}}Nova prodaja — NTech{{end}} {{define
|
||||
"dodatni-css"}}
|
||||
<style>
|
||||
.forma-kartica:nth-child(1) { animation-delay: 0.04s; }
|
||||
.forma-kartica:nth-child(2) { animation-delay: 0.12s; }
|
||||
|
||||
.greska-animacija { animation: shake 0.4s ease; }
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.stavke-tabela-wrapper { display: none; }
|
||||
.stavke-kartice { display: flex !important; }
|
||||
}
|
||||
.forma-kartica:nth-child(1) { animation-delay: 0.04s; }
|
||||
.forma-kartica:nth-child(2) { animation-delay: 0.12s; }
|
||||
.greska-animacija { animation: shake 0.4s ease; }
|
||||
@media (max-width: 768px) { .stavke-tabela-wrapper { display: none; } .stavke-kartice { display: flex !important; } }
|
||||
</style>
|
||||
{{end}}
|
||||
|
||||
{{define "sadrzaj"}}
|
||||
{{end}} {{define "sadrzaj"}}
|
||||
|
||||
<!-- lista artikala kao JSON — sadrži id, naziv i prodajnu cenu -->
|
||||
<script>var _ntechArtikli = {{.ArtikliJSON}};</script>
|
||||
<script>
|
||||
var _ntechArtikli = {{.ArtikliJSON }};
|
||||
</script>
|
||||
|
||||
<div style="width:100%;"
|
||||
x-data="{
|
||||
<div
|
||||
style="width: 100%"
|
||||
x-data="{
|
||||
stavke: [{artikal_id: '', kolicina: 1, cena: 0}],
|
||||
artikliOpcije: _ntechArtikli,
|
||||
isMobile: window.matchMedia('(max-width: 768px)').matches,
|
||||
@@ -66,190 +59,417 @@
|
||||
return this.stavke.reduce((z, s) => z + (parseFloat(s.kolicina) * parseFloat(s.cena) || 0), 0).toFixed(2);
|
||||
}
|
||||
}">
|
||||
<!-- nazad dugme -->
|
||||
<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>
|
||||
|
||||
<!-- nazad dugme -->
|
||||
<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="poruka-greska greska-animacija">{{.Greska}}</div>
|
||||
{{end}}
|
||||
|
||||
<form method="POST" action="/prodaja/nova">
|
||||
<!-- zaglavlje prodaje -->
|
||||
<div class="kartica forma-kartica animiraj" style="margin-bottom: 16px">
|
||||
<div
|
||||
style="
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 14px;
|
||||
border-bottom: 0.5px solid var(--ivica);
|
||||
">
|
||||
<span
|
||||
style="font-size: 16px; font-weight: 500; color: var(--tekst-glavni)">Nova prodaja</span>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 14px">
|
||||
<div>
|
||||
<label
|
||||
style="
|
||||
font-size: 13px;
|
||||
color: var(--tekst-sporedni);
|
||||
display: block;
|
||||
margin-bottom: 6px;
|
||||
">Klijent</label>
|
||||
<select name="klijent_id" style="width: 100%">
|
||||
<option value="">— bez klijenta —</option>
|
||||
{{range .Klijenti}}
|
||||
<option value="{{.ID}}">
|
||||
{{if .NazivFirme}}{{.NazivFirme}}{{else}}{{.Ime}}
|
||||
{{.Prezime}}{{end}}
|
||||
</option>
|
||||
{{end}}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label
|
||||
style="
|
||||
font-size: 13px;
|
||||
color: var(--tekst-sporedni);
|
||||
display: block;
|
||||
margin-bottom: 6px;
|
||||
">Napomena</label>
|
||||
<textarea
|
||||
name="napomena"
|
||||
rows="2"
|
||||
placeholder="Interna napomena o prodaji..."
|
||||
style="width: 100%; resize: vertical"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{if .Greska}}
|
||||
<div class="poruka-greska greska-animacija">{{.Greska}}</div>
|
||||
{{end}}
|
||||
<!-- stavke -->
|
||||
<div class="kartica forma-kartica animiraj" style="margin-bottom: 16px">
|
||||
<div
|
||||
style="
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 14px;
|
||||
border-bottom: 0.5px solid var(--ivica);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
">
|
||||
<span
|
||||
style="font-size: 16px; font-weight: 500; color: var(--tekst-glavni)">Stavke</span>
|
||||
<button
|
||||
type="button"
|
||||
@click="dodajStavku()"
|
||||
class="btn-primarno"
|
||||
style="font-size: 13px; padding: 6px 14px">
|
||||
+ Dodaj stavku
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- zaglavlje prodaje -->
|
||||
<div class="kartica forma-kartica animiraj" style="margin-bottom:16px;">
|
||||
<div style="margin-bottom:16px;padding-bottom:14px;border-bottom:0.5px solid var(--ivica);">
|
||||
<span style="font-size:16px;font-weight:500;color:var(--tekst-glavni);">Nova prodaja</span>
|
||||
<!-- desktop tabela stavki -->
|
||||
<div class="stavke-tabela-wrapper" style="overflow-x: auto">
|
||||
<table style="width: 100%; border-collapse: collapse">
|
||||
<thead>
|
||||
<tr style="border-bottom: 0.5px solid var(--ivica)">
|
||||
<th
|
||||
style="
|
||||
padding: 8px 10px;
|
||||
text-align: left;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--tekst-sporedni);
|
||||
">
|
||||
Artikal
|
||||
</th>
|
||||
<th
|
||||
style="
|
||||
padding: 8px 10px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--tekst-sporedni);
|
||||
width: 90px;
|
||||
">
|
||||
Količina
|
||||
</th>
|
||||
<th
|
||||
style="
|
||||
padding: 8px 10px;
|
||||
text-align: right;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--tekst-sporedni);
|
||||
width: 140px;
|
||||
">
|
||||
Cena/kom (din)
|
||||
</th>
|
||||
<th
|
||||
style="
|
||||
padding: 8px 10px;
|
||||
text-align: right;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--tekst-sporedni);
|
||||
width: 110px;
|
||||
">
|
||||
Ukupno
|
||||
</th>
|
||||
<th style="width: 40px"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<template x-for="(stavka, i) in stavke" :key="i">
|
||||
<tr style="border-bottom: 0.5px solid var(--ivica)">
|
||||
<td style="padding: 8px 10px">
|
||||
<select
|
||||
:name="'artikal_id[]'"
|
||||
x-model="stavka.artikal_id"
|
||||
@change="popuniCenu(stavka)"
|
||||
:disabled="isMobile"
|
||||
style="width: 100%">
|
||||
<option value="">— odaberi artikal —</option>
|
||||
<template x-for="a in artikliOpcije" :key="a.id">
|
||||
<option :value="a.id" x-text="a.naziv"></option>
|
||||
</template>
|
||||
</select>
|
||||
</td>
|
||||
<td style="padding: 8px 10px">
|
||||
<input
|
||||
type="number"
|
||||
:name="'kolicina[]'"
|
||||
x-model="stavka.kolicina"
|
||||
min="1"
|
||||
:disabled="isMobile"
|
||||
:style="prekoracenje(i) ? 'border-color:#dc2626;' : ''"
|
||||
style="width: 100%; text-align: center" />
|
||||
<div
|
||||
x-show="stavka.artikal_id"
|
||||
:style="prekoracenje(i) ? 'color:#dc2626' : 'color:var(--tekst-sporedni)'"
|
||||
x-text="'Na stanju: ' + dostupnaKolicina(i)"
|
||||
style="
|
||||
font-size: 11px;
|
||||
margin-top: 3px;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
"></div>
|
||||
<div
|
||||
x-show="prekoracenje(i)"
|
||||
style="
|
||||
font-size: 11px;
|
||||
color: #dc2626;
|
||||
margin-top: 1px;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
">
|
||||
Prekoračena količina
|
||||
</div>
|
||||
</td>
|
||||
<td style="padding: 8px 10px">
|
||||
<input
|
||||
type="number"
|
||||
:name="'cena_po_komadu[]'"
|
||||
x-model="stavka.cena"
|
||||
min="0"
|
||||
step="0.01"
|
||||
:disabled="isMobile"
|
||||
style="width: 100%; text-align: right" />
|
||||
</td>
|
||||
<td
|
||||
style="
|
||||
padding: 8px 10px;
|
||||
text-align: right;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--tekst-glavni);
|
||||
">
|
||||
<span x-text="ukupnoStavke(stavka) + ' din'"></span>
|
||||
</td>
|
||||
<td style="padding: 8px 10px; text-align: center">
|
||||
<button
|
||||
type="button"
|
||||
@click="ukloniStavku(i)"
|
||||
x-show="stavke.length > 1"
|
||||
style="
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: #dc2626;
|
||||
font-size: 18px;
|
||||
line-height: 1;
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
transition: background 0.15s;
|
||||
"
|
||||
onmouseover="this.style.background = 'rgba(220,38,38,0.08)'"
|
||||
onmouseout="this.style.background = 'none'"
|
||||
title="Ukloni stavku">
|
||||
×
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr style="border-top: 0.5px solid var(--ivica)">
|
||||
<td
|
||||
colspan="3"
|
||||
style="
|
||||
padding: 10px;
|
||||
text-align: right;
|
||||
font-size: 13px;
|
||||
color: var(--tekst-sporedni);
|
||||
font-weight: 500;
|
||||
">
|
||||
Ukupno:
|
||||
</td>
|
||||
<td
|
||||
style="
|
||||
padding: 10px;
|
||||
text-align: right;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: var(--tekst-glavni);
|
||||
">
|
||||
<span x-text="ukupnoSvega() + ' din'"></span>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- mobilne kartice stavki -->
|
||||
<div
|
||||
class="stavke-kartice"
|
||||
style="display: none; flex-direction: column; gap: 10px">
|
||||
<template x-for="(stavka, i) in stavke" :key="i">
|
||||
<div
|
||||
style="
|
||||
border: 0.5px solid var(--ivica);
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
">
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
">
|
||||
<span
|
||||
style="
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--tekst-sporedni);
|
||||
"
|
||||
x-text="'Stavka ' + (i + 1)"></span>
|
||||
<button
|
||||
type="button"
|
||||
@click="ukloniStavku(i)"
|
||||
x-show="stavke.length > 1"
|
||||
style="
|
||||
background: none;
|
||||
border: 0.5px solid #dc2626;
|
||||
color: #dc2626;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
padding: 2px 8px;
|
||||
border-radius: 4px;
|
||||
">
|
||||
Ukloni
|
||||
</button>
|
||||
</div>
|
||||
<div style="display:flex;flex-direction:column;gap:14px;">
|
||||
<div style="display: flex; flex-direction: column; gap: 10px">
|
||||
<div>
|
||||
<label
|
||||
style="
|
||||
font-size: 12px;
|
||||
color: var(--tekst-sporedni);
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
">Artikal</label>
|
||||
<select
|
||||
:name="'artikal_id[]'"
|
||||
x-model="stavka.artikal_id"
|
||||
@change="popuniCenu(stavka)"
|
||||
:disabled="!isMobile"
|
||||
style="width: 100%">
|
||||
<option value="">— odaberi artikal —</option>
|
||||
<template x-for="a in artikliOpcije" :key="a.id">
|
||||
<option :value="a.id" x-text="a.naziv"></option>
|
||||
</template>
|
||||
</select>
|
||||
</div>
|
||||
<div
|
||||
style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px">
|
||||
<div>
|
||||
<label style="font-size:13px;color:var(--tekst-sporedni);display:block;margin-bottom:6px;">Klijent</label>
|
||||
<select name="klijent_id" style="width:100%;">
|
||||
<option value="">— bez klijenta —</option>
|
||||
{{range .Klijenti}}
|
||||
<option value="{{.ID}}">
|
||||
{{if .NazivFirme}}{{.NazivFirme}}{{else}}{{.Ime}} {{.Prezime}}{{end}}
|
||||
</option>
|
||||
{{end}}
|
||||
</select>
|
||||
<label
|
||||
style="
|
||||
font-size: 12px;
|
||||
color: var(--tekst-sporedni);
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
">Količina</label>
|
||||
<input
|
||||
type="number"
|
||||
:name="'kolicina[]'"
|
||||
x-model="stavka.kolicina"
|
||||
min="1"
|
||||
:disabled="!isMobile"
|
||||
:style="prekoracenje(i) ? 'border-color:#dc2626;' : ''"
|
||||
style="width: 100%" />
|
||||
<div
|
||||
x-show="stavka.artikal_id"
|
||||
:style="prekoracenje(i) ? 'color:#dc2626' : 'color:var(--tekst-sporedni)'"
|
||||
x-text="'Na stanju: ' + dostupnaKolicina(i)"
|
||||
style="font-size: 11px; margin-top: 3px"></div>
|
||||
<div
|
||||
x-show="prekoracenje(i)"
|
||||
style="font-size: 11px; color: #dc2626; margin-top: 1px">
|
||||
Prekoračena količina
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label style="font-size:13px;color:var(--tekst-sporedni);display:block;margin-bottom:6px;">Napomena</label>
|
||||
<textarea name="napomena" rows="2"
|
||||
placeholder="Interna napomena o prodaji..."
|
||||
style="width:100%;resize:vertical;"></textarea>
|
||||
<label
|
||||
style="
|
||||
font-size: 12px;
|
||||
color: var(--tekst-sporedni);
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
">Cena/kom (din)</label>
|
||||
<input
|
||||
type="number"
|
||||
:name="'cena_po_komadu[]'"
|
||||
x-model="stavka.cena"
|
||||
min="0"
|
||||
step="0.01"
|
||||
:disabled="!isMobile"
|
||||
style="width: 100%" />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style="
|
||||
text-align: right;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--tekst-glavni);
|
||||
">
|
||||
Ukupno: <span x-text="ukupnoStavke(stavka) + ' din'"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
style="
|
||||
text-align: right;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: var(--tekst-glavni);
|
||||
padding: 8px 4px;
|
||||
">
|
||||
Ukupno: <span x-text="ukupnoSvega() + ' din'"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- stavke -->
|
||||
<div class="kartica forma-kartica animiraj" style="margin-bottom:16px;">
|
||||
<div style="margin-bottom:16px;padding-bottom:14px;border-bottom:0.5px solid var(--ivica);display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px;">
|
||||
<span style="font-size:16px;font-weight:500;color:var(--tekst-glavni);">Stavke</span>
|
||||
<button type="button" @click="dodajStavku()" class="btn-primarno" style="font-size:13px;padding:6px 14px;">
|
||||
+ Dodaj stavku
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- desktop tabela stavki -->
|
||||
<div class="stavke-tabela-wrapper" style="overflow-x:auto;">
|
||||
<table style="width:100%;border-collapse:collapse;">
|
||||
<thead>
|
||||
<tr style="border-bottom:0.5px solid var(--ivica);">
|
||||
<th style="padding:8px 10px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Artikal</th>
|
||||
<th style="padding:8px 10px;text-align:center;font-size:12px;font-weight:500;color:var(--tekst-sporedni);width:90px;">Količina</th>
|
||||
<th style="padding:8px 10px;text-align:right;font-size:12px;font-weight:500;color:var(--tekst-sporedni);width:140px;">Cena/kom (din)</th>
|
||||
<th style="padding:8px 10px;text-align:right;font-size:12px;font-weight:500;color:var(--tekst-sporedni);width:110px;">Ukupno</th>
|
||||
<th style="width:40px;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<template x-for="(stavka, i) in stavke" :key="i">
|
||||
<tr style="border-bottom:0.5px solid var(--ivica);">
|
||||
<td style="padding:8px 10px;">
|
||||
<select :name="'artikal_id[]'" x-model="stavka.artikal_id"
|
||||
@change="popuniCenu(stavka)"
|
||||
:disabled="isMobile"
|
||||
style="width:100%;">
|
||||
<option value="">— odaberi artikal —</option>
|
||||
<template x-for="a in artikliOpcije" :key="a.id">
|
||||
<option :value="a.id" x-text="a.naziv"></option>
|
||||
</template>
|
||||
</select>
|
||||
</td>
|
||||
<td style="padding:8px 10px;">
|
||||
<input type="number" :name="'kolicina[]'" x-model="stavka.kolicina"
|
||||
min="1" :disabled="isMobile"
|
||||
:style="prekoracenje(i) ? 'border-color:#dc2626;' : ''"
|
||||
style="width:100%;text-align:center;">
|
||||
<div x-show="stavka.artikal_id"
|
||||
:style="prekoracenje(i) ? 'color:#dc2626' : 'color:var(--tekst-sporedni)'"
|
||||
x-text="'Na stanju: ' + dostupnaKolicina(i)"
|
||||
style="font-size:11px;margin-top:3px;text-align:center;white-space:nowrap;"></div>
|
||||
<div x-show="prekoracenje(i)"
|
||||
style="font-size:11px;color:#dc2626;margin-top:1px;text-align:center;white-space:nowrap;">
|
||||
Prekoračena količina
|
||||
</div>
|
||||
</td>
|
||||
<td style="padding:8px 10px;">
|
||||
<input type="number" :name="'cena_po_komadu[]'" x-model="stavka.cena"
|
||||
min="0" step="0.01" :disabled="isMobile" style="width:100%;text-align:right;">
|
||||
</td>
|
||||
<td style="padding:8px 10px;text-align:right;font-size:14px;font-weight:500;color:var(--tekst-glavni);">
|
||||
<span x-text="ukupnoStavke(stavka) + ' din'"></span>
|
||||
</td>
|
||||
<td style="padding:8px 10px;text-align:center;">
|
||||
<button type="button" @click="ukloniStavku(i)"
|
||||
x-show="stavke.length > 1"
|
||||
style="background:none;border:none;cursor:pointer;color:#dc2626;font-size:18px;line-height:1;padding:2px 6px;border-radius:4px;transition:background 0.15s;"
|
||||
onmouseover="this.style.background='rgba(220,38,38,0.08)'"
|
||||
onmouseout="this.style.background='none'"
|
||||
title="Ukloni stavku">×</button>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr style="border-top:0.5px solid var(--ivica);">
|
||||
<td colspan="3" style="padding:10px;text-align:right;font-size:13px;color:var(--tekst-sporedni);font-weight:500;">Ukupno:</td>
|
||||
<td style="padding:10px;text-align:right;font-size:15px;font-weight:600;color:var(--tekst-glavni);">
|
||||
<span x-text="ukupnoSvega() + ' din'"></span>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- mobilne kartice stavki -->
|
||||
<div class="stavke-kartice" style="display:none;flex-direction:column;gap:10px;">
|
||||
<template x-for="(stavka, i) in stavke" :key="i">
|
||||
<div style="border:0.5px solid var(--ivica);border-radius:8px;padding:12px;">
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;">
|
||||
<span style="font-size:13px;font-weight:500;color:var(--tekst-sporedni);"
|
||||
x-text="'Stavka ' + (i + 1)"></span>
|
||||
<button type="button" @click="ukloniStavku(i)"
|
||||
x-show="stavke.length > 1"
|
||||
style="background:none;border:0.5px solid #dc2626;color:#dc2626;cursor:pointer;font-size:13px;padding:2px 8px;border-radius:4px;">
|
||||
Ukloni
|
||||
</button>
|
||||
</div>
|
||||
<div style="display:flex;flex-direction:column;gap:10px;">
|
||||
<div>
|
||||
<label style="font-size:12px;color:var(--tekst-sporedni);display:block;margin-bottom:4px;">Artikal</label>
|
||||
<select :name="'artikal_id[]'" x-model="stavka.artikal_id"
|
||||
@change="popuniCenu(stavka)"
|
||||
:disabled="!isMobile"
|
||||
style="width:100%;">
|
||||
<option value="">— odaberi artikal —</option>
|
||||
<template x-for="a in artikliOpcije" :key="a.id">
|
||||
<option :value="a.id" x-text="a.naziv"></option>
|
||||
</template>
|
||||
</select>
|
||||
</div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;">
|
||||
<div>
|
||||
<label style="font-size:12px;color:var(--tekst-sporedni);display:block;margin-bottom:4px;">Količina</label>
|
||||
<input type="number" :name="'kolicina[]'" x-model="stavka.kolicina" min="1" :disabled="!isMobile"
|
||||
:style="prekoracenje(i) ? 'border-color:#dc2626;' : ''"
|
||||
style="width:100%;">
|
||||
<div x-show="stavka.artikal_id"
|
||||
:style="prekoracenje(i) ? 'color:#dc2626' : 'color:var(--tekst-sporedni)'"
|
||||
x-text="'Na stanju: ' + dostupnaKolicina(i)"
|
||||
style="font-size:11px;margin-top:3px;"></div>
|
||||
<div x-show="prekoracenje(i)" style="font-size:11px;color:#dc2626;margin-top:1px;">Prekoračena količina</div>
|
||||
</div>
|
||||
<div>
|
||||
<label style="font-size:12px;color:var(--tekst-sporedni);display:block;margin-bottom:4px;">Cena/kom (din)</label>
|
||||
<input type="number" :name="'cena_po_komadu[]'" x-model="stavka.cena" min="0" step="0.01" :disabled="!isMobile" style="width:100%;">
|
||||
</div>
|
||||
</div>
|
||||
<div style="text-align:right;font-size:14px;font-weight:500;color:var(--tekst-glavni);">
|
||||
Ukupno: <span x-text="ukupnoStavke(stavka) + ' din'"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div style="text-align:right;font-size:15px;font-weight:600;color:var(--tekst-glavni);padding:8px 4px;">
|
||||
Ukupno: <span x-text="ukupnoSvega() + ' din'"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- dugmad forme -->
|
||||
<div style="display:flex;justify-content:flex-end;gap:10px;">
|
||||
<a href="/prodaja" class="btn-sekundarno">Odustani</a>
|
||||
<button type="submit" class="btn-primarno"
|
||||
:disabled="imaPrekoracenja()"
|
||||
:style="imaPrekoracenja() ? 'opacity:0.4;cursor:not-allowed;' : ''">
|
||||
Sačuvaj prodaju
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
<!-- dugmad forme -->
|
||||
<div style="display: flex; justify-content: flex-end; gap: 10px">
|
||||
<a href="/prodaja" class="btn-sekundarno">Odustani</a>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn-primarno"
|
||||
:disabled="imaPrekoracenja()"
|
||||
:style="imaPrekoracenja() ? 'opacity:0.4;cursor:not-allowed;' : ''">
|
||||
Sačuvaj prodaju
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
@@ -1,255 +1,136 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="sr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Priznanica {{.Nalog.BrojNaloga}}</title>
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; font-size: 14px; color: #111; background: #f5f5f5; padding: 32px 16px; }
|
||||
.stranica { background: #fff; max-width: 640px; margin: 0 auto; padding: 40px; border-radius: 8px; box-shadow: 0 1px 8px rgba(0, 0, 0, 0.08); }
|
||||
.zaglavlje { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 32px; padding-bottom: 24px; border-bottom: 1px solid #e5e7eb; }
|
||||
.firma-naziv { font-size: 20px; font-weight: 600; color: #111; }
|
||||
.firma-podnazlov { font-size: 13px; color: #6b7280; margin-top: 3px; }
|
||||
.firma-kontakt { font-size: 12px; color: #6b7280; margin-top: 2px; }
|
||||
.nalog-info { text-align: right; }
|
||||
.nalog-broj { font-size: 16px; font-weight: 600; font-family: monospace; color: #111; }
|
||||
.nalog-datum { font-size: 13px; color: #6b7280; margin-top: 3px; }
|
||||
.meta { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 28px; }
|
||||
.meta-stavka label { font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.05em; color: #9ca3af; display: block; margin-bottom: 3px; }
|
||||
.meta-stavka span { font-size: 14px; color: #111; }
|
||||
table { width: 100%; border-collapse: collapse; margin-bottom: 0; }
|
||||
thead tr { border-bottom: 1.5px solid #111; }
|
||||
thead th { padding: 8px 10px; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: #6b7280; text-align: left; }
|
||||
thead th:not(:first-child) { text-align: right; }
|
||||
tbody tr { border-bottom: 1px solid #e5e7eb; }
|
||||
tbody td { padding: 10px 10px; font-size: 14px; color: #111; }
|
||||
tbody td:not(:first-child) { text-align: right; }
|
||||
tfoot tr { border-top: 1.5px solid #111; }
|
||||
tfoot td { padding: 12px 10px; }
|
||||
.ukupno-label { text-align: right; font-size: 13px; font-weight: 500; color: #6b7280; }
|
||||
.ukupno-iznos { text-align: right; font-size: 18px; font-weight: 700; color: #111; }
|
||||
.ekran-dugmad { display: flex; gap: 10px; justify-content: flex-end; margin-top: 28px; }
|
||||
.btn { padding: 9px 20px; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; border: none; text-decoration: none; display: inline-block; }
|
||||
.btn-primarni { background: #2563eb; color: #fff; }
|
||||
.btn-sekundarni { background: #f3f4f6; color: #374151; }
|
||||
@media print { body { background: #fff; padding: 0; } .stranica { box-shadow: none; border-radius: 0; padding: 20px; max-width: 100%; } .ekran-dugmad { display: none; } }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="stranica">
|
||||
<div class="zaglavlje">
|
||||
<div>
|
||||
<div class="firma-naziv">{{.NazivFirme}}</div>
|
||||
{{if .Podnazlov}}
|
||||
<div class="firma-podnazlov">{{.Podnazlov}}</div>
|
||||
{{end}} {{if .Adresa}}
|
||||
<div class="firma-kontakt">{{.Adresa}}</div>
|
||||
{{end}} {{if .Telefon}}
|
||||
<div class="firma-kontakt">{{.Telefon}}</div>
|
||||
{{end}} {{if .PIB}}
|
||||
<div class="firma-kontakt">PIB: {{.PIB}}</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="nalog-info">
|
||||
<div class="nalog-broj">{{.Nalog.BrojNaloga}}</div>
|
||||
<div class="nalog-datum">
|
||||
{{.Nalog.Datum.Format "02.01.2006. u 15:04"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||
font-size: 14px;
|
||||
color: #111;
|
||||
background: #f5f5f5;
|
||||
padding: 32px 16px;
|
||||
}
|
||||
{{if .KlijentNaziv}}
|
||||
<div class="meta">
|
||||
<div class="meta-stavka">
|
||||
<label>Klijent</label>
|
||||
<span>{{.KlijentNaziv}}</span>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
.stranica {
|
||||
background: #fff;
|
||||
max-width: 640px;
|
||||
margin: 0 auto;
|
||||
padding: 40px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 1px 8px rgba(0,0,0,0.08);
|
||||
}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Artikal</th>
|
||||
<th>Kol.</th>
|
||||
<th>Cena/kom</th>
|
||||
<th>Ukupno</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .Stavke}}
|
||||
<tr>
|
||||
<td>{{.ArtikalNaziv}}</td>
|
||||
<td>{{.Kolicina}}</td>
|
||||
<td>{{printf "%.2f" .CenaPoKomadu}} din</td>
|
||||
<td>{{printf "%.2f" .Ukupno}} din</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="3" class="ukupno-label">Ukupno za naplatu:</td>
|
||||
<td class="ukupno-iznos">{{printf "%.2f" .Nalog.Ukupno}} din</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
.zaglavlje {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 32px;
|
||||
padding-bottom: 24px;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.firma-naziv {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
.firma-podnazlov {
|
||||
font-size: 13px;
|
||||
color: #6b7280;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.firma-kontakt {
|
||||
font-size: 12px;
|
||||
color: #6b7280;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.nalog-info {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.nalog-broj {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
font-family: monospace;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
.nalog-datum {
|
||||
font-size: 13px;
|
||||
color: #6b7280;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.meta {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 16px;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
|
||||
.meta-stavka label {
|
||||
{{if .Nalog.Napomena}}
|
||||
<div
|
||||
style="
|
||||
margin-top: 20px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
">
|
||||
<div
|
||||
style="
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
color: #9ca3af;
|
||||
display: block;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
.meta-stavka span {
|
||||
font-size: 14px;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
thead tr {
|
||||
border-bottom: 1.5px solid #111;
|
||||
}
|
||||
|
||||
thead th {
|
||||
padding: 8px 10px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
color: #6b7280;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
thead th:not(:first-child) { text-align: right; }
|
||||
|
||||
tbody tr {
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
tbody td {
|
||||
padding: 10px 10px;
|
||||
font-size: 14px;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
tbody td:not(:first-child) {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
tfoot tr {
|
||||
border-top: 1.5px solid #111;
|
||||
}
|
||||
|
||||
tfoot td {
|
||||
padding: 12px 10px;
|
||||
}
|
||||
|
||||
.ukupno-label {
|
||||
text-align: right;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.ukupno-iznos {
|
||||
text-align: right;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
.ekran-dugmad {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
justify-content: flex-end;
|
||||
margin-top: 28px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 9px 20px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.btn-primarni {
|
||||
background: #2563eb;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.btn-sekundarni {
|
||||
background: #f3f4f6;
|
||||
color: #374151;
|
||||
}
|
||||
|
||||
@media print {
|
||||
body { background: #fff; padding: 0; }
|
||||
.stranica { box-shadow: none; border-radius: 0; padding: 20px; max-width: 100%; }
|
||||
.ekran-dugmad { display: none; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="stranica">
|
||||
|
||||
<div class="zaglavlje">
|
||||
<div>
|
||||
<div class="firma-naziv">{{.NazivFirme}}</div>
|
||||
{{if .Podnazlov}}<div class="firma-podnazlov">{{.Podnazlov}}</div>{{end}}
|
||||
{{if .Adresa}}<div class="firma-kontakt">{{.Adresa}}</div>{{end}}
|
||||
{{if .Telefon}}<div class="firma-kontakt">{{.Telefon}}</div>{{end}}
|
||||
{{if .PIB}}<div class="firma-kontakt">PIB: {{.PIB}}</div>{{end}}
|
||||
</div>
|
||||
<div class="nalog-info">
|
||||
<div class="nalog-broj">{{.Nalog.BrojNaloga}}</div>
|
||||
<div class="nalog-datum">{{.Nalog.Datum.Format "02.01.2006. u 15:04"}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{if .KlijentNaziv}}
|
||||
<div class="meta">
|
||||
<div class="meta-stavka">
|
||||
<label>Klijent</label>
|
||||
<span>{{.KlijentNaziv}}</span>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Artikal</th>
|
||||
<th>Kol.</th>
|
||||
<th>Cena/kom</th>
|
||||
<th>Ukupno</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .Stavke}}
|
||||
<tr>
|
||||
<td>{{.ArtikalNaziv}}</td>
|
||||
<td>{{.Kolicina}}</td>
|
||||
<td>{{printf "%.2f" .CenaPoKomadu}} din</td>
|
||||
<td>{{printf "%.2f" .Ukupno}} din</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="3" class="ukupno-label">Ukupno za naplatu:</td>
|
||||
<td class="ukupno-iznos">{{printf "%.2f" .Nalog.Ukupno}} din</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
{{if .Nalog.Napomena}}
|
||||
<div style="margin-top:20px;padding-top:16px;border-top:1px solid #e5e7eb;">
|
||||
<div style="font-size:11px;font-weight:500;text-transform:uppercase;letter-spacing:0.05em;color:#9ca3af;margin-bottom:4px;">Napomena</div>
|
||||
<div style="font-size:13px;color:#374151;">{{.Nalog.Napomena}}</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div class="ekran-dugmad">
|
||||
<button class="btn btn-sekundarni" onclick="window.close()">Zatvori</button>
|
||||
<button class="btn btn-primarni" onclick="window.print()">Štampaj</button>
|
||||
margin-bottom: 4px;
|
||||
">
|
||||
Napomena
|
||||
</div>
|
||||
<div style="font-size: 13px; color: #374151">{{.Nalog.Napomena}}</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div class="ekran-dugmad">
|
||||
<button class="btn btn-sekundarni" onclick="window.close()">
|
||||
Zatvori
|
||||
</button>
|
||||
<button class="btn btn-primarni" onclick="window.print()">
|
||||
Štampaj
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>window.onload = function() { window.print(); };</script>
|
||||
</body>
|
||||
</html>
|
||||
<script>
|
||||
window.onload = function () {
|
||||
window.print();
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -17,26 +17,13 @@
|
||||
.servis-tabela tbody tr:nth-child(9) { animation-delay: 0.36s; }
|
||||
.servis-tabela tbody tr:nth-child(10) { animation-delay: 0.40s; }
|
||||
|
||||
.servis-kartice {
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.servis-kartica:nth-child(1) { animation-delay: 0.04s; }
|
||||
.servis-kartica:nth-child(2) { animation-delay: 0.10s; }
|
||||
.servis-kartica:nth-child(3) { animation-delay: 0.16s; }
|
||||
.servis-kartica:nth-child(4) { animation-delay: 0.22s; }
|
||||
.servis-kartica:nth-child(5) { animation-delay: 0.28s; }
|
||||
|
||||
.status-badge {
|
||||
display: inline-block;
|
||||
padding: 3px 10px;
|
||||
border-radius: 20px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.servis-kartice { display: none; flex-direction: column; gap: 12px; }
|
||||
.servis-kartica:nth-child(1) { animation-delay: 0.04s; }
|
||||
.servis-kartica:nth-child(2) { animation-delay: 0.10s; }
|
||||
.servis-kartica:nth-child(3) { animation-delay: 0.16s; }
|
||||
.servis-kartica:nth-child(4) { animation-delay: 0.22s; }
|
||||
.servis-kartica:nth-child(5) { animation-delay: 0.28s; }
|
||||
.status-badge { display: inline-block; padding: 3px 10px; border-radius: 20px; font-size: 12px; font-weight: 500; white-space: nowrap; }
|
||||
|
||||
.status-primljeno { background: rgba(148,163,184,0.15); color: #94a3b8; }
|
||||
.status-dijagnostika { background: rgba(59,130,246,0.15); color: #3b82f6; }
|
||||
|
||||
@@ -9,24 +9,14 @@
|
||||
.detalji-kartica:nth-child(3) { animation-delay: 0.20s; }
|
||||
.detalji-kartica:nth-child(4) { animation-delay: 0.28s; }
|
||||
.detalji-kartica:nth-child(5) { animation-delay: 0.36s; }
|
||||
|
||||
.poruka-animacija { animation: slideDown 0.3s ease forwards; }
|
||||
|
||||
.status-badge {
|
||||
display: inline-block;
|
||||
padding: 4px 12px;
|
||||
border-radius: 20px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.status-primljeno { background: rgba(148,163,184,0.15); color: #94a3b8; }
|
||||
.status-dijagnostika { background: rgba(59,130,246,0.15); color: #3b82f6; }
|
||||
.status-ceka { background: rgba(249,115,22,0.15); color: #f97316; }
|
||||
.status-popravka { background: rgba(234,179,8,0.15); color: #ca8a04; }
|
||||
.status-zavrseno { background: rgba(34,197,94,0.15); color: #16a34a; }
|
||||
.status-preuzeto { background: rgba(21,128,61,0.15); color: #15803d; }
|
||||
.status-badge { display: inline-block; padding: 4px 12px; border-radius: 20px; font-size: 13px; font-weight: 500; white-space: nowrap; }
|
||||
.status-primljeno { background: rgba(148,163,184,0.15); color: #94a3b8; }
|
||||
.status-dijagnostika { background: rgba(59,130,246,0.15); color: #3b82f6; }
|
||||
.status-ceka { background: rgba(249,115,22,0.15); color: #f97316; }
|
||||
.status-popravka { background: rgba(234,179,8,0.15); color: #ca8a04; }
|
||||
.status-zavrseno { background: rgba(34,197,94,0.15); color: #16a34a; }
|
||||
.status-preuzeto { background: rgba(21,128,61,0.15); color: #15803d; }
|
||||
</style>
|
||||
{{end}}
|
||||
|
||||
|
||||
@@ -6,74 +6,20 @@
|
||||
<title>Dvostepena verifikacija — NTech</title>
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||
background: #0f1117;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 16px;
|
||||
}
|
||||
.kartica {
|
||||
background: #1a1d27;
|
||||
border: 0.5px solid #2d3148;
|
||||
border-radius: 16px;
|
||||
padding: 40px;
|
||||
width: 100%;
|
||||
max-width: 380px;
|
||||
}
|
||||
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #0f1117; min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 16px; }
|
||||
.kartica { background: #1a1d27; border: 0.5px solid #2d3148; border-radius: 16px; padding: 40px; width: 100%; max-width: 380px; }
|
||||
.logo { text-align: center; margin-bottom: 32px; }
|
||||
.logo-naziv { font-size: 22px; font-weight: 600; color: #fff; }
|
||||
.opis { font-size: 13px; color: #9ca3af; margin-bottom: 24px; line-height: 1.5; }
|
||||
h1 { font-size: 18px; font-weight: 600; color: #fff; margin-bottom: 8px; }
|
||||
.polje { margin-bottom: 16px; }
|
||||
label { display: block; font-size: 13px; color: #9ca3af; margin-bottom: 6px; }
|
||||
input {
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
background: #0f1117;
|
||||
border: 0.5px solid #2d3148;
|
||||
border-radius: 8px;
|
||||
font-size: 20px;
|
||||
color: #fff;
|
||||
outline: none;
|
||||
text-align: center;
|
||||
letter-spacing: 6px;
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
input { width: 100%; padding: 8px 12px; background: #0f1117; border: 0.5px solid #2d3148; border-radius: 8px; font-size: 20px; color: #fff; outline: none; text-align: center; letter-spacing: 6px; transition: border-color 0.2s; }
|
||||
input:focus { border-color: #e53e3e; }
|
||||
.dugme {
|
||||
width: 100%;
|
||||
padding: 11px;
|
||||
background: #e53e3e;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
margin-top: 8px;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
.dugme { width: 100%; padding: 11px; background: #e53e3e; color: #fff; border: none; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; margin-top: 8px; transition: opacity 0.2s; }
|
||||
.dugme:hover { opacity: 0.88; }
|
||||
.greska {
|
||||
background: #fef2f2;
|
||||
border: 0.5px solid #fca5a5;
|
||||
color: #dc2626;
|
||||
border-radius: 8px;
|
||||
padding: 10px 14px;
|
||||
font-size: 13px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.nazad {
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin-top: 16px;
|
||||
font-size: 13px;
|
||||
color: #6b7280;
|
||||
text-decoration: none;
|
||||
}
|
||||
.greska { background: #fef2f2; border: 0.5px solid #fca5a5; color: #dc2626; border-radius: 8px; padding: 10px 14px; font-size: 13px; margin-bottom: 20px; }
|
||||
.nazad { display: block; text-align: center; margin-top: 16px; font-size: 13px; color: #6b7280; text-decoration: none; }
|
||||
.nazad:hover { color: #9ca3af; }
|
||||
</style>
|
||||
</head>
|
||||
|
||||
@@ -38,91 +38,21 @@
|
||||
|
||||
{{if .AppPozadina}}
|
||||
<style>
|
||||
.app-bg {
|
||||
position: fixed;
|
||||
inset: {{if ne .AppPozadinaBlurPozadine "0"}}-20px{{else}}0{{end}};
|
||||
background-image: url('{{.AppPozadina}}');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
filter: blur({{.AppPozadinaBlurPozadine}}px);
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
.app-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0,0,0,{{.AppPozadinaOpacity}}%);
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
}
|
||||
.raspored {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
.sidebar {
|
||||
background: rgba(0,0,0,{{if .AppPozadinaGlassOpacity}}{{.AppPozadinaGlassOpacity}}%{{else}}0.3{{end}}) !important;
|
||||
backdrop-filter: blur({{.AppPozadinaBlur}}px);
|
||||
-webkit-backdrop-filter: blur({{.AppPozadinaBlur}}px);
|
||||
border-right: 1px solid rgba(255,255,255,0.12) !important;
|
||||
}
|
||||
.sidebar .nav-stavka,
|
||||
.sidebar .logo-naziv,
|
||||
.sidebar .logo-podnazlov {
|
||||
text-shadow: 0 1px 3px rgba(0,0,0,0.8);
|
||||
color: rgba(255,255,255,0.95) !important;
|
||||
}
|
||||
.sidebar .nav-stavka svg {
|
||||
color: rgba(255,255,255,0.95) !important;
|
||||
stroke: rgba(255,255,255,0.95) !important;
|
||||
}
|
||||
.sidebar .nav-oznaka {
|
||||
text-shadow: 0 1px 3px rgba(0,0,0,0.8);
|
||||
color: rgba(255,255,255,0.7) !important;
|
||||
}
|
||||
.topbar {
|
||||
background: rgba(0,0,0,{{if .AppPozadinaGlassOpacity}}{{.AppPozadinaGlassOpacity}}%{{else}}0.08{{end}}) !important;
|
||||
backdrop-filter: blur({{.AppPozadinaBlur}}px);
|
||||
-webkit-backdrop-filter: blur({{.AppPozadinaBlur}}px);
|
||||
border-bottom: 1px solid rgba(255,255,255,0.12) !important;
|
||||
}
|
||||
.kartica {
|
||||
background: rgba(0,0,0,{{if .AppPozadinaGlassOpacity}}{{.AppPozadinaGlassOpacity}}%{{else}}0.08{{end}}) !important;
|
||||
backdrop-filter: blur({{.AppPozadinaBlur}}px);
|
||||
-webkit-backdrop-filter: blur({{.AppPozadinaBlur}}px);
|
||||
border: 1px solid rgba(255,255,255,0.12) !important;
|
||||
}
|
||||
.kartica p,
|
||||
.kartica span,
|
||||
.kartica h1,
|
||||
.kartica h2,
|
||||
.kartica h3,
|
||||
.kartica h4,
|
||||
.kartica label,
|
||||
.kartica td,
|
||||
.kartica th,
|
||||
.kartica li,
|
||||
.kartica a {
|
||||
color: rgba(255,255,255,0.95) !important;
|
||||
text-shadow: 0 1px 3px rgba(0,0,0,0.7);
|
||||
}
|
||||
table, th, td {
|
||||
color: rgba(255,255,255,0.95) !important;
|
||||
text-shadow: 0 1px 3px rgba(0,0,0,0.8);
|
||||
}
|
||||
tr {
|
||||
background: rgba(0,0,0,0.2);
|
||||
}
|
||||
tr:hover {
|
||||
background: rgba(0,0,0,0.35);
|
||||
}
|
||||
thead th {
|
||||
background: rgba(0,0,0,0.4) !important;
|
||||
}
|
||||
div:has(> canvas) {
|
||||
background: rgba(0,0,0,0.3);
|
||||
border-radius: 8px;
|
||||
padding: 8px;
|
||||
}
|
||||
.app-bg { position: fixed; inset: {{if ne .AppPozadinaBlurPozadine "0"}}-20px{{else}}0{{end}}; background-image: url('{{.AppPozadina}}'); background-size: cover; background-position: center; filter: blur({{.AppPozadinaBlurPozadine}}px); pointer-events: none; z-index: 0; }
|
||||
.app-overlay { position: fixed; inset: 0; background: rgba(0,0,0,{{.AppPozadinaOpacity}}%); pointer-events: none; z-index: 1; }
|
||||
.raspored { position: relative; z-index: 2; }
|
||||
.sidebar { background: rgba(0,0,0,{{if .AppPozadinaGlassOpacity}}{{.AppPozadinaGlassOpacity}}%{{else}}0.3{{end}}) !important; backdrop-filter: blur({{.AppPozadinaBlur}}px); -webkit-backdrop-filter: blur({{.AppPozadinaBlur}}px); border-right: 1px solid rgba(255,255,255,0.12) !important; }
|
||||
.sidebar .nav-stavka, .sidebar .logo-naziv, .sidebar .logo-podnazlov { text-shadow: 0 1px 3px rgba(0,0,0,0.8); color: rgba(255,255,255,0.95) !important; }
|
||||
.sidebar .nav-stavka svg { color: rgba(255,255,255,0.95) !important; stroke: rgba(255,255,255,0.95) !important; }
|
||||
.sidebar .nav-oznaka { text-shadow: 0 1px 3px rgba(0,0,0,0.8); color: rgba(255,255,255,0.7) !important; }
|
||||
.topbar { background: rgba(0,0,0,{{if .AppPozadinaGlassOpacity}}{{.AppPozadinaGlassOpacity}}%{{else}}0.08{{end}}) !important; backdrop-filter: blur({{.AppPozadinaBlur}}px); -webkit-backdrop-filter: blur({{.AppPozadinaBlur}}px); border-bottom: 1px solid rgba(255,255,255,0.12) !important; }
|
||||
.kartica { background: rgba(0,0,0,{{if .AppPozadinaGlassOpacity}}{{.AppPozadinaGlassOpacity}}%{{else}}0.08{{end}}) !important; backdrop-filter: blur({{.AppPozadinaBlur}}px); -webkit-backdrop-filter: blur({{.AppPozadinaBlur}}px); border: 1px solid rgba(255,255,255,0.12) !important; }
|
||||
.kartica p, .kartica span, .kartica h1, .kartica h2, .kartica h3, .kartica h4, .kartica label, .kartica td, .kartica th, .kartica li, .kartica a { color: rgba(255,255,255,0.95) !important; text-shadow: 0 1px 3px rgba(0,0,0,0.7); }
|
||||
table, th, td { color: rgba(255,255,255,0.95) !important; text-shadow: 0 1px 3px rgba(0,0,0,0.8); }
|
||||
tr { background: rgba(0,0,0,0.2); }
|
||||
tr:hover { background: rgba(0,0,0,0.35); }
|
||||
thead th { background: rgba(0,0,0,0.4) !important; }
|
||||
div:has(> canvas) { background: rgba(0,0,0,0.3); border-radius: 8px; padding: 8px; }
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
Reference in New Issue
Block a user