Ispravka QR koda za 2FA — generisanje na serveru kao base64 PNG
This commit is contained in:
@@ -81,6 +81,23 @@
|
||||
<span class="nav-tooltip">Izveštaji</span>
|
||||
</a>
|
||||
|
||||
<div class="nav-separator"></div>
|
||||
<div class="nav-oznaka">Nalog</div>
|
||||
|
||||
{{if or (eq .KorisnikUloga "superadmin") (eq .KorisnikUloga "admin")}}
|
||||
<a href="/admin/korisnici" class="nav-stavka {{if eq .Stranica "admin"}}aktivan{{end}}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
|
||||
<span>Korisnici</span>
|
||||
<span class="nav-tooltip">Korisnici</span>
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
<a href="/admin/profil" class="nav-stavka">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
|
||||
<span>Moj profil</span>
|
||||
<span class="nav-tooltip">Moj profil</span>
|
||||
</a>
|
||||
|
||||
<div class="nav-separator"></div>
|
||||
<div class="nav-oznaka">Sistem</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
{{template "base" .}}
|
||||
|
||||
{{define "naslov"}}Korisnici — NTech{{end}}
|
||||
|
||||
{{define "sadrzaj"}}
|
||||
<div style="display:flex;flex-direction:column;gap:16px;">
|
||||
|
||||
{{if .Sacuvano}}
|
||||
<div class="poruka-uspeh">Promene su uspešno sačuvane.</div>
|
||||
{{end}}
|
||||
|
||||
{{if eq .Greska "1"}}
|
||||
<div class="poruka-greska">Proverite unete podatke.</div>
|
||||
{{else if eq .Greska "2"}}
|
||||
<div class="poruka-greska">Greška pri čuvanju. Pokušajte ponovo.</div>
|
||||
{{end}}
|
||||
|
||||
<!-- lista korisnika -->
|
||||
<div class="kartica" 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);">Korisnici sistema</span>
|
||||
</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);">Korisničko ime</th>
|
||||
<th style="padding:10px 20px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Uloga</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:center;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">2FA</th>
|
||||
<th style="padding:10px 20px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Kreiran</th>
|
||||
<th style="padding:10px 20px;text-align:right;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Akcije</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .Korisnici}}
|
||||
<tr style="border-bottom:0.5px solid var(--ivica);">
|
||||
<td style="padding:10px 20px;font-size:14px;font-weight:500;color:var(--tekst-glavni);">{{.KorisnickoIme}}</td>
|
||||
<td style="padding:10px 20px;">
|
||||
{{if eq $.KorisnikUloga "superadmin"}}
|
||||
<form method="POST" action="/admin/korisnici/{{.ID}}/uloga" style="display:inline;">
|
||||
<select name="uloga" onchange="this.form.submit()"
|
||||
style="padding:4px 8px;border:0.5px solid var(--ivica);border-radius:6px;background:var(--pozadina);color:var(--tekst-glavni);font-size:12px;">
|
||||
<option value="superadmin" {{if eq .Uloga "superadmin"}}selected{{end}}>Superadmin</option>
|
||||
<option value="admin" {{if eq .Uloga "admin"}}selected{{end}}>Admin</option>
|
||||
<option value="radnik" {{if eq .Uloga "radnik"}}selected{{end}}>Radnik</option>
|
||||
</select>
|
||||
</form>
|
||||
{{else}}
|
||||
<span style="font-size:13px;color:var(--tekst-sporedni);">
|
||||
{{if eq .Uloga "superadmin"}}Superadmin{{else if eq .Uloga "admin"}}Admin{{else}}Radnik{{end}}
|
||||
</span>
|
||||
{{end}}
|
||||
</td>
|
||||
<td style="padding:10px 20px;text-align:center;">
|
||||
{{if .Aktivan}}
|
||||
<span style="display:inline-block;padding:2px 10px;border-radius:20px;background:#f0fdf4;color:#16a34a;font-size:11px;font-weight:500;">Aktivan</span>
|
||||
{{else}}
|
||||
<span style="display:inline-block;padding:2px 10px;border-radius:20px;background:#fef2f2;color:#dc2626;font-size:11px;font-weight:500;">Deaktiviran</span>
|
||||
{{end}}
|
||||
</td>
|
||||
<td style="padding:10px 20px;text-align:center;">
|
||||
{{if .TotpTajna}}
|
||||
<span style="font-size:11px;color:#16a34a;">✓ Uključena</span>
|
||||
{{else}}
|
||||
<span style="font-size:11px;color:var(--tekst-sporedni);">—</span>
|
||||
{{end}}
|
||||
</td>
|
||||
<td style="padding:10px 20px;font-size:13px;color:var(--tekst-sporedni);">
|
||||
{{.DatumKreiranja.Format "02.01.2006."}}
|
||||
</td>
|
||||
<td style="padding:10px 20px;text-align:right;">
|
||||
{{if ne .KorisnickoIme $.KorisnikIme}}
|
||||
<form method="POST" action="/admin/korisnici/{{.ID}}/aktivan" style="display:inline;">
|
||||
<button type="submit"
|
||||
style="padding:5px 12px;border:0.5px solid var(--ivica);border-radius:6px;background:transparent;color:var(--tekst-sporedni);font-size:12px;cursor:pointer;">
|
||||
{{if .Aktivan}}Deaktiviraj{{else}}Aktiviraj{{end}}
|
||||
</button>
|
||||
</form>
|
||||
{{end}}
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- forma za novog korisnika -->
|
||||
<div class="kartica">
|
||||
<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);">
|
||||
Novi korisnik
|
||||
</div>
|
||||
<form method="POST" action="/admin/korisnici/novi">
|
||||
<div style="display:grid;grid-template-columns:repeat(auto-fit, minmax(180px, 1fr));gap:14px;margin-bottom:16px;">
|
||||
<div>
|
||||
<label style="font-size:13px;color:var(--tekst-sporedni);display:block;margin-bottom:6px;">Korisničko ime</label>
|
||||
<input type="text" name="korisnicko_ime" required minlength="3"
|
||||
style="width:100%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
||||
</div>
|
||||
<div>
|
||||
<label style="font-size:13px;color:var(--tekst-sporedni);display:block;margin-bottom:6px;">Lozinka</label>
|
||||
<input type="password" name="lozinka" required minlength="8"
|
||||
style="width:100%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
||||
</div>
|
||||
<div>
|
||||
<label style="font-size:13px;color:var(--tekst-sporedni);display:block;margin-bottom:6px;">Uloga</label>
|
||||
<select name="uloga"
|
||||
style="width:100%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
||||
<option value="radnik">Radnik</option>
|
||||
<option value="admin">Admin</option>
|
||||
{{if eq .KorisnikUloga "superadmin"}}<option value="superadmin">Superadmin</option>{{end}}
|
||||
</select>
|
||||
</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;">
|
||||
Dodaj korisnika
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -0,0 +1,129 @@
|
||||
{{template "base" .}}
|
||||
|
||||
{{define "naslov"}}Moj profil — NTech{{end}}
|
||||
|
||||
{{define "dodatni-css"}}{{end}}
|
||||
|
||||
{{define "sadrzaj"}}
|
||||
<div style="display:flex;flex-direction:column;gap:16px;max-width:560px;">
|
||||
|
||||
{{if eq .Sacuvano "lozinka"}}
|
||||
<div class="poruka-uspeh">Lozinka je uspešno promenjena.</div>
|
||||
{{else if eq .Sacuvano "totp"}}
|
||||
<div class="poruka-uspeh">Dvostepena verifikacija je uspešno uključena.</div>
|
||||
{{else if eq .Sacuvano "totp_off"}}
|
||||
<div class="poruka-uspeh">Dvostepena verifikacija je isključena.</div>
|
||||
{{end}}
|
||||
|
||||
<!-- promena lozinke -->
|
||||
<div class="kartica">
|
||||
<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>
|
||||
|
||||
{{if eq .Greska "lozinka"}}
|
||||
<div class="poruka-greska" style="margin-bottom:14px;">Stara lozinka nije ispravna.</div>
|
||||
{{else if eq .Greska "lozinka2"}}
|
||||
<div class="poruka-greska" style="margin-bottom:14px;">Nova lozinka mora imati najmanje 8 karaktera i lozinke moraju biti iste.</div>
|
||||
{{end}}
|
||||
|
||||
<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%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
||||
</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%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
||||
</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%;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:14px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;">
|
||||
</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>
|
||||
|
||||
<!-- TOTP / 2FA -->
|
||||
<div class="kartica">
|
||||
<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>
|
||||
|
||||
{{if .TotpURI}}
|
||||
<!-- postavljanje TOTP -->
|
||||
{{if eq .Greska "totp"}}
|
||||
<div class="poruka-greska" style="margin-bottom:14px;">Neispravan kod. Pokušajte ponovo.</div>
|
||||
{{end}}
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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;padding:8px 12px;border:0.5px solid var(--ivica);border-radius:8px;font-size:18px;background:var(--pozadina);color:var(--tekst-glavni);outline:none;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>
|
||||
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -0,0 +1,320 @@
|
||||
{{template "base" .}}
|
||||
|
||||
{{define "naslov"}}Izveštaji — NTech{{end}}
|
||||
|
||||
{{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;
|
||||
}
|
||||
|
||||
.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-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.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.upozorenje { background: #fffbeb; color: #b45309; }
|
||||
.badge-dana.kritican { background: #fef2f2; color: #dc2626; }
|
||||
</style>
|
||||
{{end}}
|
||||
|
||||
{{define "sadrzaj"}}
|
||||
<div style="display:flex;flex-direction:column;gap:20px;">
|
||||
|
||||
<!-- 1. mesečni prihod -->
|
||||
<div class="kartica">
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:10px;margin-bottom:4px;">
|
||||
<div class="izv-naslov" style="margin-bottom:0;">Mesečni prihod — poslednjih 12 meseci</div>
|
||||
<div class="toggle-red" style="margin-bottom:0;">
|
||||
<span style="font-size:13px;color:var(--tekst-sporedni);">Grafikon</span>
|
||||
<label class="toggle-switch">
|
||||
<input type="checkbox" id="toggle-grafikon" checked>
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="grafikon-wrapper" style="margin:16px 0;position:relative;height:260px;">
|
||||
<canvas id="grafikon-prihod"></canvas>
|
||||
</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:8px 12px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Mesec</th>
|
||||
<th style="padding:8px 12px;text-align:right;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Prodaja</th>
|
||||
<th style="padding:8px 12px;text-align:right;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Servis</th>
|
||||
<th style="padding:8px 12px;text-align:right;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Ukupno</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .MesecniPrihodi}}
|
||||
<tr style="border-bottom:0.5px solid var(--ivica);">
|
||||
<td style="padding:8px 12px;font-size:13px;color:var(--tekst-glavni);">{{.MesecPrikaz}}</td>
|
||||
<td style="padding:8px 12px;text-align:right;font-size:13px;color:var(--tekst-sporedni);">
|
||||
{{if gt .Prodaja 0.0}}{{printf "%.0f" .Prodaja}} din{{else}}—{{end}}
|
||||
</td>
|
||||
<td style="padding:8px 12px;text-align:right;font-size:13px;color:var(--tekst-sporedni);">
|
||||
{{if gt .Servis 0.0}}{{printf "%.0f" .Servis}} din{{else}}—{{end}}
|
||||
</td>
|
||||
<td style="padding:8px 12px;text-align:right;font-size:13px;font-weight:500;color:var(--tekst-glavni);">
|
||||
{{if gt .Ukupno 0.0}}{{printf "%.0f" .Ukupno}} din{{else}}—{{end}}
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 2. stari otvoreni nalozi -->
|
||||
<div class="kartica">
|
||||
<div class="izv-naslov">Stari otvoreni nalozi — bez završetka duže od 14 dana</div>
|
||||
{{if .StariNalozi}}
|
||||
<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:8px 12px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Nalog</th>
|
||||
<th style="padding:8px 12px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Uređaj</th>
|
||||
<th style="padding:8px 12px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Klijent</th>
|
||||
<th style="padding:8px 12px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Status</th>
|
||||
<th style="padding:8px 12px;text-align:left;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Primljeno</th>
|
||||
<th style="padding:8px 12px;text-align:right;font-size:12px;font-weight:500;color:var(--tekst-sporedni);">Dana</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .StariNalozi}}
|
||||
<tr style="border-bottom:0.5px solid var(--ivica);">
|
||||
<td style="padding:8px 12px;">
|
||||
<a href="/servis/{{.ID}}" style="font-size:13px;font-family:monospace;color:var(--sb-akcent);text-decoration:none;">{{.BrojNaloga}}</a>
|
||||
</td>
|
||||
<td style="padding:8px 12px;font-size:13px;color:var(--tekst-glavni);">{{.Uredjaj}}</td>
|
||||
<td style="padding:8px 12px;font-size:13px;color:var(--tekst-sporedni);">{{.KlijentNaziv}}</td>
|
||||
<td style="padding:8px 12px;font-size:13px;color:var(--tekst-sporedni);">{{.Status}}</td>
|
||||
<td style="padding:8px 12px;font-size:13px;color:var(--tekst-sporedni);">{{.DatumPrijema}}</td>
|
||||
<td style="padding:8px 12px;text-align:right;">
|
||||
{{if gt .DanaProslo 30}}
|
||||
<span class="badge-dana kritican">{{.DanaProslo}} dana</span>
|
||||
{{else}}
|
||||
<span class="badge-dana upozorenje">{{.DanaProslo}} dana</span>
|
||||
{{end}}
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{else}}
|
||||
<div style="font-size:13px;color:var(--tekst-sporedni);padding:8px 0;">Nema zaostalih naloga. Sve je u redu.</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
|
||||
<!-- 3. top 10 artikala -->
|
||||
<div class="kartica">
|
||||
<div class="izv-naslov">Najprodavaniji artikli — top 10</div>
|
||||
{{if .TopArtikli}}
|
||||
<table style="width:100%;border-collapse:collapse;">
|
||||
<thead>
|
||||
<tr style="border-bottom:0.5px solid var(--ivica);">
|
||||
<th style="padding:6px 8px;text-align:left;font-size:11px;font-weight:500;color:var(--tekst-sporedni);width:32px;">#</th>
|
||||
<th style="padding:6px 8px;text-align:left;font-size:11px;font-weight:500;color:var(--tekst-sporedni);">Artikal</th>
|
||||
<th style="padding:6px 8px;text-align:right;font-size:11px;font-weight:500;color:var(--tekst-sporedni);width:60px;">Kom.</th>
|
||||
<th style="padding:6px 8px;text-align:right;font-size:11px;font-weight:500;color:var(--tekst-sporedni);width:100px;">Prihod</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .TopArtikli}}
|
||||
<tr style="border-bottom:0.5px solid var(--ivica);">
|
||||
<td style="padding:7px 8px;">
|
||||
<span class="rang-broj {{if eq .Rang 1}}zlatni{{end}}">{{.Rang}}</span>
|
||||
</td>
|
||||
<td style="padding:7px 8px;">
|
||||
<div style="font-size:13px;color:var(--tekst-glavni);">{{.Naziv}}</div>
|
||||
<div style="font-size:11px;color:var(--tekst-sporedni);margin-top:1px;">{{.Kategorija}}</div>
|
||||
</td>
|
||||
<td style="padding:7px 8px;text-align:right;font-size:13px;color:var(--tekst-glavni);">{{.UkupnoKolicina}}</td>
|
||||
<td style="padding:7px 8px;text-align:right;font-size:13px;font-weight:500;color:var(--tekst-glavni);">{{printf "%.0f" .UkupnoPrihod}} din</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{else}}
|
||||
<div style="font-size:13px;color:var(--tekst-sporedni);padding:8px 0;">Nema podataka o prodaji.</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
<!-- 4. top 10 klijenata -->
|
||||
<div class="kartica">
|
||||
<div class="izv-naslov">Najvažniji klijenti — top 10</div>
|
||||
{{if .TopKlijenti}}
|
||||
<table style="width:100%;border-collapse:collapse;">
|
||||
<thead>
|
||||
<tr style="border-bottom:0.5px solid var(--ivica);">
|
||||
<th style="padding:6px 8px;text-align:left;font-size:11px;font-weight:500;color:var(--tekst-sporedni);width:32px;">#</th>
|
||||
<th style="padding:6px 8px;text-align:left;font-size:11px;font-weight:500;color:var(--tekst-sporedni);">Klijent</th>
|
||||
<th style="padding:6px 8px;text-align:right;font-size:11px;font-weight:500;color:var(--tekst-sporedni);width:60px;">Naloga</th>
|
||||
<th style="padding:6px 8px;text-align:right;font-size:11px;font-weight:500;color:var(--tekst-sporedni);width:110px;">Vrednost</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .TopKlijenti}}
|
||||
<tr style="border-bottom:0.5px solid var(--ivica);">
|
||||
<td style="padding:7px 8px;">
|
||||
<span class="rang-broj {{if eq .Rang 1}}zlatni{{end}}">{{.Rang}}</span>
|
||||
</td>
|
||||
<td style="padding:7px 8px;font-size:13px;color:var(--tekst-glavni);">{{.Naziv}}</td>
|
||||
<td style="padding:7px 8px;text-align:right;font-size:13px;color:var(--tekst-sporedni);">{{.BrojNaloga}}</td>
|
||||
<td style="padding:7px 8px;text-align:right;font-size:13px;font-weight:500;color:var(--tekst-glavni);">{{printf "%.0f" .UkupnoVrednost}} din</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{else}}
|
||||
<div style="font-size:13px;color:var(--tekst-sporedni);padding:8px 0;">Nema podataka o klijentima.</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
var podaci = {{.GrafikonJSON}};
|
||||
|
||||
var isDark = document.documentElement.getAttribute('data-tema') !== 'svetla';
|
||||
var tekstBoja = getComputedStyle(document.documentElement).getPropertyValue('--tekst-sporedni').trim() || '#6b7280';
|
||||
var ivicaBoja = getComputedStyle(document.documentElement).getPropertyValue('--ivica').trim() || '#e5e7eb';
|
||||
|
||||
var ctx = document.getElementById('grafikon-prihod').getContext('2d');
|
||||
var grafikon = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: podaci.labele,
|
||||
datasets: [
|
||||
{
|
||||
label: 'Prodaja',
|
||||
data: podaci.prodaja,
|
||||
backgroundColor: 'rgba(79, 126, 248, 0.75)',
|
||||
borderRadius: 4,
|
||||
borderSkipped: false,
|
||||
},
|
||||
{
|
||||
label: 'Servis',
|
||||
data: podaci.servis,
|
||||
backgroundColor: 'rgba(22, 163, 74, 0.75)',
|
||||
borderRadius: 4,
|
||||
borderSkipped: false,
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: {
|
||||
labels: { color: tekstBoja, font: { size: 12 }, boxWidth: 12, padding: 16 }
|
||||
},
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
label: function(ctx) {
|
||||
return ' ' + ctx.dataset.label + ': ' + Math.round(ctx.parsed.y).toLocaleString('sr-RS') + ' din';
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
stacked: false,
|
||||
ticks: { color: tekstBoja, font: { size: 11 } },
|
||||
grid: { color: ivicaBoja }
|
||||
},
|
||||
y: {
|
||||
ticks: {
|
||||
color: tekstBoja,
|
||||
font: { size: 11 },
|
||||
callback: function(v) { return Math.round(v).toLocaleString('sr-RS') + ' din'; }
|
||||
},
|
||||
grid: { color: ivicaBoja }
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('toggle-grafikon').addEventListener('change', function() {
|
||||
document.getElementById('grafikon-wrapper').style.display = this.checked ? 'block' : 'none';
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
{{end}}
|
||||
@@ -117,7 +117,15 @@
|
||||
<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="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06-.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
|
||||
<span style="font-size:15px;font-weight:500;color:var(--tekst-glavni);">Sistem</span>
|
||||
</div>
|
||||
<div style="font-size:13px;color:var(--tekst-sporedni);">Verzija programa: <span style="color:var(--tekst-glavni);font-weight:500;">1.0.0</span></div>
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;">
|
||||
<div style="font-size:13px;color:var(--tekst-sporedni);">Verzija programa: <span style="color:var(--tekst-glavni);font-weight:500;">1.0.0</span></div>
|
||||
<a href="/podesavanja/backup"
|
||||
style="display:inline-flex;align-items:center;gap:6px;padding:8px 16px;background:var(--kartica);border:0.5px solid var(--ivica);border-radius:8px;font-size:13px;color:var(--tekst-sporedni);text-decoration:none;transition:background 0.2s;"
|
||||
onmouseover="this.style.background='var(--pozadina)'" onmouseout="this.style.background='var(--kartica)'">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
|
||||
Preuzmi backup baze
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- dugme za čuvanje -->
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
<!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;
|
||||
}
|
||||
.kartica {
|
||||
background: #1a1d2e;
|
||||
border: 0.5px solid #2a2d3e;
|
||||
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;
|
||||
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: 10px 14px;
|
||||
background: #0f1117;
|
||||
border: 0.5px solid #2a2d3e;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
outline: none;
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
input:focus { border-color: #4f7ef8; }
|
||||
.dugme {
|
||||
width: 100%;
|
||||
padding: 11px;
|
||||
background: #4f7ef8;
|
||||
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>
|
||||
<div class="kartica">
|
||||
<div class="logo">
|
||||
<div class="logo-naziv">NTech</div>
|
||||
<div class="logo-podnazlov">Sistem za upravljanje</div>
|
||||
</div>
|
||||
|
||||
<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>
|
||||
{{end}}
|
||||
|
||||
{{if .Sacuvano}}
|
||||
<div class="uspeh">Nalog je kreiran. Možete se prijaviti.</div>
|
||||
{{end}}
|
||||
|
||||
<form method="POST" action="/prijava">
|
||||
<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>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,112 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="sr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Podešavanje — 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: #1a1d2e;
|
||||
border: 0.5px solid #2a2d3e;
|
||||
border-radius: 16px;
|
||||
padding: 40px;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
}
|
||||
.logo { text-align: center; margin-bottom: 32px; }
|
||||
.logo-naziv { font-size: 22px; font-weight: 600; color: #fff; }
|
||||
.logo-podnazlov { font-size: 13px; color: #6b7280; margin-top: 4px; }
|
||||
h1 { font-size: 18px; font-weight: 600; color: #fff; margin-bottom: 6px; }
|
||||
.opis { font-size: 13px; color: #9ca3af; margin-bottom: 24px; line-height: 1.5; }
|
||||
.polje { margin-bottom: 16px; }
|
||||
label { display: block; font-size: 13px; color: #9ca3af; margin-bottom: 6px; }
|
||||
input {
|
||||
width: 100%;
|
||||
padding: 10px 14px;
|
||||
background: #0f1117;
|
||||
border: 0.5px solid #2a2d3e;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
outline: none;
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
input:focus { border-color: #4f7ef8; }
|
||||
.dugme {
|
||||
width: 100%;
|
||||
padding: 11px;
|
||||
background: #4f7ef8;
|
||||
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;
|
||||
}
|
||||
.napomena {
|
||||
font-size: 12px;
|
||||
color: #6b7280;
|
||||
margin-top: 4px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="kartica">
|
||||
<div class="logo">
|
||||
<div class="logo-naziv">NTech</div>
|
||||
<div class="logo-podnazlov">Prvo pokretanje</div>
|
||||
</div>
|
||||
|
||||
<h1>Kreiranje admin naloga</h1>
|
||||
<p class="opis">Dobrodošli. Kreirajte nalog superadmin korisnika koji će upravljati sistemom.</p>
|
||||
|
||||
{{if eq .Greska "1"}}
|
||||
<div class="greska">Proverite unete podatke. Korisničko ime mora imati najmanje 3 karaktera, lozinka najmanje 8, a lozinke moraju biti iste.</div>
|
||||
{{else if eq .Greska "2"}}
|
||||
<div class="greska">Greška pri kreiranju naloga. Pokušajte ponovo.</div>
|
||||
{{end}}
|
||||
|
||||
<form method="POST" action="/setup">
|
||||
<div class="polje">
|
||||
<label for="korisnicko_ime">Korisničko ime</label>
|
||||
<input type="text" id="korisnicko_ime" name="korisnicko_ime"
|
||||
autocomplete="username" autofocus required minlength="3">
|
||||
</div>
|
||||
<div class="polje">
|
||||
<label for="lozinka">Lozinka</label>
|
||||
<input type="password" id="lozinka" name="lozinka"
|
||||
autocomplete="new-password" required minlength="8">
|
||||
<div class="napomena">Najmanje 8 karaktera</div>
|
||||
</div>
|
||||
<div class="polje">
|
||||
<label for="lozinka_potvrda">Potvrda lozinke</label>
|
||||
<input type="password" id="lozinka_potvrda" name="lozinka_potvrda"
|
||||
autocomplete="new-password" required>
|
||||
</div>
|
||||
<button type="submit" class="dugme">Kreiraj nalog i nastavi</button>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,106 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="sr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<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: #1a1d2e;
|
||||
border: 0.5px solid #2a2d3e;
|
||||
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: 10px 14px;
|
||||
background: #0f1117;
|
||||
border: 0.5px solid #2a2d3e;
|
||||
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: #4f7ef8; }
|
||||
.dugme {
|
||||
width: 100%;
|
||||
padding: 11px;
|
||||
background: #4f7ef8;
|
||||
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;
|
||||
}
|
||||
.nazad:hover { color: #9ca3af; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="kartica">
|
||||
<div class="logo">
|
||||
<div class="logo-naziv">NTech</div>
|
||||
</div>
|
||||
|
||||
<h1>Dvostepena verifikacija</h1>
|
||||
<p class="opis">Unesite 6-cifreni kod iz vaše aplikacije za autentifikaciju.</p>
|
||||
|
||||
{{if eq .Greska "1"}}
|
||||
<div class="greska">Neispravan kod. Pokušajte ponovo.</div>
|
||||
{{end}}
|
||||
|
||||
<form method="POST" action="/prijava/totp">
|
||||
<div class="polje">
|
||||
<label for="kod">Kod za verifikaciju</label>
|
||||
<input type="text" id="kod" name="kod"
|
||||
inputmode="numeric" pattern="[0-9]{6}"
|
||||
maxlength="6" autocomplete="one-time-code" autofocus required>
|
||||
</div>
|
||||
<button type="submit" class="dugme">Potvrdi</button>
|
||||
</form>
|
||||
|
||||
<a href="/odjava" class="nazad">← Nazad na prijavu</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user