Servis forma, animacije, hover efekti i pojačane senke

Servis:
- Nova polja: ostecenja, pin_uredjaja, pribor (migracija 051)
- Default garancija iz podešavanja, svič "Bez garancije" u formi
- Podešavanja → Servis: konfigurabilan rok garancije (migracija 052)
- Default datum prijema = danas; datum_prijema se eksplicitno upisuje
- Sidebar link za Servis podešavanja

PDV/Nivelacije:
- Default raspon datuma = početak/kraj tekućeg meseca (KIR, KPR, Nivelacije)
- Dodata class="tabela" na tabele bez klase (KIR, KPR, Obračun, Nivelacije)

Animacije (Moj profil → Tema):
- Korisnik bira vrstu animacije: bez, fadeInUp, fadeIn, scaleIn, slideLeft
- Čuva se po korisniku u korisnici.lokalna_animacija (migracija 053)
- CSS [data-animacija] radi na body (globalno) i na preview wrapperima (izolovano)
- Preview animacije izolovan: data-animacija na #anim-preview-wrap, ne na body
- Mobilne kartice se animiraju kad korisnik odabere stil (podrazumevano ne)
- Animacija primenjena direktno na .tabela tbody tr (bez potrebe za .animiraj)

Hover efekti (Moj profil → Tema):
- Opcije: podrazumevano, bez, podizanje, svetlost, zoom, boja
- Čuva se po korisniku u korisnici.lokalni_hover (migracija 054)
- CSS [data-hover] radi izolovano; preview menja samo #hover-preview-wrap
- Pojačane senke u oba teme (--senka i nova --senka-hover promenljiva)
- Transition dodat za transform i background na karticama

Grafikon (Izveštaji): toggle zamenjen globalnim .toggl/.toggl-klizac svičom
This commit is contained in:
2026-06-18 02:21:06 +02:00
parent b417ff6d02
commit f29e76612e
36 changed files with 707 additions and 53 deletions
+83 -7
View File
@@ -339,12 +339,42 @@ body {
border-radius: 12px;
padding: 16px;
box-shadow: var(--senka);
transition: transform 0.25s cubic-bezier(.4,0,.2,1), box-shadow 0.25s;
transition: box-shadow 0.25s, border-color 0.25s, transform 0.25s, background 0.25s;
}
.kartica:hover {
transform: scale(1.02);
box-shadow: var(--senka-hover);
border-color: var(--ivica-jaka);
}
/* hover varijante po korisničkoj preferenciji.
Selektor je [data-hover] (ne body[data-hover]) da bi isti CSS
radio i globalno (body) i lokalno na preview wrapperima. */
[data-hover="bez"] .kartica:hover {
box-shadow: var(--senka);
border-color: var(--ivica);
transform: none;
}
[data-hover="podizanje"] .kartica:hover {
box-shadow: var(--senka-hover);
border-color: var(--ivica-jaka);
transform: translateY(-3px);
}
[data-hover="svetlost"] .kartica:hover {
box-shadow: 0 0 0 1.5px var(--sb-akcent), 0 0 20px color-mix(in srgb, var(--sb-akcent) 35%, transparent);
border-color: var(--sb-akcent);
transform: none;
}
[data-hover="zoom"] .kartica:hover {
box-shadow: var(--senka-hover);
border-color: var(--ivica-jaka);
transform: scale(1.02);
}
[data-hover="boja"] .kartica:hover {
box-shadow: var(--senka-hover);
border-color: var(--ivica-jaka);
background: color-mix(in srgb, var(--sb-akcent) 6%, var(--kartica));
transform: none;
}
/* modal za premeštanje artikla — koristi promenljive teme, pa prati svetlu/tamnu;
@@ -592,7 +622,9 @@ body {
color: var(--tekst-sporedni);
text-transform: uppercase;
letter-spacing: 0.05em;
margin-bottom: 10px;
padding-bottom: 8px;
margin-bottom: 12px;
border-bottom: 0.5px solid var(--ivica);
}
/* avatar krug korisnika u topbaru */
@@ -980,6 +1012,21 @@ select {
to { opacity: 1; transform: translateY(0); }
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes scaleIn {
from { opacity: 0; transform: scale(0.95); }
to { opacity: 1; transform: scale(1); }
}
@keyframes slideLeft {
from { opacity: 0; transform: translateX(-12px); }
to { opacity: 1; transform: translateX(0); }
}
@keyframes slideDown {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
@@ -1003,11 +1050,40 @@ select {
animation: fadeInUp 0.2s ease backwards;
}
/* kartice ne animiramo po defaultu — animacija je samo na redovima tabela */
.kartica.animiraj {
animation: none;
}
/* korisnikova preferencija animacije: body[data-animacija] nadjačava podrazumevano.
Kad korisnik odabere stil, animiraju se i redovi tabela i mobilne kartice. */
[data-animacija="bez"] .animiraj,
[data-animacija="bez"] .tabela tbody tr,
[data-animacija="bez"] .kartica.animiraj { animation: none; }
[data-animacija="fadeInUp"] .animiraj,
[data-animacija="fadeInUp"] .tabela tbody tr,
[data-animacija="fadeInUp"] .kartica.animiraj { animation: fadeInUp 0.2s ease backwards; }
[data-animacija="fadeIn"] .animiraj,
[data-animacija="fadeIn"] .tabela tbody tr,
[data-animacija="fadeIn"] .kartica.animiraj { animation: fadeIn 0.2s ease backwards; }
[data-animacija="scaleIn"] .animiraj,
[data-animacija="scaleIn"] .tabela tbody tr,
[data-animacija="scaleIn"] .kartica.animiraj { animation: scaleIn 0.2s ease backwards; }
[data-animacija="slideLeft"] .animiraj,
[data-animacija="slideLeft"] .tabela tbody tr,
[data-animacija="slideLeft"] .kartica.animiraj { animation: slideLeft 0.2s ease backwards; }
/* Stepenasta (stagger) animacija redova u svim listama — JEDNO mesto za sve tabele.
Pogađa samo redove koji se animiraju (<tr class="animiraj">); ostali ostaju bez
delay-a. Mora biti u main.css: HTMX navigacija (hx-select) odbacuje <head>, pa
stilovi iz page <style> blokova ne bi važili tokom navigacije.
Da promeniš animaciju redova svuda — menjaš samo ovde. */
Animacija se primenjuje direktno na <tr> u .tabela, bez potrebe za .animiraj klasom.
Mora biti u main.css: HTMX navigacija (hx-select) odbacuje <head>, pa
stilovi iz page <style> blokova ne bi važili tokom navigacije. */
.tabela tbody tr {
animation: fadeInUp 0.2s ease backwards;
}
.tabela tbody tr:nth-child(1) { animation-delay: 0.04s; }
.tabela tbody tr:nth-child(2) { animation-delay: 0.08s; }
.tabela tbody tr:nth-child(3) { animation-delay: 0.12s; }
+3 -1
View File
@@ -8,6 +8,7 @@
--tekst-sporedni: #57606a;
--tekst-jak: #1f2328;
--ivica: #d0d7de;
--ivica-jaka: #9ba5b0;
--sb-akcent: #1f6feb;
--sb-akcent-hover: #388bfd;
--sb-aktivan: #ebeef1;
@@ -15,7 +16,8 @@
--upozorenje: #9a6700;
--greska: #cf222e;
--info: #0969da;
--senka: 0 4px 12px rgba(0, 0, 0, 0.08);
--senka: 0 4px 16px rgba(0, 0, 0, 0.12), 0 1px 4px rgba(0, 0, 0, 0.08);
--senka-hover: 0 8px 28px rgba(0, 0, 0, 0.18), 0 2px 8px rgba(0, 0, 0, 0.10);
--sidebar-pozadina: #ffffff;
--poruka-uspeh-bg: rgba(26, 127, 55, 0.1);
--poruka-uspeh-boja: #1a7f37;
+3 -1
View File
@@ -8,6 +8,7 @@
--tekst-sporedni: #a0a8b5;
--tekst-jak: #f0f3f6;
--ivica: #353a44;
--ivica-jaka: #5a6070;
--sb-akcent: #4684d6;
--sb-akcent-hover: #5a96e6;
--sb-aktivan: #2a2f37;
@@ -15,7 +16,8 @@
--upozorenje: #e1b04a;
--greska: #cf5757;
--info: #5cb1d6;
--senka: 0 4px 12px rgba(0, 0, 0, 0.4);
--senka: 0 4px 16px rgba(0, 0, 0, 0.55), 0 1px 4px rgba(0, 0, 0, 0.35);
--senka-hover: 0 8px 28px rgba(0, 0, 0, 0.7), 0 2px 8px rgba(0, 0, 0, 0.45);
--sidebar-pozadina: #1a1c20;
--poruka-uspeh-bg: rgba(93, 184, 118, 0.15);
--poruka-uspeh-boja: #5db876;
+8 -3
View File
@@ -187,19 +187,19 @@
{{if index .Dozvole "podesavanja.pregled"}}
<div>
<button type="button" data-podmeni-dugme
class="nav-stavka {{if or (eq .Stranica "podesavanja") (eq .Stranica "podesavanja-opste") (eq .Stranica "podesavanja-izgled") (eq .Stranica "podesavanja-sistem") (eq .Stranica "podesavanja-kalkulacija-pdv") (eq .Stranica "dozvole")}}aktivan{{end}}"
class="nav-stavka {{if or (eq .Stranica "podesavanja") (eq .Stranica "podesavanja-opste") (eq .Stranica "podesavanja-izgled") (eq .Stranica "podesavanja-sistem") (eq .Stranica "podesavanja-kalkulacija-pdv") (eq .Stranica "podesavanja-servis") (eq .Stranica "dozvole")}}aktivan{{end}}"
style="width:100%;background:none;border:none;cursor:pointer;">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06-.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
<span>Podešavanja</span>
<span class="nav-strelica">
<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"
style="transition:transform 0.2s;transform:{{if or (eq .Stranica "podesavanja") (eq .Stranica "podesavanja-opste") (eq .Stranica "podesavanja-izgled") (eq .Stranica "podesavanja-sistem") (eq .Stranica "podesavanja-kalkulacija-pdv") (eq .Stranica "dozvole")}}rotate(180deg){{else}}rotate(0deg){{end}}">
style="transition:transform 0.2s;transform:{{if or (eq .Stranica "podesavanja") (eq .Stranica "podesavanja-opste") (eq .Stranica "podesavanja-izgled") (eq .Stranica "podesavanja-sistem") (eq .Stranica "podesavanja-kalkulacija-pdv") (eq .Stranica "podesavanja-servis") (eq .Stranica "dozvole")}}rotate(180deg){{else}}rotate(0deg){{end}}">
<polyline points="6 9 12 15 18 9"/>
</svg>
</span>
<span class="nav-tooltip">Podešavanja</span>
</button>
<div class="nav-podmeni {{if or (eq .Stranica "podesavanja") (eq .Stranica "podesavanja-opste") (eq .Stranica "podesavanja-izgled") (eq .Stranica "podesavanja-sistem") (eq .Stranica "podesavanja-kalkulacija-pdv") (eq .Stranica "dozvole")}}otvoren{{end}}">
<div class="nav-podmeni {{if or (eq .Stranica "podesavanja") (eq .Stranica "podesavanja-opste") (eq .Stranica "podesavanja-izgled") (eq .Stranica "podesavanja-sistem") (eq .Stranica "podesavanja-kalkulacija-pdv") (eq .Stranica "podesavanja-servis") (eq .Stranica "dozvole")}}otvoren{{end}}">
<a href="/admin/podesavanja/opste" class="nav-stavka nav-podstavka {{if eq .Stranica "podesavanja-opste"}}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="M3 21h18"/><path d="M5 21V7a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v14"/><path d="M9 21v-5h6v5"/><path d="M9 9h.01M15 9h.01M9 13h.01M15 13h.01"/></svg>
<span>Opšte</span>
@@ -220,6 +220,11 @@
<span>Kalkulacija i PDV</span>
<span class="nav-tooltip">Kalkulacija i PDV</span>
</a>
<a href="/admin/podesavanja/servis" class="nav-stavka nav-podstavka {{if eq .Stranica "podesavanja-servis"}}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="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>
<span>Servis</span>
<span class="nav-tooltip">Servis</span>
</a>
{{if or (eq .KorisnikUloga "superadmin") (eq .KorisnikUloga "admin")}}
<a href="/admin/dozvole" class="nav-stavka nav-podstavka {{if eq .Stranica "dozvole"}}aktivan{{end}}">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
+2 -8
View File
@@ -6,12 +6,6 @@
<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; }
@@ -34,9 +28,9 @@
<div class="izv-naslov" style="margin-bottom:0;">Mesečni prihod — poslednjih 12 meseci</div>
<div class="toggle-red" style="margin-bottom:0;">
<span class="pomocni-tekst">Grafikon</span>
<label class="toggle-switch">
<label class="toggl">
<input type="checkbox" id="toggle-grafikon" checked>
<span class="toggle-slider"></span>
<span class="toggl-klizac"></span>
</label>
</div>
</div>
+1 -1
View File
@@ -24,7 +24,7 @@
<!-- istorija nivelacija -->
<div class="kartica animiraj" style="padding:0;overflow:hidden;">
<div style="overflow-x:auto;">
<table style="width:100%;border-collapse:collapse;font-size:13px;min-width:760px;">
<table class="tabela" style="width:100%;border-collapse:collapse;font-size:13px;min-width:760px;">
<thead>
<tr style="text-align:left;color:var(--tekst-sporedni);border-bottom:0.5px solid var(--ivica);">
<th style="padding:10px 12px;">Datum</th>
+1 -1
View File
@@ -27,7 +27,7 @@
<!-- knjiga -->
<div class="kartica animiraj" style="padding:0;overflow:hidden;">
<div style="overflow-x:auto;">
<table style="width:100%;border-collapse:collapse;font-size:13px;min-width:900px;">
<table class="tabela" style="width:100%;border-collapse:collapse;font-size:13px;min-width:900px;">
<thead>
<tr style="text-align:left;color:var(--tekst-sporedni);border-bottom:0.5px solid var(--ivica);">
<th style="padding:10px 12px;">Datum prometa</th>
+1 -1
View File
@@ -27,7 +27,7 @@
<!-- knjiga -->
<div class="kartica animiraj" style="padding:0;overflow:hidden;">
<div style="overflow-x:auto;">
<table style="width:100%;border-collapse:collapse;font-size:13px;min-width:980px;">
<table class="tabela" style="width:100%;border-collapse:collapse;font-size:13px;min-width:980px;">
<thead>
<tr style="text-align:left;color:var(--tekst-sporedni);border-bottom:0.5px solid var(--ivica);">
<th style="padding:10px 12px;">Datum prometa</th>
+2 -2
View File
@@ -23,7 +23,7 @@
<!-- obračun po stopama -->
<div class="kartica animiraj" style="padding:0;overflow:hidden;margin-bottom:16px;">
<div style="overflow-x:auto;">
<table style="width:100%;border-collapse:collapse;font-size:13px;min-width:560px;">
<table class="tabela" style="width:100%;border-collapse:collapse;font-size:13px;min-width:560px;">
<thead>
<tr style="text-align:left;color:var(--tekst-sporedni);border-bottom:0.5px solid var(--ivica);">
<th style="padding:10px 12px;"></th>
@@ -110,7 +110,7 @@
</div>
</div>
<div style="overflow-x:auto;margin-top:12px;">
<table style="width:100%;border-collapse:collapse;font-size:13px;min-width:560px;">
<table class="tabela" style="width:100%;border-collapse:collapse;font-size:13px;min-width:560px;">
<thead>
<tr style="text-align:left;color:var(--tekst-sporedni);border-bottom:0.5px solid var(--ivica);">
<th style="padding:10px 12px;width:48px;">Polje</th>
@@ -0,0 +1,45 @@
{{template "base" .}}
{{define "naslov"}}Podešavanja — Servis — NTech{{end}}
{{define "sadrzaj"}}
<div class="stranica-stack" style="width:100%;max-width:100%;">
{{if .Sacuvano}}
<div class="poruka-uspeh">Podešavanja su uspešno sačuvana.</div>
{{end}}
<form method="POST" action="/podesavanja/sacuvaj">
<input type="hidden" name="_csrf" value="{{.CsrfToken}}">
<input type="hidden" name="_next" value="/admin/podesavanja/servis">
<div class="kartica animiraj">
<div style="display:flex;align-items:center;gap:10px;margin-bottom:16px;padding-bottom:12px;border-bottom:0.5px solid var(--ivica);">
<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"><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>
<span style="font-size:15px;font-weight:500;color:var(--tekst-glavni);">Servis</span>
</div>
<div class="kolona" style="gap:16px;">
<div style="max-width:280px;">
<label for="servis_garancija_meseci" class="polje-labela">
Podrazumevani rok garancije (meseci)
</label>
<input type="number" id="servis_garancija_meseci" name="servis_garancija_meseci"
min="0" max="120" value="{{.ServisGarancijaMeseci}}"
style="width:100%;">
<div class="pomocni-tekst" style="margin-top:6px;">
Automatski se upisuje pri prijemu uređaja. Vrednost 0 znači bez garancije.
</div>
</div>
</div>
<div style="display:flex;justify-content:flex-end;margin-top:20px;">
<button type="submit" class="btn-primarno">Sačuvaj</button>
</div>
</div>
</form>
</div>
{{end}}
+145
View File
@@ -74,6 +74,104 @@
{{end}}
</div>
<!-- kartica: animacije -->
<div class="kartica animiraj" style="margin-bottom:16px;">
<div style="display:flex;align-items:center;gap:10px;margin-bottom:16px;padding-bottom:12px;border-bottom:0.5px solid var(--ivica);">
<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"><path d="M5 12s2.545-5 7-5c4.454 0 7 5 7 5s-2.546 5-7 5c-4.455 0-7-5-7-5z"/><circle cx="12" cy="12" r="3"/></svg>
<span style="font-size:15px;font-weight:500;color:var(--tekst-glavni);">Animacije tabela</span>
</div>
<form method="POST" action="/profil/animacija">
<input type="hidden" name="_csrf" value="{{.CsrfToken}}">
<div class="kolona" style="gap:16px;">
<div style="max-width:300px;">
<label class="polje-labela" for="anim-select">Vrsta animacije pri učitavanju</label>
<select id="anim-select" name="lokalna_animacija" style="width:100%;" onchange="animPreview(this.value)"><!-- preview se primenjuje na wrapper, ne na body -->
<option value="" {{if eq .LokalnaAnimacija ""}}selected{{end}}>Podrazumevano (klizanje gore)</option>
<option value="bez" {{if eq .LokalnaAnimacija "bez"}}selected{{end}}>Bez animacije</option>
<option value="fadeInUp" {{if eq .LokalnaAnimacija "fadeInUp"}}selected{{end}}>Klizanje gore (fadeInUp)</option>
<option value="fadeIn" {{if eq .LokalnaAnimacija "fadeIn"}}selected{{end}}>Pojavljivanje (fadeIn)</option>
<option value="scaleIn" {{if eq .LokalnaAnimacija "scaleIn"}}selected{{end}}>Zumiranje (scaleIn)</option>
<option value="slideLeft" {{if eq .LokalnaAnimacija "slideLeft"}}selected{{end}}>Klizanje s leva (slideLeft)</option>
</select>
</div>
<!-- preview -->
<div>
<div class="pomocni-tekst" style="margin-bottom:8px;">Pregled:</div>
<!-- preview wrapper nosi data-animacija atribut; isti CSS [data-animacija] .animiraj
koji radi globalno na body radi i ovde, ali izolovano — pogađa SAMO redove unutar wrappera -->
<div id="anim-preview-wrap" style="border:0.5px solid var(--ivica);border-radius:8px;overflow:hidden;max-width:340px;">
<table style="width:100%;border-collapse:collapse;">
<tbody id="anim-preview-body">
<tr class="animiraj" style="border-bottom:0.5px solid var(--ivica);"><td style="padding:8px 12px;font-size:13px;color:var(--tekst-glavni);">Laptop HP 840</td><td style="padding:8px 12px;text-align:right;font-size:13px;color:var(--tekst-sporedni);">120.000 din</td></tr>
<tr class="animiraj" style="border-bottom:0.5px solid var(--ivica);animation-delay:0.08s;"><td style="padding:8px 12px;font-size:13px;color:var(--tekst-glavni);">iPhone 14 Pro</td><td style="padding:8px 12px;text-align:right;font-size:13px;color:var(--tekst-sporedni);">95.000 din</td></tr>
<tr class="animiraj" style="animation-delay:0.16s;"><td style="padding:8px 12px;font-size:13px;color:var(--tekst-glavni);">Samsung S24</td><td style="padding:8px 12px;text-align:right;font-size:13px;color:var(--tekst-sporedni);">80.000 din</td></tr>
</tbody>
</table>
</div>
<button type="button" onclick="animPreviewPonovi()"
style="margin-top:8px;padding:6px 14px;background:var(--pozadina);border:0.5px solid var(--ivica);border-radius:8px;font-size:12px;color:var(--tekst-sporedni);cursor:pointer;">
Ponovi pregled
</button>
</div>
<div>
<button type="submit" class="btn-primarno">Sačuvaj</button>
</div>
</div>
</form>
</div>
<!-- kartica: hover efekat -->
<div class="kartica animiraj" style="margin-bottom:16px;">
<div style="display:flex;align-items:center;gap:10px;margin-bottom:16px;padding-bottom:12px;border-bottom:0.5px solid var(--ivica);">
<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"><path d="M5 3l14 9-7 1-4 7z"/></svg>
<span style="font-size:15px;font-weight:500;color:var(--tekst-glavni);">Hover efekat kartica</span>
</div>
<form method="POST" action="/profil/hover">
<input type="hidden" name="_csrf" value="{{.CsrfToken}}">
<div class="kolona" style="gap:16px;">
<div style="max-width:300px;">
<label class="polje-labela" for="hover-select">Efekat pri prelasku mišem</label>
<select id="hover-select" name="lokalni_hover" style="width:100%;" onchange="hoverPreview(this.value)">
<option value="" {{if eq .LokalniHover ""}}selected{{end}}>Podrazumevano (senka + ivica)</option>
<option value="bez" {{if eq .LokalniHover "bez"}}selected{{end}}>Bez efekta</option>
<option value="podizanje" {{if eq .LokalniHover "podizanje"}}selected{{end}}>Podizanje (lift)</option>
<option value="svetlost" {{if eq .LokalniHover "svetlost"}}selected{{end}}>Svetlost ivice (akcent)</option>
<option value="zoom" {{if eq .LokalniHover "zoom"}}selected{{end}}>Zoom (uvećanje)</option>
<option value="boja" {{if eq .LokalniHover "boja"}}selected{{end}}>Boja pozadine (akcent)</option>
</select>
</div>
<!-- preview -->
<div>
<div class="pomocni-tekst" style="margin-bottom:8px;">Pregled — pređi mišem:</div>
<div id="hover-preview-wrap" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:10px;max-width:380px;">
<div id="hprev1" class="kartica" style="padding:12px;cursor:default;min-height:64px;display:flex;flex-direction:column;gap:4px;">
<div style="font-size:11px;color:var(--tekst-sporedni);">Artikli</div>
<div style="font-size:18px;font-weight:600;color:var(--tekst-glavni);">1.284</div>
</div>
<div id="hprev2" class="kartica" style="padding:12px;cursor:default;min-height:64px;display:flex;flex-direction:column;gap:4px;">
<div style="font-size:11px;color:var(--tekst-sporedni);">Servis</div>
<div style="font-size:18px;font-weight:600;color:var(--tekst-glavni);">47</div>
</div>
<div id="hprev3" class="kartica" style="padding:12px;cursor:default;min-height:64px;display:flex;flex-direction:column;gap:4px;">
<div style="font-size:11px;color:var(--tekst-sporedni);">Prihod</div>
<div style="font-size:18px;font-weight:600;color:var(--tekst-glavni);">+12%</div>
</div>
</div>
<div class="pomocni-tekst" style="margin-top:6px;font-size:11px;">Efekat se primenjuje odmah pri odabiru.</div>
</div>
<div>
<button type="submit" class="btn-primarno">Sačuvaj</button>
</div>
</div>
</form>
</div>
<!-- kartica: moj avatar -->
<div class="kartica animiraj" style="margin-bottom:16px;">
<div style="display:flex;align-items:center;gap:10px;margin-bottom:16px;padding-bottom:12px;border-bottom:0.5px solid var(--ivica);">
@@ -255,4 +353,51 @@
{{end}}
</div>
<script>
function hoverPreview(val) {
var wrap = document.getElementById('hover-preview-wrap');
if (!wrap) return;
if (val === '') {
wrap.removeAttribute('data-hover');
} else {
wrap.setAttribute('data-hover', val);
}
}
// inicijalizuj preview na osnovu trenutnog odabira pri učitavanju
(function() {
var sel = document.getElementById('hover-select');
if (sel) hoverPreview(sel.value);
})();
// mapiranje vrednosti dropdowna na vrednost data-animacija atributa.
// prazna vrednost ("Podrazumevano") odgovara fadeInUp — istom podrazumevanom stilu.
var animVrednosti = {
'': 'fadeInUp',
'bez': 'bez',
'fadeInUp': 'fadeInUp',
'fadeIn': 'fadeIn',
'scaleIn': 'scaleIn',
'slideLeft': 'slideLeft'
};
// postavlja data-animacija na PREVIEW wrapper (ne na body), pa CSS
// [data-animacija] .animiraj radi izolovano — samo nad redovima preview tabele.
function animPreview(val) {
var wrap = document.getElementById('anim-preview-wrap');
if (!wrap) return;
var anim = animVrednosti[val] || 'fadeInUp';
// restartuj animaciju: skini atribut, izazovi reflow, pa ga vrati
wrap.removeAttribute('data-animacija');
void wrap.offsetHeight; // reflow da bi se animacija ponovo okinula
wrap.setAttribute('data-animacija', anim);
}
// "Ponovi pregled" — ponovo okida animaciju za trenutno izabrani stil
function animPreviewPonovi() {
animPreview(document.getElementById('anim-select').value);
}
// inicijalizuj preview na osnovu sačuvane preferencije pri učitavanju stranice
(function() {
var sel = document.getElementById('anim-select');
if (sel) animPreview(sel.value);
})();
</script>
{{end}}
@@ -103,6 +103,28 @@
<div style="font-size:12px;color:var(--tekst-sporedni);margin-bottom:6px;">Opis kvara</div>
<div style="font-size:14px;color:var(--tekst-glavni);line-height:1.6;white-space:pre-wrap;">{{.Nalog.OpisKvara}}</div>
</div>
{{if or .Nalog.Ostecenja .Nalog.PinUredjaja .Nalog.Pribor}}
<div style="display:grid;grid-template-columns:repeat(auto-fit, minmax(160px, 1fr));gap:16px;">
{{if .Nalog.Ostecenja}}
<div>
<div style="font-size:12px;color:var(--tekst-sporedni);margin-bottom:4px;">Oštećenja pri prijemu</div>
<div style="font-size:14px;color:var(--tekst-glavni);">{{.Nalog.Ostecenja}}</div>
</div>
{{end}}
{{if .Nalog.PinUredjaja}}
<div>
<div style="font-size:12px;color:var(--tekst-sporedni);margin-bottom:4px;">PIN / lozinka uređaja</div>
<div style="font-size:14px;color:var(--tekst-glavni);font-family:monospace;">{{.Nalog.PinUredjaja}}</div>
</div>
{{end}}
{{if .Nalog.Pribor}}
<div>
<div style="font-size:12px;color:var(--tekst-sporedni);margin-bottom:4px;">Pribor i oprema</div>
<div style="font-size:14px;color:var(--tekst-glavni);">{{.Nalog.Pribor}}</div>
</div>
{{end}}
</div>
{{end}}
{{if .Nalog.Napomena}}
<div>
<div style="font-size:12px;color:var(--tekst-sporedni);margin-bottom:6px;">Napomena</div>
+69 -12
View File
@@ -12,11 +12,11 @@
</a>
<div class="kartica forma-kartica animiraj">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;padding-bottom:14px;border-bottom:0.5px solid var(--ivica);flex-wrap:wrap;gap:10px;">
<span style="font-size:16px;font-weight:500;color:var(--tekst-glavni);">
<div style="display:flex;justify-content:space-between;align-items:center;margin:-16px -16px 20px -16px;padding:12px 16px;background:var(--pozadina);border-radius:12px 12px 0 0;flex-wrap:wrap;gap:10px;">
<span style="font-size:15px;font-weight:600;color:var(--tekst-glavni);">
{{if .Izmena}}Izmeni nalog{{else}}Novi nalog{{end}}
</span>
<span style="font-size:14px;font-weight:500;color:var(--tekst-sporedni);font-family:monospace;">
<span style="font-size:13px;font-weight:500;color:var(--tekst-sporedni);font-family:monospace;">
{{.Nalog.BrojNaloga}}
</span>
</div>
@@ -60,6 +60,26 @@
placeholder="Opišite problem koji je klijent prijavio..."
style="width:100%;resize:vertical;">{{.Nalog.OpisKvara}}</textarea>
</div>
<div class="forma-grid-2" style="display:grid;grid-template-columns:1fr 1fr;gap:12px;">
<div>
<label class="polje-labela">Oštećenja pri prijemu</label>
<input type="text" name="ostecenja" value="{{.Nalog.Ostecenja}}"
placeholder="npr. ogrebotina na ekranu"
style="width:100%;">
</div>
<div>
<label class="polje-labela">PIN / lozinka uređaja</label>
<input type="text" name="pin_uredjaja" value="{{.Nalog.PinUredjaja}}"
placeholder="npr. 1234"
style="width:100%;">
</div>
</div>
<div>
<label class="polje-labela">Pribor i oprema</label>
<input type="text" name="pribor" value="{{.Nalog.Pribor}}"
placeholder="npr. punjač, torbica, miš"
style="width:100%;">
</div>
</div>
</div>
@@ -97,8 +117,8 @@
<!-- status i datumi -->
<div>
<div class="sekcija-naslov">Status i datumi</div>
<div class="forma-grid-4" style="display:grid;grid-template-columns:1fr 1fr 1fr 1fr;gap:12px;">
<div style="grid-column:span 2;">
<div class="kolona" style="gap:12px;">
<div>
<label class="polje-labela">Status naloga</label>
<select name="status" style="width:100%;">
{{range .SviStatusi}}
@@ -106,17 +126,38 @@
{{end}}
</select>
</div>
<div>
<label class="polje-labela">Datum završetka</label>
<input type="date" name="datum_zavrsetka"
value="{{if .Nalog.DatumZavrsetka}}{{.Nalog.DatumZavrsetka.Format "2006-01-02"}}{{end}}"
style="width:100%;">
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:12px;">
<div>
<label class="polje-labela">Datum prijema</label>
<input type="date" name="datum_prijema"
value="{{.Nalog.DatumPrijema.Format "2006-01-02"}}"
style="width:100%;">
</div>
<div>
<label class="polje-labela">Datum završetka</label>
<input type="date" name="datum_zavrsetka"
value="{{if .Nalog.DatumZavrsetka}}{{.Nalog.DatumZavrsetka.Format "2006-01-02"}}{{end}}"
style="width:100%;">
</div>
</div>
<div>
<label class="polje-labela">Garancija do</label>
<input type="date" name="garancija_do"
<input type="date" name="garancija_do" id="garancija_do_input"
value="{{if .Nalog.GarancijaDo}}{{.Nalog.GarancijaDo.Format "2006-01-02"}}{{end}}"
style="width:100%;">
{{if not .Nalog.GarancijaDo}}disabled{{end}}
style="width:100%;{{if not .Nalog.GarancijaDo}}opacity:0.4;{{end}}">
</div>
<!-- svič bez garancije -->
<div style="display:flex;align-items:center;gap:10px;">
<label class="toggl" style="flex-shrink:0;">
<input type="checkbox" id="bez_garancije_chk"
{{if not .Nalog.GarancijaDo}}checked{{end}}
onchange="toggleGarancija(this)">
<span class="toggl-klizac"></span>
</label>
<input type="hidden" name="bez_garancije" id="bez_garancije_val"
value="{{if not .Nalog.GarancijaDo}}1{{else}}0{{end}}">
<span style="font-size:13px;color:var(--tekst-sporedni);">Bez garancije</span>
</div>
</div>
</div>
@@ -172,4 +213,20 @@
</form>
</div>
</div>
<script>
function toggleGarancija(chk) {
var input = document.getElementById('garancija_do_input');
var hidden = document.getElementById('bez_garancije_val');
if (chk.checked) {
input.value = '';
input.disabled = true;
input.style.opacity = '0.4';
hidden.value = '1';
} else {
input.disabled = false;
input.style.opacity = '1';
hidden.value = '0';
}
}
</script>
{{end}}
+1 -1
View File
@@ -106,7 +106,7 @@
</script>
{{end}}
</head>
<body>
<body{{if .LokalnaAnimacija}} data-animacija="{{.LokalnaAnimacija}}"{{end}}{{if .LokalniHover}} data-hover="{{.LokalniHover}}"{{end}}>
<div class="raspored">
<div class="sidebar-overlay" id="sidebar-overlay"></div>
{{template "sidebar" .}}