Files
GoNtech/web/templates/teme/podrazumevana/base.html
T
Dasko 8cec26a03f Refaktoring: uklanjanje globalne teme i app pozadine, dozvole u podešavanja, UI ispravke
- Uklonjena globalna tema i pozadinska slika aplikacije (ostala samo lična pozadina po korisniku)
- Uklonjena animacija treperenja pozadine pri navigaciji; dodat sessionStorage za instant prikaz
- Dozvole premeštene iz sidebar-a u Podešavanja → Sistem; vidljive i adminu (samo Radnik kolona)
- Admin može menjati samo dozvole uloge Radnik, superadmin menja i Radnik i Admin
- Zatamnjivanje kartice NTech na stranici prijave — novi slider u Podešavanja → Izgled
- Upozorenje na dashboard-u (kritične zalihe) — popravljen kontrast boje
2026-06-06 21:07:01 +02:00

260 lines
8.7 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{{define "base"}}
<!doctype html>
<html lang="sr">
<head>
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{block "naslov" .}}NTech{{end}}</title>
<meta name="csrf-token" content="{{.CsrfToken}}">
<script>
if (window.innerWidth > 768 && localStorage.getItem('sidebar-skupljen') === 'true') {
document.documentElement.classList.add('sidebar-init-skupljen');
}
// pozadinska slika iz prethodne stranice — sprečava treperenje pri navigaciji
(function() {
var bg = sessionStorage.getItem('ntech-bg');
if (bg) {
var s = document.documentElement.style;
s.backgroundImage = 'url(' + bg + ')';
s.backgroundSize = 'cover';
s.backgroundPosition = 'center';
s.backgroundAttachment = 'fixed';
}
})();
</script>
<!-- tema — učitava se prva -->
<link rel="stylesheet" href="/static/css/teme/{{.Tema}}.css" />
<!-- glavni stilovi -->
<link rel="stylesheet" href="/static/css/main.css" />
<!-- tailwind -->
<script src="https://cdn.tailwindcss.com"></script>
{{block "dodatni-css" .}}{{end}}
{{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;
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
var meni = document.getElementById('avatar-meni');
if (!meni) return;
meni.style.backdropFilter = 'none';
meni.style.webkitBackdropFilter = 'none';
meni.style.background = 'var(--kartica)';
});
</script>
{{end}}
</head>
<body>
{{if .AppPozadina}}<div class="app-bg"></div><div class="app-overlay"></div>{{end}}
<div class="raspored">
<div class="sidebar-overlay" id="sidebar-overlay"></div>
{{template "sidebar" .}}
<div class="glavni-sadrzaj">
{{template "topbar" .}}
<main class="sadrzaj">{{block "sadrzaj" .}}{{end}}</main>
</div>
</div>
<!-- flash poruka — prikazuje se kao toast u gornjem desnom uglu -->
{{if .Flash}}
<div id="flash-toast" class="flash-toast flash-{{.Flash.Tip}}" role="alert">
<span class="flash-ikona">{{if eq .Flash.Tip "uspeh"}}✓{{else}}!{{end}}</span>
<span class="flash-tekst">{{.Flash.Poruka}}</span>
<button class="flash-zatvori" onclick="this.parentElement.remove()" aria-label="Zatvori">×</button>
</div>
<script>
(function() {
var t = document.getElementById('flash-toast');
if (!t) return;
setTimeout(function() {
t.classList.add('flash-izlaz');
setTimeout(function() { if (t.parentElement) t.remove(); }, 350);
}, 4000);
})();
</script>
{{end}}
<!-- alpine.js za interaktivnost -->
<script
src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"
defer
></script>
<!-- htmx za komunikaciju sa serverom -->
<script src="https://cdn.jsdelivr.net/npm/htmx.org@2.x.x/dist/htmx.min.js"></script>
<!-- sidebar logika -->
<!-- sidebar logika -->
<script>
const sidebar = document.getElementById("sidebar");
const hamburger = document.getElementById("hamburger");
const overlay = document.getElementById("sidebar-overlay");
const mobilni = () => window.innerWidth <= 768;
// učitaj stanje iz localStorage samo za desktop
if (!mobilni() && localStorage.getItem("sidebar-skupljen") === "true") {
sidebar.classList.add("skupljen");
}
document.documentElement.classList.remove('sidebar-init-skupljen');
hamburger.addEventListener("click", () => {
if (mobilni()) {
// mobilno — drawer ponašanje
sidebar.classList.toggle("otvoren");
overlay.classList.toggle("aktivan");
} else {
// desktop — skupljanje
sidebar.classList.toggle("skupljen");
localStorage.setItem(
"sidebar-skupljen",
sidebar.classList.contains("skupljen"),
);
}
});
// zatvori sidebar klikom na overlay
overlay.addEventListener("click", () => {
sidebar.classList.remove("otvoren");
overlay.classList.remove("aktivan");
});
// zatvori sidebar kada se promeni veličina prozora
window.addEventListener("resize", () => {
if (!mobilni()) {
sidebar.classList.remove("otvoren");
overlay.classList.remove("aktivan");
}
});
</script>
{{block "dodatni-js" .}}{{end}}
<!-- čuva URL pozadine za sledeću navigaciju (bez treperenja) -->
<script>
{{if .AppPozadina}}
sessionStorage.setItem('ntech-bg', '{{.AppPozadina}}');
{{else}}
sessionStorage.removeItem('ntech-bg');
document.documentElement.style.backgroundImage = '';
{{end}}
</script>
<!-- CSRF: automatski dodaje skriveno polje u sve POST forme -->
<script>
document.addEventListener('DOMContentLoaded', function() {
var m = document.querySelector('meta[name="csrf-token"]');
if (!m || !m.content) return;
document.querySelectorAll('form[method="POST"],form[method="post"]').forEach(function(f) {
if (f.querySelector('input[name="_csrf"]')) return;
var i = document.createElement('input');
i.type = 'hidden'; i.name = '_csrf'; i.value = m.content;
f.appendChild(i);
});
// data-potvrda: sigurna alternativa za onclick=confirm() na dugmadima i linkovima
// Vrednost atributa je poruka koja se prikazuje korisniku. Go template je HTML-escape-uje,
// JS čita originalnu vrednost — nema problema sa specijalnim karakterima u imenima.
document.querySelectorAll('[data-potvrda]').forEach(function(el) {
el.addEventListener('click', function(e) {
if (!confirm(el.getAttribute('data-potvrda'))) e.preventDefault();
});
});
});
</script>
</body>
</html>
{{end}}