Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
f29e76612e
|
|||
|
b417ff6d02
|
@@ -1,108 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# ──────────────────────────────────────────────
|
|
||||||
# Verzija
|
|
||||||
# ──────────────────────────────────────────────
|
|
||||||
read -p "Verzija (npr. 0.1.1): " VERZIJA
|
|
||||||
VERZIJA=${VERZIJA:-"0.0.1"}
|
|
||||||
|
|
||||||
# ──────────────────────────────────────────────
|
|
||||||
# Okruženje
|
|
||||||
# ──────────────────────────────────────────────
|
|
||||||
echo ""
|
|
||||||
echo "Okruženje:"
|
|
||||||
echo " 1) production"
|
|
||||||
echo " 2) development"
|
|
||||||
read -p "Izbor [1/2, podrazumevano 1]: " OKR_IZBOR
|
|
||||||
OKR_IZBOR=${OKR_IZBOR:-1}
|
|
||||||
|
|
||||||
if [ "$OKR_IZBOR" = "2" ]; then
|
|
||||||
OKRUZENJE="development"
|
|
||||||
LDFLAGS="-X main.Verzija=dev-${VERZIJA}"
|
|
||||||
NAZIV="ntech-dev"
|
|
||||||
else
|
|
||||||
OKRUZENJE="production"
|
|
||||||
LDFLAGS="-X main.Verzija=${VERZIJA} -s -w"
|
|
||||||
NAZIV="ntech"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ──────────────────────────────────────────────
|
|
||||||
# Ciljni OS
|
|
||||||
# ──────────────────────────────────────────────
|
|
||||||
echo ""
|
|
||||||
echo "Ciljni OS:"
|
|
||||||
echo " 1) Linux (amd64)"
|
|
||||||
echo " 2) Windows (amd64)"
|
|
||||||
read -p "Izbor [1/2, podrazumevano 1]: " OS_IZBOR
|
|
||||||
OS_IZBOR=${OS_IZBOR:-1}
|
|
||||||
|
|
||||||
if [ "$OS_IZBOR" = "2" ]; then
|
|
||||||
GOOS_VAL="windows"
|
|
||||||
NAZIV="${NAZIV}.exe"
|
|
||||||
else
|
|
||||||
GOOS_VAL="linux"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ──────────────────────────────────────────────
|
|
||||||
# UPX kompresija
|
|
||||||
# ──────────────────────────────────────────────
|
|
||||||
echo ""
|
|
||||||
UPX_DOSTUPAN=false
|
|
||||||
if command -v upx &>/dev/null; then
|
|
||||||
UPX_DOSTUPAN=true
|
|
||||||
read -p "Kompresovati UPX-om? [d/N]: " UPX_IZBOR
|
|
||||||
else
|
|
||||||
echo "UPX nije instaliran — kompresija preskočena."
|
|
||||||
UPX_IZBOR="n"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ──────────────────────────────────────────────
|
|
||||||
# Sažetak pre builda
|
|
||||||
# ──────────────────────────────────────────────
|
|
||||||
echo ""
|
|
||||||
echo "──────────────────────────────────────────"
|
|
||||||
echo " Okruženje : ${OKRUZENJE}"
|
|
||||||
echo " Verzija : ${VERZIJA}"
|
|
||||||
echo " OS : ${GOOS_VAL}/amd64"
|
|
||||||
echo " Izlaz : ${NAZIV}"
|
|
||||||
if [ "$UPX_DOSTUPAN" = true ] && [[ "$UPX_IZBOR" =~ ^[dDyY] ]]; then
|
|
||||||
echo " UPX : da"
|
|
||||||
else
|
|
||||||
echo " UPX : ne"
|
|
||||||
fi
|
|
||||||
echo "──────────────────────────────────────────"
|
|
||||||
echo ""
|
|
||||||
read -p "Pokrenuti build? [D/n]: " POTVRDA
|
|
||||||
POTVRDA=${POTVRDA:-"d"}
|
|
||||||
if [[ ! "$POTVRDA" =~ ^[dDyY] ]]; then
|
|
||||||
echo "Build otkazan."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ──────────────────────────────────────────────
|
|
||||||
# Build
|
|
||||||
# ──────────────────────────────────────────────
|
|
||||||
echo ""
|
|
||||||
echo "Buildovanje..."
|
|
||||||
CGO_ENABLED=0 GOARCH=amd64 GOOS=${GOOS_VAL} go build \
|
|
||||||
-ldflags "${LDFLAGS}" \
|
|
||||||
-o "${NAZIV}" \
|
|
||||||
./cmd/ntech
|
|
||||||
|
|
||||||
echo "Build završen: ${NAZIV}"
|
|
||||||
ls -lh "${NAZIV}"
|
|
||||||
|
|
||||||
# ──────────────────────────────────────────────
|
|
||||||
# UPX
|
|
||||||
# ──────────────────────────────────────────────
|
|
||||||
if [ "$UPX_DOSTUPAN" = true ] && [[ "$UPX_IZBOR" =~ ^[dDyY] ]]; then
|
|
||||||
echo ""
|
|
||||||
echo "Kompresovanje sa UPX..."
|
|
||||||
upx --best "${NAZIV}"
|
|
||||||
echo "Nakon kompresije:"
|
|
||||||
ls -lh "${NAZIV}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Gotovo."
|
|
||||||
@@ -247,6 +247,7 @@ func main() {
|
|||||||
r.Get("/admin/podesavanja/opste", h.PodesavanjaOpste)
|
r.Get("/admin/podesavanja/opste", h.PodesavanjaOpste)
|
||||||
r.Get("/admin/podesavanja/izgled", h.PodesavanjaIzgled)
|
r.Get("/admin/podesavanja/izgled", h.PodesavanjaIzgled)
|
||||||
r.Get("/admin/podesavanja/sistem", h.PodesavanjaSistem)
|
r.Get("/admin/podesavanja/sistem", h.PodesavanjaSistem)
|
||||||
|
r.Get("/admin/podesavanja/servis", h.PodesavanjaServis)
|
||||||
r.Get("/admin/podesavanja/kalkulacija-pdv", h.PdvStope)
|
r.Get("/admin/podesavanja/kalkulacija-pdv", h.PdvStope)
|
||||||
r.With(doz("podesavanja.izmeni")).Post("/podesavanja/pdv-stope/dodaj", h.DodajPdvStopu)
|
r.With(doz("podesavanja.izmeni")).Post("/podesavanja/pdv-stope/dodaj", h.DodajPdvStopu)
|
||||||
r.With(doz("podesavanja.izmeni")).Post("/podesavanja/pdv-stope/{id}/izmeni", h.IzmeniPdvStopu)
|
r.With(doz("podesavanja.izmeni")).Post("/podesavanja/pdv-stope/{id}/izmeni", h.IzmeniPdvStopu)
|
||||||
@@ -356,6 +357,8 @@ func main() {
|
|||||||
r.Post("/admin/profil/totp/deaktiviraj", h.AdminTotpDeaktivacija)
|
r.Post("/admin/profil/totp/deaktiviraj", h.AdminTotpDeaktivacija)
|
||||||
r.Post("/admin/profil/totp/kodovi", h.AdminTotpRegenerisiKodove)
|
r.Post("/admin/profil/totp/kodovi", h.AdminTotpRegenerisiKodove)
|
||||||
r.With(doz("tema.lokalno")).Post("/profil/tema", h.SacuvajLokalnuTemu)
|
r.With(doz("tema.lokalno")).Post("/profil/tema", h.SacuvajLokalnuTemu)
|
||||||
|
r.With(doz("tema.lokalno")).Post("/profil/animacija", h.SacuvajLokalnuAnimaciju)
|
||||||
|
r.With(doz("tema.lokalno")).Post("/profil/hover", h.SacuvajLokalniHover)
|
||||||
r.Get("/profil/tema", h.ProfilTema)
|
r.Get("/profil/tema", h.ProfilTema)
|
||||||
r.With(doz("tema.lokalno")).Post("/profil/pozadina", h.ProfilOtpremiPozadinu)
|
r.With(doz("tema.lokalno")).Post("/profil/pozadina", h.ProfilOtpremiPozadinu)
|
||||||
r.With(doz("tema.lokalno")).Post("/profil/pozadina/ukloni", h.ProfilUkloniPozadinu)
|
r.With(doz("tema.lokalno")).Post("/profil/pozadina/ukloni", h.ProfilUkloniPozadinu)
|
||||||
|
|||||||
@@ -12,12 +12,26 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
github.com/boombuler/barcode v1.1.0 // indirect
|
||||||
|
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
|
github.com/f-amaral/go-async v0.3.0 // indirect
|
||||||
|
github.com/hhrutter/lzw v1.0.0 // indirect
|
||||||
|
github.com/hhrutter/pkcs7 v0.2.0 // indirect
|
||||||
|
github.com/hhrutter/tiff v1.0.2 // indirect
|
||||||
|
github.com/johnfercher/go-tree v1.1.0 // indirect
|
||||||
|
github.com/johnfercher/maroto/v2 v2.4.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/mattn/go-runewidth v0.0.21 // indirect
|
||||||
github.com/ncruces/go-strftime v1.0.0 // indirect
|
github.com/ncruces/go-strftime v1.0.0 // indirect
|
||||||
|
github.com/pdfcpu/pdfcpu v0.11.1 // indirect
|
||||||
|
github.com/phpdave11/gofpdf v1.4.3 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
|
golang.org/x/image v0.37.0 // indirect
|
||||||
golang.org/x/sys v0.45.0 // indirect
|
golang.org/x/sys v0.45.0 // indirect
|
||||||
|
golang.org/x/text v0.37.0 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
modernc.org/libc v1.72.3 // indirect
|
modernc.org/libc v1.72.3 // indirect
|
||||||
modernc.org/mathutil v1.7.1 // indirect
|
modernc.org/mathutil v1.7.1 // indirect
|
||||||
modernc.org/memory v1.11.0 // indirect
|
modernc.org/memory v1.11.0 // indirect
|
||||||
|
|||||||
@@ -1,9 +1,17 @@
|
|||||||
|
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
|
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
|
||||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||||
|
github.com/boombuler/barcode v1.1.0 h1:ChaYjBR63fr4LFyGn8E8nt7dBSt3MiU3zMOZqFvVkHo=
|
||||||
|
github.com/boombuler/barcode v1.1.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||||
|
github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
|
||||||
|
github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
|
||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
|
github.com/f-amaral/go-async v0.3.0 h1:h4kLsX7aKfdWaHvV0lf+/EE3OIeCzyeDYJDb/vDZUyg=
|
||||||
|
github.com/f-amaral/go-async v0.3.0/go.mod h1:Hz5Qr6DAWpbTTUjytnrg1WIsDgS7NtOei5y8SipYS7U=
|
||||||
github.com/go-chi/chi/v5 v5.3.0 h1:halUjDxhshgXHMrao5bB8eNBXo/rnzwr8m5m36glehM=
|
github.com/go-chi/chi/v5 v5.3.0 h1:halUjDxhshgXHMrao5bB8eNBXo/rnzwr8m5m36glehM=
|
||||||
github.com/go-chi/chi/v5 v5.3.0/go.mod h1:R+tYY2hNuVUUjxoPtqUdgBqevM9s9njzkTLutVsOCto=
|
github.com/go-chi/chi/v5 v5.3.0/go.mod h1:R+tYY2hNuVUUjxoPtqUdgBqevM9s9njzkTLutVsOCto=
|
||||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
|
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
|
||||||
@@ -12,23 +20,50 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
|||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||||
|
github.com/hhrutter/lzw v1.0.0 h1:laL89Llp86W3rRs83LvKbwYRx6INE8gDn0XNb1oXtm0=
|
||||||
|
github.com/hhrutter/lzw v1.0.0/go.mod h1:2HC6DJSn/n6iAZfgM3Pg+cP1KxeWc3ezG8bBqW5+WEo=
|
||||||
|
github.com/hhrutter/pkcs7 v0.2.0 h1:i4HN2XMbGQpZRnKBLsUwO3dSckzgX142TNqY/KfXg+I=
|
||||||
|
github.com/hhrutter/pkcs7 v0.2.0/go.mod h1:aEzKz0+ZAlz7YaEMY47jDHL14hVWD6iXt0AgqgAvWgE=
|
||||||
|
github.com/hhrutter/tiff v1.0.2 h1:7H3FQQpKu/i5WaSChoD1nnJbGx4MxU5TlNqqpxw55z8=
|
||||||
|
github.com/hhrutter/tiff v1.0.2/go.mod h1:pcOeuK5loFUE7Y/WnzGw20YxUdnqjY1P0Jlcieb/cCw=
|
||||||
|
github.com/johnfercher/go-tree v1.1.0 h1:L0Fs5jLR1uA2e/CwfHjNdO/Lt4IGQ46QgxarAC1yeXs=
|
||||||
|
github.com/johnfercher/go-tree v1.1.0/go.mod h1:DUO6QkXIFh1K7jeGBIkLCZaeUgnkdQAsB64FDSoHswg=
|
||||||
|
github.com/johnfercher/maroto/v2 v2.4.0 h1:Nc/jA2RCZvNZESrQj41HJOgtkwmerSHd5FUbP4dRrIE=
|
||||||
|
github.com/johnfercher/maroto/v2 v2.4.0/go.mod h1:Nnxa3g4f+vzdx/u/dUgx/52HnrCOCt5QBPSdeSlkFZQ=
|
||||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
|
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mattn/go-runewidth v0.0.21 h1:jJKAZiQH+2mIinzCJIaIG9Be1+0NR+5sz/lYEEjdM8w=
|
||||||
|
github.com/mattn/go-runewidth v0.0.21/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||||
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
|
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
|
||||||
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||||
|
github.com/pdfcpu/pdfcpu v0.11.1 h1:htHBSkGH5jMKWC6e0sihBFbcKZ8vG1M67c8/dJxhjas=
|
||||||
|
github.com/pdfcpu/pdfcpu v0.11.1/go.mod h1:pP3aGga7pRvwFWAm9WwFvo+V68DfANi9kxSQYioNYcw=
|
||||||
|
github.com/phpdave11/gofpdf v1.4.3 h1:M/zHvS8FO3zh9tUd2RCOPEjyuVcs281FCyF22Qlz/IA=
|
||||||
|
github.com/phpdave11/gofpdf v1.4.3/go.mod h1:MAwzoUIgD3J55u0rxIG2eu37c+XWhBtXSpPAhnQXf/o=
|
||||||
|
github.com/phpdave11/gofpdi v1.0.15/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
|
||||||
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/pquerna/otp v1.5.0 h1:NMMR+WrmaqXU4EzdGJEE1aUUI0AMRzsp96fFFWNPwxs=
|
github.com/pquerna/otp v1.5.0 h1:NMMR+WrmaqXU4EzdGJEE1aUUI0AMRzsp96fFFWNPwxs=
|
||||||
github.com/pquerna/otp v1.5.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
github.com/pquerna/otp v1.5.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
|
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988=
|
golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988=
|
||||||
golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc=
|
golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc=
|
||||||
|
golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
golang.org/x/image v0.37.0 h1:ZiRjArKI8GwxZOoEtUfhrBtaCN+4b/7709dlT6SSnQA=
|
||||||
|
golang.org/x/image v0.37.0/go.mod h1:/3f6vaXC+6CEanU4KJxbcUZyEePbyKbaLoDOe4ehFYY=
|
||||||
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
|
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
|
||||||
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
|
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
|
||||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||||
@@ -36,8 +71,14 @@ golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
|||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
|
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
|
||||||
golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc=
|
||||||
|
golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38=
|
||||||
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
|
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
|
||||||
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
|
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
modernc.org/cc/v4 v4.28.2 h1:3tQ0lf2ADtoby2EtSP+J7IE2SHwEJdP8ioR59wx7XpY=
|
modernc.org/cc/v4 v4.28.2 h1:3tQ0lf2ADtoby2EtSP+J7IE2SHwEJdP8ioR59wx7XpY=
|
||||||
modernc.org/cc/v4 v4.28.2/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI=
|
modernc.org/cc/v4 v4.28.2/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI=
|
||||||
modernc.org/ccgo/v4 v4.34.0 h1:yRLPFZieg532OT4rp4JFNIVcquwalMX26G95WQDqwCQ=
|
modernc.org/ccgo/v4 v4.34.0 h1:yRLPFZieg532OT4rp4JFNIVcquwalMX26G95WQDqwCQ=
|
||||||
|
|||||||
@@ -149,6 +149,8 @@ type KorisniciRepository interface {
|
|||||||
SacuvajTotpTajnu(ctx context.Context, id int64, tajna string) error
|
SacuvajTotpTajnu(ctx context.Context, id int64, tajna string) error
|
||||||
SacuvajLokalnuTemu(ctx context.Context, id int64, lokalnaTema string, koristi bool) error
|
SacuvajLokalnuTemu(ctx context.Context, id int64, lokalnaTema string, koristi bool) error
|
||||||
SacuvajLokalnuPozadinu(ctx context.Context, id int64, pozadina, opacity, blur, blurPozadine, glassOpacity string) error
|
SacuvajLokalnuPozadinu(ctx context.Context, id int64, pozadina, opacity, blur, blurPozadine, glassOpacity string) error
|
||||||
|
SacuvajLokalnuAnimaciju(ctx context.Context, id int64, animacija string) error
|
||||||
|
SacuvajLokalniHover(ctx context.Context, id int64, hover string) error
|
||||||
SacuvajAvatar(ctx context.Context, id int64, putanja string) error
|
SacuvajAvatar(ctx context.Context, id int64, putanja string) error
|
||||||
PostojiIjedan(ctx context.Context) (bool, error)
|
PostojiIjedan(ctx context.Context) (bool, error)
|
||||||
Obrisi(ctx context.Context, id int64) error
|
Obrisi(ctx context.Context, id int64) error
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ type korisnikOpcije struct {
|
|||||||
lokalnaPozadinaBlurPozadine sql.NullString
|
lokalnaPozadinaBlurPozadine sql.NullString
|
||||||
lokalnaPozadinaGlassOpacity sql.NullString
|
lokalnaPozadinaGlassOpacity sql.NullString
|
||||||
avatarPutanja sql.NullString
|
avatarPutanja sql.NullString
|
||||||
|
lokalnaAnimacija sql.NullString
|
||||||
|
lokalniHover sql.NullString
|
||||||
}
|
}
|
||||||
|
|
||||||
// dodeliOpcijeKorisnika prenosi vrednosti iz korisnikOpcije na model.Korisnik
|
// dodeliOpcijeKorisnika prenosi vrednosti iz korisnikOpcije na model.Korisnik
|
||||||
@@ -44,6 +46,8 @@ func dodeliOpcijeKorisnika(k *model.Korisnik, o korisnikOpcije) {
|
|||||||
k.LokalnaPozadinaBlurPozadine = o.lokalnaPozadinaBlurPozadine.String
|
k.LokalnaPozadinaBlurPozadine = o.lokalnaPozadinaBlurPozadine.String
|
||||||
k.LokalnaPozadinaGlassOpacity = o.lokalnaPozadinaGlassOpacity.String
|
k.LokalnaPozadinaGlassOpacity = o.lokalnaPozadinaGlassOpacity.String
|
||||||
k.AvatarPutanja = o.avatarPutanja.String
|
k.AvatarPutanja = o.avatarPutanja.String
|
||||||
|
k.LokalnaAnimacija = o.lokalnaAnimacija.String
|
||||||
|
k.LokalniHover = o.lokalniHover.String
|
||||||
}
|
}
|
||||||
|
|
||||||
// skeniraiKorisnika čita jedan red iz baze i popunjava model.Korisnik
|
// skeniraiKorisnika čita jedan red iz baze i popunjava model.Korisnik
|
||||||
@@ -55,6 +59,7 @@ func skeniraiKorisnika(row interface{ Scan(...any) error }) (*model.Korisnik, er
|
|||||||
&o.lokalnaTema, &o.koristiLokalnuTemu, &o.datumKreiranja,
|
&o.lokalnaTema, &o.koristiLokalnuTemu, &o.datumKreiranja,
|
||||||
&o.lokalnaPozadina, &o.lokalnaPozadinaOpacity, &o.lokalnaPozadinaBlur,
|
&o.lokalnaPozadina, &o.lokalnaPozadinaOpacity, &o.lokalnaPozadinaBlur,
|
||||||
&o.lokalnaPozadinaBlurPozadine, &o.lokalnaPozadinaGlassOpacity, &o.avatarPutanja,
|
&o.lokalnaPozadinaBlurPozadine, &o.lokalnaPozadinaGlassOpacity, &o.avatarPutanja,
|
||||||
|
&o.lokalnaAnimacija, &o.lokalniHover,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -98,7 +103,8 @@ func (r *sqliteKorisniciRepo) DohvatiPoImenu(ctx context.Context, korisnickoIme
|
|||||||
COALESCE(lokalna_tema, ''), koristi_lokalnu_temu, datum_kreiranja,
|
COALESCE(lokalna_tema, ''), koristi_lokalnu_temu, datum_kreiranja,
|
||||||
COALESCE(lokalna_pozadina, ''), COALESCE(lokalna_pozadina_opacity, '50'),
|
COALESCE(lokalna_pozadina, ''), COALESCE(lokalna_pozadina_opacity, '50'),
|
||||||
COALESCE(lokalna_pozadina_blur, '12'), COALESCE(lokalna_pozadina_blur_pozadine, '0'),
|
COALESCE(lokalna_pozadina_blur, '12'), COALESCE(lokalna_pozadina_blur_pozadine, '0'),
|
||||||
COALESCE(lokalna_pozadina_glass_opacity, '10'), COALESCE(avatar_putanja, '')
|
COALESCE(lokalna_pozadina_glass_opacity, '10'), COALESCE(avatar_putanja, ''),
|
||||||
|
COALESCE(lokalna_animacija, ''), COALESCE(lokalni_hover, '')
|
||||||
FROM korisnici WHERE korisnicko_ime = ?`, korisnickoIme)
|
FROM korisnici WHERE korisnicko_ime = ?`, korisnickoIme)
|
||||||
k, err := skeniraiKorisnika(row)
|
k, err := skeniraiKorisnika(row)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -114,7 +120,8 @@ func (r *sqliteKorisniciRepo) DohvatiPoID(ctx context.Context, id int64) (*model
|
|||||||
COALESCE(lokalna_tema, ''), koristi_lokalnu_temu, datum_kreiranja,
|
COALESCE(lokalna_tema, ''), koristi_lokalnu_temu, datum_kreiranja,
|
||||||
COALESCE(lokalna_pozadina, ''), COALESCE(lokalna_pozadina_opacity, '50'),
|
COALESCE(lokalna_pozadina, ''), COALESCE(lokalna_pozadina_opacity, '50'),
|
||||||
COALESCE(lokalna_pozadina_blur, '12'), COALESCE(lokalna_pozadina_blur_pozadine, '0'),
|
COALESCE(lokalna_pozadina_blur, '12'), COALESCE(lokalna_pozadina_blur_pozadine, '0'),
|
||||||
COALESCE(lokalna_pozadina_glass_opacity, '10'), COALESCE(avatar_putanja, '')
|
COALESCE(lokalna_pozadina_glass_opacity, '10'), COALESCE(avatar_putanja, ''),
|
||||||
|
COALESCE(lokalna_animacija, ''), COALESCE(lokalni_hover, '')
|
||||||
FROM korisnici WHERE id = ?`, id)
|
FROM korisnici WHERE id = ?`, id)
|
||||||
k, err := skeniraiKorisnika(row)
|
k, err := skeniraiKorisnika(row)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -130,7 +137,8 @@ func (r *sqliteKorisniciRepo) Lista(ctx context.Context) ([]model.Korisnik, erro
|
|||||||
COALESCE(lokalna_tema, ''), koristi_lokalnu_temu, datum_kreiranja,
|
COALESCE(lokalna_tema, ''), koristi_lokalnu_temu, datum_kreiranja,
|
||||||
COALESCE(lokalna_pozadina, ''), COALESCE(lokalna_pozadina_opacity, '50'),
|
COALESCE(lokalna_pozadina, ''), COALESCE(lokalna_pozadina_opacity, '50'),
|
||||||
COALESCE(lokalna_pozadina_blur, '12'), COALESCE(lokalna_pozadina_blur_pozadine, '0'),
|
COALESCE(lokalna_pozadina_blur, '12'), COALESCE(lokalna_pozadina_blur_pozadine, '0'),
|
||||||
COALESCE(lokalna_pozadina_glass_opacity, '10'), COALESCE(avatar_putanja, '')
|
COALESCE(lokalna_pozadina_glass_opacity, '10'), COALESCE(avatar_putanja, ''),
|
||||||
|
COALESCE(lokalna_animacija, ''), COALESCE(lokalni_hover, '')
|
||||||
FROM korisnici ORDER BY datum_kreiranja ASC`)
|
FROM korisnici ORDER BY datum_kreiranja ASC`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("ntech: korisnici.Lista: %w", err)
|
return nil, fmt.Errorf("ntech: korisnici.Lista: %w", err)
|
||||||
@@ -145,6 +153,7 @@ func (r *sqliteKorisniciRepo) Lista(ctx context.Context) ([]model.Korisnik, erro
|
|||||||
&o.lokalnaTema, &o.koristiLokalnuTemu, &o.datumKreiranja,
|
&o.lokalnaTema, &o.koristiLokalnuTemu, &o.datumKreiranja,
|
||||||
&o.lokalnaPozadina, &o.lokalnaPozadinaOpacity, &o.lokalnaPozadinaBlur,
|
&o.lokalnaPozadina, &o.lokalnaPozadinaOpacity, &o.lokalnaPozadinaBlur,
|
||||||
&o.lokalnaPozadinaBlurPozadine, &o.lokalnaPozadinaGlassOpacity, &o.avatarPutanja,
|
&o.lokalnaPozadinaBlurPozadine, &o.lokalnaPozadinaGlassOpacity, &o.avatarPutanja,
|
||||||
|
&o.lokalnaAnimacija, &o.lokalniHover,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, fmt.Errorf("ntech: korisnici.Lista: %w", err)
|
return nil, fmt.Errorf("ntech: korisnici.Lista: %w", err)
|
||||||
}
|
}
|
||||||
@@ -194,6 +203,32 @@ func (r *sqliteKorisniciRepo) SacuvajLokalnuTemu(ctx context.Context, id int64,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *sqliteKorisniciRepo) SacuvajLokalnuAnimaciju(ctx context.Context, id int64, animacija string) error {
|
||||||
|
var val any
|
||||||
|
if animacija != "" {
|
||||||
|
val = animacija
|
||||||
|
}
|
||||||
|
_, err := r.db.ExecContext(ctx,
|
||||||
|
`UPDATE korisnici SET lokalna_animacija = ? WHERE id = ?`, val, id)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("ntech: korisnici.SacuvajLokalnuAnimaciju: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *sqliteKorisniciRepo) SacuvajLokalniHover(ctx context.Context, id int64, hover string) error {
|
||||||
|
var val any
|
||||||
|
if hover != "" {
|
||||||
|
val = hover
|
||||||
|
}
|
||||||
|
_, err := r.db.ExecContext(ctx,
|
||||||
|
`UPDATE korisnici SET lokalni_hover = ? WHERE id = ?`, val, id)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("ntech: korisnici.SacuvajLokalniHover: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *sqliteKorisniciRepo) AzurirajUlogu(ctx context.Context, id int64, uloga string) error {
|
func (r *sqliteKorisniciRepo) AzurirajUlogu(ctx context.Context, id int64, uloga string) error {
|
||||||
_, err := r.db.ExecContext(ctx, `UPDATE korisnici SET uloga = ? WHERE id = ?`, uloga, id)
|
_, err := r.db.ExecContext(ctx, `UPDATE korisnici SET uloga = ? WHERE id = ?`, uloga, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ func (r *ServisRepo) Lista(ctx context.Context, pretraga, status string) ([]mode
|
|||||||
sn.id, sn.klijent_id, sn.tehnicar_id, sn.broj_naloga, sn.uredjaj, sn.serijski_broj,
|
sn.id, sn.klijent_id, sn.tehnicar_id, sn.broj_naloga, sn.uredjaj, sn.serijski_broj,
|
||||||
sn.opis_kvara, sn.status, sn.cena_od, sn.cena_do, sn.cena_konacna,
|
sn.opis_kvara, sn.status, sn.cena_od, sn.cena_do, sn.cena_konacna,
|
||||||
sn.avans, sn.napomena, sn.garancija_do, sn.datum_prijema, sn.datum_zavrsetka,
|
sn.avans, sn.napomena, sn.garancija_do, sn.datum_prijema, sn.datum_zavrsetka,
|
||||||
|
sn.ostecenja, sn.pin_uredjaja, sn.pribor,
|
||||||
COALESCE(kp.naziv, '') AS klijent_naziv
|
COALESCE(kp.naziv, '') AS klijent_naziv
|
||||||
FROM servisni_nalozi sn
|
FROM servisni_nalozi sn
|
||||||
LEFT JOIN klijent_prikaz kp ON kp.id = sn.klijent_id
|
LEFT JOIN klijent_prikaz kp ON kp.id = sn.klijent_id
|
||||||
@@ -88,7 +89,8 @@ func (r *ServisRepo) DohvatiID(ctx context.Context, id int64) (*model.ServisniNa
|
|||||||
SELECT
|
SELECT
|
||||||
id, klijent_id, tehnicar_id, broj_naloga, uredjaj, serijski_broj,
|
id, klijent_id, tehnicar_id, broj_naloga, uredjaj, serijski_broj,
|
||||||
opis_kvara, status, cena_od, cena_do, cena_konacna,
|
opis_kvara, status, cena_od, cena_do, cena_konacna,
|
||||||
avans, napomena, garancija_do, datum_prijema, datum_zavrsetka
|
avans, napomena, garancija_do, datum_prijema, datum_zavrsetka,
|
||||||
|
ostecenja, pin_uredjaja, pribor
|
||||||
FROM servisni_nalozi WHERE id = ?`, id)
|
FROM servisni_nalozi WHERE id = ?`, id)
|
||||||
|
|
||||||
var n model.ServisniNalog
|
var n model.ServisniNalog
|
||||||
@@ -105,13 +107,16 @@ func (r *ServisRepo) Kreiraj(ctx context.Context, n *model.ServisniNalog) (int64
|
|||||||
rezultat, err := r.db.ExecContext(ctx, `
|
rezultat, err := r.db.ExecContext(ctx, `
|
||||||
INSERT INTO servisni_nalozi
|
INSERT INTO servisni_nalozi
|
||||||
(klijent_id, tehnicar_id, broj_naloga, uredjaj, serijski_broj, opis_kvara,
|
(klijent_id, tehnicar_id, broj_naloga, uredjaj, serijski_broj, opis_kvara,
|
||||||
status, cena_od, cena_do, cena_konacna, avans, napomena, garancija_do, datum_zavrsetka)
|
status, cena_od, cena_do, cena_konacna, avans, napomena, garancija_do, datum_zavrsetka,
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
ostecenja, pin_uredjaja, pribor, datum_prijema)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||||
nullInt64(n.KlijentID), nullInt64(n.TehnicarID), n.BrojNaloga, n.Uredjaj,
|
nullInt64(n.KlijentID), nullInt64(n.TehnicarID), n.BrojNaloga, n.Uredjaj,
|
||||||
nullString(n.SerijskiBroj), n.OpisKvara, n.Status,
|
nullString(n.SerijskiBroj), n.OpisKvara, n.Status,
|
||||||
nullFloat64(n.CenaOd), nullFloat64(n.CenaDo), nullFloat64(n.CenaKonacna),
|
nullFloat64(n.CenaOd), nullFloat64(n.CenaDo), nullFloat64(n.CenaKonacna),
|
||||||
nullFloat64(n.Avans), nullString(n.Napomena),
|
nullFloat64(n.Avans), nullString(n.Napomena),
|
||||||
nullTime(n.GarancijaDo), nullTime(n.DatumZavrsetka),
|
nullTime(n.GarancijaDo), nullTime(n.DatumZavrsetka),
|
||||||
|
nullString(n.Ostecenja), nullString(n.PinUredjaja), nullString(n.Pribor),
|
||||||
|
n.DatumPrijema,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("ntech: ServisRepo.Kreiraj: %w", err)
|
return 0, fmt.Errorf("ntech: ServisRepo.Kreiraj: %w", err)
|
||||||
@@ -131,11 +136,13 @@ func (r *ServisRepo) Izmeni(ctx context.Context, n *model.ServisniNalog) error {
|
|||||||
UPDATE servisni_nalozi SET
|
UPDATE servisni_nalozi SET
|
||||||
klijent_id = ?, tehnicar_id = ?, uredjaj = ?, serijski_broj = ?, opis_kvara = ?,
|
klijent_id = ?, tehnicar_id = ?, uredjaj = ?, serijski_broj = ?, opis_kvara = ?,
|
||||||
status = ?, cena_od = ?, cena_do = ?, cena_konacna = ?,
|
status = ?, cena_od = ?, cena_do = ?, cena_konacna = ?,
|
||||||
avans = ?, napomena = ?, garancija_do = ?, datum_zavrsetka = ?
|
avans = ?, napomena = ?, garancija_do = ?, datum_zavrsetka = ?,
|
||||||
|
ostecenja = ?, pin_uredjaja = ?, pribor = ?
|
||||||
WHERE id = ?`,
|
WHERE id = ?`,
|
||||||
nullInt64(n.KlijentID), nullInt64(n.TehnicarID), n.Uredjaj, nullString(n.SerijskiBroj), n.OpisKvara,
|
nullInt64(n.KlijentID), nullInt64(n.TehnicarID), n.Uredjaj, nullString(n.SerijskiBroj), n.OpisKvara,
|
||||||
n.Status, nullFloat64(n.CenaOd), nullFloat64(n.CenaDo), nullFloat64(n.CenaKonacna),
|
n.Status, nullFloat64(n.CenaOd), nullFloat64(n.CenaDo), nullFloat64(n.CenaKonacna),
|
||||||
nullFloat64(n.Avans), nullString(n.Napomena), nullTime(n.GarancijaDo), nullTime(n.DatumZavrsetka),
|
nullFloat64(n.Avans), nullString(n.Napomena), nullTime(n.GarancijaDo), nullTime(n.DatumZavrsetka),
|
||||||
|
nullString(n.Ostecenja), nullString(n.PinUredjaja), nullString(n.Pribor),
|
||||||
n.ID,
|
n.ID,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -159,7 +166,7 @@ func (r *ServisRepo) Obrisi(ctx context.Context, id int64) error {
|
|||||||
// klijentNaziv je opcioni pokazivač, nil kada se čita bez JOIN-a
|
// klijentNaziv je opcioni pokazivač, nil kada se čita bez JOIN-a
|
||||||
func scanNalog(scan func(...any) error, n *model.ServisniNalog, klijentNaziv *string) error {
|
func scanNalog(scan func(...any) error, n *model.ServisniNalog, klijentNaziv *string) error {
|
||||||
var klijentID, tehnicarID sql.NullInt64
|
var klijentID, tehnicarID sql.NullInt64
|
||||||
var serijskiBroj, napomena sql.NullString
|
var serijskiBroj, napomena, ostecenja, pinUredjaja, pribor sql.NullString
|
||||||
var cenaOd, cenaDo, cenaKonacna, avans sql.NullFloat64
|
var cenaOd, cenaDo, cenaKonacna, avans sql.NullFloat64
|
||||||
var garancijaDo, datumZavrsetka sql.NullTime
|
var garancijaDo, datumZavrsetka sql.NullTime
|
||||||
|
|
||||||
@@ -167,6 +174,7 @@ func scanNalog(scan func(...any) error, n *model.ServisniNalog, klijentNaziv *st
|
|||||||
&n.ID, &klijentID, &tehnicarID, &n.BrojNaloga, &n.Uredjaj, &serijskiBroj,
|
&n.ID, &klijentID, &tehnicarID, &n.BrojNaloga, &n.Uredjaj, &serijskiBroj,
|
||||||
&n.OpisKvara, &n.Status, &cenaOd, &cenaDo, &cenaKonacna,
|
&n.OpisKvara, &n.Status, &cenaOd, &cenaDo, &cenaKonacna,
|
||||||
&avans, &napomena, &garancijaDo, &n.DatumPrijema, &datumZavrsetka,
|
&avans, &napomena, &garancijaDo, &n.DatumPrijema, &datumZavrsetka,
|
||||||
|
&ostecenja, &pinUredjaja, &pribor,
|
||||||
}
|
}
|
||||||
|
|
||||||
if klijentNaziv != nil {
|
if klijentNaziv != nil {
|
||||||
@@ -187,6 +195,9 @@ func scanNalog(scan func(...any) error, n *model.ServisniNalog, klijentNaziv *st
|
|||||||
}
|
}
|
||||||
n.SerijskiBroj = serijskiBroj.String
|
n.SerijskiBroj = serijskiBroj.String
|
||||||
n.Napomena = napomena.String
|
n.Napomena = napomena.String
|
||||||
|
n.Ostecenja = ostecenja.String
|
||||||
|
n.PinUredjaja = pinUredjaja.String
|
||||||
|
n.Pribor = pribor.String
|
||||||
if cenaOd.Valid {
|
if cenaOd.Valid {
|
||||||
v := cenaOd.Float64
|
v := cenaOd.Float64
|
||||||
n.CenaOd = &v
|
n.CenaOd = &v
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ type podaciProfilTema struct {
|
|||||||
LokalnaPozadinaBlur string
|
LokalnaPozadinaBlur string
|
||||||
LokalnaPozadinaBlurPozadine string
|
LokalnaPozadinaBlurPozadine string
|
||||||
LokalnaPozadinaGlassOpacity string
|
LokalnaPozadinaGlassOpacity string
|
||||||
|
LokalnaAnimacija string
|
||||||
|
LokalniHover string
|
||||||
}
|
}
|
||||||
|
|
||||||
// AdminKorisnici prikazuje listu korisnika
|
// AdminKorisnici prikazuje listu korisnika
|
||||||
|
|||||||
@@ -211,6 +211,10 @@ func (h *Handler) popuniPodaciStranice(r *http.Request, podesavanja map[string]s
|
|||||||
ps.AppPozadinaGlassOpacity = "10"
|
ps.AppPozadinaGlassOpacity = "10"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if korisnik != nil {
|
||||||
|
ps.LokalnaAnimacija = korisnik.LokalnaAnimacija
|
||||||
|
ps.LokalniHover = korisnik.LokalniHover
|
||||||
|
}
|
||||||
|
|
||||||
return ps
|
return ps
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ var saSidebar = []string{
|
|||||||
"klijenti", "klijent_forma",
|
"klijenti", "klijent_forma",
|
||||||
"magacin", "magacin_forma",
|
"magacin", "magacin_forma",
|
||||||
"nabavke", "nabavka_forma", "nabavka_detalji",
|
"nabavke", "nabavka_forma", "nabavka_detalji",
|
||||||
"podesavanja", "podesavanja_opste", "podesavanja_izgled", "podesavanja_sistem",
|
"podesavanja", "podesavanja_opste", "podesavanja_izgled", "podesavanja_sistem", "podesavanja_servis",
|
||||||
"pdv_stope",
|
"pdv_stope",
|
||||||
"pdv_kir", "pdv_kir_forma",
|
"pdv_kir", "pdv_kir_forma",
|
||||||
"pdv_kpr", "pdv_kpr_forma",
|
"pdv_kpr", "pdv_kpr_forma",
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"ntech/internal/db/sqlite"
|
"ntech/internal/db/sqlite"
|
||||||
"ntech/internal/middleware"
|
"ntech/internal/middleware"
|
||||||
@@ -34,6 +35,18 @@ func (h *Handler) Nivelacije(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
odStr := r.URL.Query().Get("od")
|
odStr := r.URL.Query().Get("od")
|
||||||
doStr := r.URL.Query().Get("do")
|
doStr := r.URL.Query().Get("do")
|
||||||
|
// podrazumevano: tekući mesec (od prvog do poslednjeg dana)
|
||||||
|
if odStr == "" || doStr == "" {
|
||||||
|
sada := time.Now()
|
||||||
|
prvi := time.Date(sada.Year(), sada.Month(), 1, 0, 0, 0, 0, sada.Location())
|
||||||
|
poslednji := prvi.AddDate(0, 1, -1)
|
||||||
|
if odStr == "" {
|
||||||
|
odStr = prvi.Format("2006-01-02")
|
||||||
|
}
|
||||||
|
if doStr == "" {
|
||||||
|
doStr = poslednji.Format("2006-01-02")
|
||||||
|
}
|
||||||
|
}
|
||||||
zapisi, err := h.NivelacijaRepo.Lista(r.Context(), parsiraDatumOpcionalno(odStr), parsiraDatumOpcionalno(doStr))
|
zapisi, err := h.NivelacijaRepo.Lista(r.Context(), parsiraDatumOpcionalno(odStr), parsiraDatumOpcionalno(doStr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Greška pri učitavanju nivelacija", http.StatusInternalServerError)
|
http.Error(w, "Greška pri učitavanju nivelacija", http.StatusInternalServerError)
|
||||||
|
|||||||
@@ -61,6 +61,18 @@ func (h *Handler) PdvKir(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
odStr := r.URL.Query().Get("od")
|
odStr := r.URL.Query().Get("od")
|
||||||
doStr := r.URL.Query().Get("do")
|
doStr := r.URL.Query().Get("do")
|
||||||
|
// podrazumevano: tekući mesec (od prvog do poslednjeg dana)
|
||||||
|
if odStr == "" || doStr == "" {
|
||||||
|
sada := time.Now()
|
||||||
|
prvi := time.Date(sada.Year(), sada.Month(), 1, 0, 0, 0, 0, sada.Location())
|
||||||
|
poslednji := prvi.AddDate(0, 1, -1)
|
||||||
|
if odStr == "" {
|
||||||
|
odStr = prvi.Format("2006-01-02")
|
||||||
|
}
|
||||||
|
if doStr == "" {
|
||||||
|
doStr = poslednji.Format("2006-01-02")
|
||||||
|
}
|
||||||
|
}
|
||||||
zapisi, err := h.PdvKirRepo.Lista(r.Context(), parsiraDatumOpcionalno(odStr), parsiraDatumOpcionalno(doStr))
|
zapisi, err := h.PdvKirRepo.Lista(r.Context(), parsiraDatumOpcionalno(odStr), parsiraDatumOpcionalno(doStr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Greška pri učitavanju knjige izdatih računa", http.StatusInternalServerError)
|
http.Error(w, "Greška pri učitavanju knjige izdatih računa", http.StatusInternalServerError)
|
||||||
|
|||||||
@@ -42,6 +42,18 @@ func (h *Handler) PdvKpr(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
odStr := r.URL.Query().Get("od")
|
odStr := r.URL.Query().Get("od")
|
||||||
doStr := r.URL.Query().Get("do")
|
doStr := r.URL.Query().Get("do")
|
||||||
|
// podrazumevano: tekući mesec (od prvog do poslednjeg dana)
|
||||||
|
if odStr == "" || doStr == "" {
|
||||||
|
sada := time.Now()
|
||||||
|
prvi := time.Date(sada.Year(), sada.Month(), 1, 0, 0, 0, 0, sada.Location())
|
||||||
|
poslednji := prvi.AddDate(0, 1, -1)
|
||||||
|
if odStr == "" {
|
||||||
|
odStr = prvi.Format("2006-01-02")
|
||||||
|
}
|
||||||
|
if doStr == "" {
|
||||||
|
doStr = poslednji.Format("2006-01-02")
|
||||||
|
}
|
||||||
|
}
|
||||||
zapisi, err := h.PdvKprRepo.Lista(r.Context(), parsiraDatumOpcionalno(odStr), parsiraDatumOpcionalno(doStr))
|
zapisi, err := h.PdvKprRepo.Lista(r.Context(), parsiraDatumOpcionalno(odStr), parsiraDatumOpcionalno(doStr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Greška pri učitavanju knjige primljenih računa", http.StatusInternalServerError)
|
http.Error(w, "Greška pri učitavanju knjige primljenih računa", http.StatusInternalServerError)
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ type PodaciPodesavanja struct {
|
|||||||
BackupIntervalSati string
|
BackupIntervalSati string
|
||||||
BackupBrojKopija string
|
BackupBrojKopija string
|
||||||
KalkulacijaMarza string
|
KalkulacijaMarza string
|
||||||
|
ServisGarancijaMeseci string
|
||||||
LoginPozadina string
|
LoginPozadina string
|
||||||
LoginPozadinaOpacity string
|
LoginPozadinaOpacity string
|
||||||
LoginPozadinaBlurPozadine string
|
LoginPozadinaBlurPozadine string
|
||||||
@@ -314,6 +315,20 @@ func (h *Handler) SacuvajPodesavanja(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// podrazumevani rok garancije za servis (meseci, 0–120)
|
||||||
|
if v := strings.TrimSpace(r.FormValue("servis_garancija_meseci")); v != "" {
|
||||||
|
n, err := strconv.Atoi(v)
|
||||||
|
if err != nil || n < 0 || n > 120 {
|
||||||
|
middleware.SetFlash(w, r, h.DB, "greska", "Rok garancije mora biti broj između 0 i 120 meseci.")
|
||||||
|
http.Redirect(w, r, sledeci, http.StatusSeeOther)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "servis_garancija_meseci", strconv.Itoa(n)); err != nil {
|
||||||
|
http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
http.Redirect(w, r, sledeci+"?sacuvano=1", http.StatusSeeOther)
|
http.Redirect(w, r, sledeci+"?sacuvano=1", http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -438,6 +453,20 @@ func (h *Handler) UkloniLogo(w http.ResponseWriter, r *http.Request) {
|
|||||||
http.Redirect(w, r, "/admin/podesavanja/opste?sacuvano=1", http.StatusSeeOther)
|
http.Redirect(w, r, "/admin/podesavanja/opste?sacuvano=1", http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PodesavanjaServis renderuje stranicu sa podešavanjima servisnog modula
|
||||||
|
func (h *Handler) PodesavanjaServis(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if _, ok := h.zahtevajDozvolu(w, r, "podesavanja.pregled"); !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
podaci, err := h.napuniPodaciPodesavanja(r, "Podešavanja — Servis")
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Greška pri učitavanju podešavanja", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
podaci.Stranica = "podesavanja-servis"
|
||||||
|
h.renderujTemplate(w, "podesavanja_servis", podaci)
|
||||||
|
}
|
||||||
|
|
||||||
// generisiImeUploada vraća slučajno hex ime (16 bajtova) sa datom ekstenzijom
|
// generisiImeUploada vraća slučajno hex ime (16 bajtova) sa datom ekstenzijom
|
||||||
func generisiImeUploada(ext string) (string, error) {
|
func generisiImeUploada(ext string) (string, error) {
|
||||||
buf := make([]byte, 16)
|
buf := make([]byte, 16)
|
||||||
@@ -669,6 +698,7 @@ func (h *Handler) napuniPodaciPodesavanja(r *http.Request, naslov string) (Podac
|
|||||||
BackupIntervalSati: vrednostIliDefault(podesavanja, "backup_interval_sati", "24"),
|
BackupIntervalSati: vrednostIliDefault(podesavanja, "backup_interval_sati", "24"),
|
||||||
BackupBrojKopija: vrednostIliDefault(podesavanja, "backup_broj_kopija", "7"),
|
BackupBrojKopija: vrednostIliDefault(podesavanja, "backup_broj_kopija", "7"),
|
||||||
KalkulacijaMarza: vrednostIliDefault(podesavanja, "kalkulacija_marza", "20"),
|
KalkulacijaMarza: vrednostIliDefault(podesavanja, "kalkulacija_marza", "20"),
|
||||||
|
ServisGarancijaMeseci: vrednostIliDefault(podesavanja, "servis_garancija_meseci", "2"),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ func (h *Handler) PrikazPrijave(w http.ResponseWriter, r *http.Request) {
|
|||||||
"LoginPozadinaBlurPozadine": loginBlurPozadine,
|
"LoginPozadinaBlurPozadine": loginBlurPozadine,
|
||||||
"LoginPozadinaBlurKartice": loginBlurKartice,
|
"LoginPozadinaBlurKartice": loginBlurKartice,
|
||||||
"LoginPozadinaZatamnjenjeKartice": loginZatamnjenjeKartice,
|
"LoginPozadinaZatamnjenjeKartice": loginZatamnjenjeKartice,
|
||||||
|
"Verzija": h.Verzija,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ func (h *Handler) ProfilTema(w http.ResponseWriter, r *http.Request) {
|
|||||||
LokalnaPozadinaBlur: svezi.LokalnaPozadinaBlur,
|
LokalnaPozadinaBlur: svezi.LokalnaPozadinaBlur,
|
||||||
LokalnaPozadinaBlurPozadine: svezi.LokalnaPozadinaBlurPozadine,
|
LokalnaPozadinaBlurPozadine: svezi.LokalnaPozadinaBlurPozadine,
|
||||||
LokalnaPozadinaGlassOpacity: svezi.LokalnaPozadinaGlassOpacity,
|
LokalnaPozadinaGlassOpacity: svezi.LokalnaPozadinaGlassOpacity,
|
||||||
|
LokalnaAnimacija: svezi.LokalnaAnimacija,
|
||||||
|
LokalniHover: svezi.LokalniHover,
|
||||||
}
|
}
|
||||||
if podaci.LokalnaPozadinaOpacity == "" {
|
if podaci.LokalnaPozadinaOpacity == "" {
|
||||||
podaci.LokalnaPozadinaOpacity = "50"
|
podaci.LokalnaPozadinaOpacity = "50"
|
||||||
@@ -293,6 +295,84 @@ func (h *Handler) SacuvajLokalnuTemu(w http.ResponseWriter, r *http.Request) {
|
|||||||
http.Redirect(w, r, "/admin/profil", http.StatusSeeOther)
|
http.Redirect(w, r, "/admin/profil", http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SacuvajLokalnuAnimaciju čuva korisnikovu preferencu animacije tabela
|
||||||
|
func (h *Handler) SacuvajLokalnuAnimaciju(w http.ResponseWriter, r *http.Request) {
|
||||||
|
k := middleware.KorisnikIzKonteksta(r.Context())
|
||||||
|
if k == nil {
|
||||||
|
http.Redirect(w, r, "/prijava", http.StatusSeeOther)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !h.DozvoleRepo.ImaDozvolu(r.Context(), k.Uloga, "tema.lokalno") {
|
||||||
|
http.Error(w, "Pristup odbijen", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := r.ParseForm(); err != nil {
|
||||||
|
middleware.SetFlash(w, r, h.DB, "greska", "Greška. Pokušajte ponovo.")
|
||||||
|
http.Redirect(w, r, "/admin/profil/tema", http.StatusSeeOther)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
animacija := r.FormValue("lokalna_animacija")
|
||||||
|
dozvoljene := map[string]bool{"": true, "bez": true, "fadeInUp": true, "fadeIn": true, "scaleIn": true, "slideLeft": true}
|
||||||
|
if !dozvoljene[animacija] {
|
||||||
|
animacija = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := h.KorisniciRepo.SacuvajLokalnuAnimaciju(r.Context(), k.ID, animacija); err != nil {
|
||||||
|
middleware.SetFlash(w, r, h.DB, "greska", "Greška pri čuvanju. Pokušajte ponovo.")
|
||||||
|
http.Redirect(w, r, "/admin/profil/tema", http.StatusSeeOther)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
middleware.SetFlash(w, r, h.DB, "uspeh", "Animacija je sačuvana.")
|
||||||
|
if ref := r.Referer(); ref != "" {
|
||||||
|
if u, err := url.Parse(ref); err == nil {
|
||||||
|
http.Redirect(w, r, u.RequestURI(), http.StatusSeeOther)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
http.Redirect(w, r, "/admin/profil/tema", http.StatusSeeOther)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SacuvajLokalniHover čuva korisnikovu preferencu hover efekta na karticama
|
||||||
|
func (h *Handler) SacuvajLokalniHover(w http.ResponseWriter, r *http.Request) {
|
||||||
|
k := middleware.KorisnikIzKonteksta(r.Context())
|
||||||
|
if k == nil {
|
||||||
|
http.Redirect(w, r, "/prijava", http.StatusSeeOther)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !h.DozvoleRepo.ImaDozvolu(r.Context(), k.Uloga, "tema.lokalno") {
|
||||||
|
http.Error(w, "Pristup odbijen", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := r.ParseForm(); err != nil {
|
||||||
|
middleware.SetFlash(w, r, h.DB, "greska", "Greška. Pokušajte ponovo.")
|
||||||
|
http.Redirect(w, r, "/admin/profil/tema", http.StatusSeeOther)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
hover := r.FormValue("lokalni_hover")
|
||||||
|
dozvoljeni := map[string]bool{"": true, "bez": true, "podizanje": true, "svetlost": true, "zoom": true, "boja": true}
|
||||||
|
if !dozvoljeni[hover] {
|
||||||
|
hover = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := h.KorisniciRepo.SacuvajLokalniHover(r.Context(), k.ID, hover); err != nil {
|
||||||
|
middleware.SetFlash(w, r, h.DB, "greska", "Greška pri čuvanju. Pokušajte ponovo.")
|
||||||
|
http.Redirect(w, r, "/admin/profil/tema", http.StatusSeeOther)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
middleware.SetFlash(w, r, h.DB, "uspeh", "Hover efekat je sačuvan.")
|
||||||
|
if ref := r.Referer(); ref != "" {
|
||||||
|
if u, err := url.Parse(ref); err == nil {
|
||||||
|
http.Redirect(w, r, u.RequestURI(), http.StatusSeeOther)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
http.Redirect(w, r, "/admin/profil/tema", http.StatusSeeOther)
|
||||||
|
}
|
||||||
|
|
||||||
// ProfilOtpremiAvatar prima upload lične avatar slike korisnika
|
// ProfilOtpremiAvatar prima upload lične avatar slike korisnika
|
||||||
func (h *Handler) ProfilOtpremiAvatar(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) ProfilOtpremiAvatar(w http.ResponseWriter, r *http.Request) {
|
||||||
k := middleware.KorisnikIzKonteksta(r.Context())
|
k := middleware.KorisnikIzKonteksta(r.Context())
|
||||||
|
|||||||
@@ -110,9 +110,15 @@ func (h *Handler) NoviNalog(w http.ResponseWriter, r *http.Request) {
|
|||||||
ps := h.popuniPodaciStranice(r, podesavanja)
|
ps := h.popuniPodaciStranice(r, podesavanja)
|
||||||
ps.Stranica = "servis"
|
ps.Stranica = "servis"
|
||||||
ps.NaslovStranice = "Novi nalog"
|
ps.NaslovStranice = "Novi nalog"
|
||||||
|
noviNalog := model.ServisniNalog{
|
||||||
|
BrojNaloga: brojNaloga,
|
||||||
|
Status: model.StatusPrimljeno,
|
||||||
|
DatumPrijema: time.Now(),
|
||||||
|
}
|
||||||
|
noviNalog.GarancijaDo = defaultGarancija(noviNalog.DatumPrijema, podesavanja)
|
||||||
h.renderujFormuNaloga(w, PodaciFormeNaloga{
|
h.renderujFormuNaloga(w, PodaciFormeNaloga{
|
||||||
PodaciStranice: ps,
|
PodaciStranice: ps,
|
||||||
Nalog: model.ServisniNalog{BrojNaloga: brojNaloga, Status: model.StatusPrimljeno},
|
Nalog: noviNalog,
|
||||||
Klijenti: klijenti,
|
Klijenti: klijenti,
|
||||||
Tehnicari: tehnicari,
|
Tehnicari: tehnicari,
|
||||||
SviStatusi: model.SviStatusi,
|
SviStatusi: model.SviStatusi,
|
||||||
@@ -206,6 +212,9 @@ func (h *Handler) IzmeniNalog(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if nalog.GarancijaDo == nil {
|
||||||
|
nalog.GarancijaDo = defaultGarancija(nalog.DatumPrijema, podesavanja)
|
||||||
|
}
|
||||||
ps := h.popuniPodaciStranice(r, podesavanja)
|
ps := h.popuniPodaciStranice(r, podesavanja)
|
||||||
ps.Stranica = "servis"
|
ps.Stranica = "servis"
|
||||||
ps.NaslovStranice = "Izmeni nalog"
|
ps.NaslovStranice = "Izmeni nalog"
|
||||||
@@ -460,6 +469,17 @@ func parseFormuNaloga(r *http.Request) (model.ServisniNalog, string) {
|
|||||||
OpisKvara: opisKvara,
|
OpisKvara: opisKvara,
|
||||||
Status: r.FormValue("status"),
|
Status: r.FormValue("status"),
|
||||||
Napomena: strings.TrimSpace(r.FormValue("napomena")),
|
Napomena: strings.TrimSpace(r.FormValue("napomena")),
|
||||||
|
Ostecenja: strings.TrimSpace(r.FormValue("ostecenja")),
|
||||||
|
PinUredjaja: strings.TrimSpace(r.FormValue("pin_uredjaja")),
|
||||||
|
Pribor: strings.TrimSpace(r.FormValue("pribor")),
|
||||||
|
DatumPrijema: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// datum prijema — korisnik može da unese drugi datum (npr. retroaktivno)
|
||||||
|
if dp := strings.TrimSpace(r.FormValue("datum_prijema")); dp != "" {
|
||||||
|
if t, err := time.Parse("2006-01-02", dp); err == nil {
|
||||||
|
nalog.DatumPrijema = t
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if nalog.Status == "" {
|
if nalog.Status == "" {
|
||||||
@@ -493,16 +513,29 @@ func parseFormuNaloga(r *http.Request) (model.ServisniNalog, string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// opcioni datum garancije
|
// opcioni datum garancije — preskačemo ako je korisnik označio "bez garancije"
|
||||||
if gd := strings.TrimSpace(r.FormValue("garancija_do")); gd != "" {
|
if r.FormValue("bez_garancije") != "1" {
|
||||||
if t, err := time.Parse("2006-01-02", gd); err == nil {
|
if gd := strings.TrimSpace(r.FormValue("garancija_do")); gd != "" {
|
||||||
nalog.GarancijaDo = &t
|
if t, err := time.Parse("2006-01-02", gd); err == nil {
|
||||||
|
nalog.GarancijaDo = &t
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nalog, ""
|
return nalog, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// defaultGarancija vraća datum garancije na osnovu datuma prijema i podešavanja;
|
||||||
|
// vraća nil ako je rok 0 ili podešavanje nedostaje
|
||||||
|
func defaultGarancija(datumPrijema time.Time, podesavanja map[string]string) *time.Time {
|
||||||
|
meseci, err := strconv.Atoi(vrednostIliDefault(podesavanja, "servis_garancija_meseci", "2"))
|
||||||
|
if err != nil || meseci <= 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
t := datumPrijema.AddDate(0, meseci, 0)
|
||||||
|
return &t
|
||||||
|
}
|
||||||
|
|
||||||
// parseOpcionuCenu pretvara string u *float64 — prazno polje ili neispravna vrednost vraća nil
|
// parseOpcionuCenu pretvara string u *float64 — prazno polje ili neispravna vrednost vraća nil
|
||||||
func parseOpcionuCenu(s string) *float64 {
|
func parseOpcionuCenu(s string) *float64 {
|
||||||
s = strings.TrimSpace(s)
|
s = strings.TrimSpace(s)
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ type Korisnik struct {
|
|||||||
LokalnaPozadinaBlurPozadine string
|
LokalnaPozadinaBlurPozadine string
|
||||||
LokalnaPozadinaGlassOpacity string
|
LokalnaPozadinaGlassOpacity string
|
||||||
AvatarPutanja string
|
AvatarPutanja string
|
||||||
|
LokalnaAnimacija string // "" | "fadeInUp" | "fadeIn" | "scaleIn" | "slideLeft"
|
||||||
|
LokalniHover string // "" | "bez" | "podizanje" | "svetlost"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sesija predstavlja aktivnu sesiju prijavljenog korisnika
|
// Sesija predstavlja aktivnu sesiju prijavljenog korisnika
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ type ServisniNalog struct {
|
|||||||
GarancijaDo *time.Time
|
GarancijaDo *time.Time
|
||||||
DatumPrijema time.Time
|
DatumPrijema time.Time
|
||||||
DatumZavrsetka *time.Time
|
DatumZavrsetka *time.Time
|
||||||
|
Ostecenja string
|
||||||
|
PinUredjaja string
|
||||||
|
Pribor string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServisniDeo predstavlja jedan artikal ugrađen u servisni nalog
|
// ServisniDeo predstavlja jedan artikal ugrađen u servisni nalog
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ type PodaciStranice struct {
|
|||||||
AppPozadinaBlur string // vrednost 0-20 (px backdrop-filter blur na elementima)
|
AppPozadinaBlur string // vrednost 0-20 (px backdrop-filter blur na elementima)
|
||||||
AppPozadinaBlurPozadine string // vrednost 0-20 (px filter blur na pozadinskoj slici)
|
AppPozadinaBlurPozadine string // vrednost 0-20 (px filter blur na pozadinskoj slici)
|
||||||
AppPozadinaGlassOpacity string // vrednost 0-80 (% zatamnjivanje glass elemenata) — samo za ličnu pozadinu
|
AppPozadinaGlassOpacity string // vrednost 0-80 (% zatamnjivanje glass elemenata) — samo za ličnu pozadinu
|
||||||
|
LokalnaAnimacija string // "" | "fadeInUp" | "fadeIn" | "scaleIn" | "slideLeft"
|
||||||
|
LokalniHover string // "" | "bez" | "podizanje" | "svetlost"
|
||||||
}
|
}
|
||||||
|
|
||||||
// PodaciDashboarda su podaci specifični za dashboard stranicu
|
// PodaciDashboarda su podaci specifični za dashboard stranicu
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE servisni_nalozi ADD COLUMN ostecenja TEXT;
|
||||||
|
ALTER TABLE servisni_nalozi ADD COLUMN pin_uredjaja TEXT;
|
||||||
|
ALTER TABLE servisni_nalozi ADD COLUMN pribor TEXT;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
INSERT OR IGNORE INTO podesavanja (kljuc, vrednost) VALUES
|
||||||
|
('servis_garancija_meseci', '2');
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE korisnici ADD COLUMN lokalna_animacija TEXT;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE korisnici ADD COLUMN lokalni_hover TEXT;
|
||||||
+83
-7
@@ -339,12 +339,42 @@ body {
|
|||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
box-shadow: var(--senka);
|
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 {
|
.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);
|
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;
|
/* modal za premeštanje artikla — koristi promenljive teme, pa prati svetlu/tamnu;
|
||||||
@@ -592,7 +622,9 @@ body {
|
|||||||
color: var(--tekst-sporedni);
|
color: var(--tekst-sporedni);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.05em;
|
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 */
|
/* avatar krug korisnika u topbaru */
|
||||||
@@ -980,6 +1012,21 @@ select {
|
|||||||
to { opacity: 1; transform: translateY(0); }
|
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 {
|
@keyframes slideDown {
|
||||||
from { opacity: 0; transform: translateY(-10px); }
|
from { opacity: 0; transform: translateY(-10px); }
|
||||||
to { opacity: 1; transform: translateY(0); }
|
to { opacity: 1; transform: translateY(0); }
|
||||||
@@ -1003,11 +1050,40 @@ select {
|
|||||||
animation: fadeInUp 0.2s ease backwards;
|
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.
|
/* 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
|
Animacija se primenjuje direktno na <tr> u .tabela, bez potrebe za .animiraj klasom.
|
||||||
delay-a. Mora biti u main.css: HTMX navigacija (hx-select) odbacuje <head>, pa
|
Mora biti u main.css: HTMX navigacija (hx-select) odbacuje <head>, pa
|
||||||
stilovi iz page <style> blokova ne bi važili tokom navigacije.
|
stilovi iz page <style> blokova ne bi važili tokom navigacije. */
|
||||||
Da promeniš animaciju redova svuda — menjaš samo ovde. */
|
.tabela tbody tr {
|
||||||
|
animation: fadeInUp 0.2s ease backwards;
|
||||||
|
}
|
||||||
.tabela tbody tr:nth-child(1) { animation-delay: 0.04s; }
|
.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(2) { animation-delay: 0.08s; }
|
||||||
.tabela tbody tr:nth-child(3) { animation-delay: 0.12s; }
|
.tabela tbody tr:nth-child(3) { animation-delay: 0.12s; }
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
--tekst-sporedni: #57606a;
|
--tekst-sporedni: #57606a;
|
||||||
--tekst-jak: #1f2328;
|
--tekst-jak: #1f2328;
|
||||||
--ivica: #d0d7de;
|
--ivica: #d0d7de;
|
||||||
|
--ivica-jaka: #9ba5b0;
|
||||||
--sb-akcent: #1f6feb;
|
--sb-akcent: #1f6feb;
|
||||||
--sb-akcent-hover: #388bfd;
|
--sb-akcent-hover: #388bfd;
|
||||||
--sb-aktivan: #ebeef1;
|
--sb-aktivan: #ebeef1;
|
||||||
@@ -15,7 +16,8 @@
|
|||||||
--upozorenje: #9a6700;
|
--upozorenje: #9a6700;
|
||||||
--greska: #cf222e;
|
--greska: #cf222e;
|
||||||
--info: #0969da;
|
--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;
|
--sidebar-pozadina: #ffffff;
|
||||||
--poruka-uspeh-bg: rgba(26, 127, 55, 0.1);
|
--poruka-uspeh-bg: rgba(26, 127, 55, 0.1);
|
||||||
--poruka-uspeh-boja: #1a7f37;
|
--poruka-uspeh-boja: #1a7f37;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
--tekst-sporedni: #a0a8b5;
|
--tekst-sporedni: #a0a8b5;
|
||||||
--tekst-jak: #f0f3f6;
|
--tekst-jak: #f0f3f6;
|
||||||
--ivica: #353a44;
|
--ivica: #353a44;
|
||||||
|
--ivica-jaka: #5a6070;
|
||||||
--sb-akcent: #4684d6;
|
--sb-akcent: #4684d6;
|
||||||
--sb-akcent-hover: #5a96e6;
|
--sb-akcent-hover: #5a96e6;
|
||||||
--sb-aktivan: #2a2f37;
|
--sb-aktivan: #2a2f37;
|
||||||
@@ -15,7 +16,8 @@
|
|||||||
--upozorenje: #e1b04a;
|
--upozorenje: #e1b04a;
|
||||||
--greska: #cf5757;
|
--greska: #cf5757;
|
||||||
--info: #5cb1d6;
|
--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;
|
--sidebar-pozadina: #1a1c20;
|
||||||
--poruka-uspeh-bg: rgba(93, 184, 118, 0.15);
|
--poruka-uspeh-bg: rgba(93, 184, 118, 0.15);
|
||||||
--poruka-uspeh-boja: #5db876;
|
--poruka-uspeh-boja: #5db876;
|
||||||
|
|||||||
@@ -187,19 +187,19 @@
|
|||||||
{{if index .Dozvole "podesavanja.pregled"}}
|
{{if index .Dozvole "podesavanja.pregled"}}
|
||||||
<div>
|
<div>
|
||||||
<button type="button" data-podmeni-dugme
|
<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;">
|
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>
|
<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>Podešavanja</span>
|
||||||
<span class="nav-strelica">
|
<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"
|
<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"/>
|
<polyline points="6 9 12 15 18 9"/>
|
||||||
</svg>
|
</svg>
|
||||||
</span>
|
</span>
|
||||||
<span class="nav-tooltip">Podešavanja</span>
|
<span class="nav-tooltip">Podešavanja</span>
|
||||||
</button>
|
</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}}">
|
<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>
|
<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>
|
<span>Opšte</span>
|
||||||
@@ -220,6 +220,11 @@
|
|||||||
<span>Kalkulacija i PDV</span>
|
<span>Kalkulacija i PDV</span>
|
||||||
<span class="nav-tooltip">Kalkulacija i PDV</span>
|
<span class="nav-tooltip">Kalkulacija i PDV</span>
|
||||||
</a>
|
</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")}}
|
{{if or (eq .KorisnikUloga "superadmin") (eq .KorisnikUloga "admin")}}
|
||||||
<a href="/admin/dozvole" class="nav-stavka nav-podstavka {{if eq .Stranica "dozvole"}}aktivan{{end}}">
|
<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>
|
<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>
|
||||||
|
|||||||
@@ -6,12 +6,6 @@
|
|||||||
<style>
|
<style>
|
||||||
.izv-naslov { font-size: 13px; font-weight: 500; color: var(--tekst-sporedni); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 14px; }
|
.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-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 { 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; }
|
.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; }
|
||||||
@@ -34,9 +28,9 @@
|
|||||||
<div class="izv-naslov" style="margin-bottom:0;">Mesečni prihod — poslednjih 12 meseci</div>
|
<div class="izv-naslov" style="margin-bottom:0;">Mesečni prihod — poslednjih 12 meseci</div>
|
||||||
<div class="toggle-red" style="margin-bottom:0;">
|
<div class="toggle-red" style="margin-bottom:0;">
|
||||||
<span class="pomocni-tekst">Grafikon</span>
|
<span class="pomocni-tekst">Grafikon</span>
|
||||||
<label class="toggle-switch">
|
<label class="toggl">
|
||||||
<input type="checkbox" id="toggle-grafikon" checked>
|
<input type="checkbox" id="toggle-grafikon" checked>
|
||||||
<span class="toggle-slider"></span>
|
<span class="toggl-klizac"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
<!-- istorija nivelacija -->
|
<!-- istorija nivelacija -->
|
||||||
<div class="kartica animiraj" style="padding:0;overflow:hidden;">
|
<div class="kartica animiraj" style="padding:0;overflow:hidden;">
|
||||||
<div style="overflow-x:auto;">
|
<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>
|
<thead>
|
||||||
<tr style="text-align:left;color:var(--tekst-sporedni);border-bottom:0.5px solid var(--ivica);">
|
<tr style="text-align:left;color:var(--tekst-sporedni);border-bottom:0.5px solid var(--ivica);">
|
||||||
<th style="padding:10px 12px;">Datum</th>
|
<th style="padding:10px 12px;">Datum</th>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
<!-- knjiga -->
|
<!-- knjiga -->
|
||||||
<div class="kartica animiraj" style="padding:0;overflow:hidden;">
|
<div class="kartica animiraj" style="padding:0;overflow:hidden;">
|
||||||
<div style="overflow-x:auto;">
|
<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>
|
<thead>
|
||||||
<tr style="text-align:left;color:var(--tekst-sporedni);border-bottom:0.5px solid var(--ivica);">
|
<tr style="text-align:left;color:var(--tekst-sporedni);border-bottom:0.5px solid var(--ivica);">
|
||||||
<th style="padding:10px 12px;">Datum prometa</th>
|
<th style="padding:10px 12px;">Datum prometa</th>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
<!-- knjiga -->
|
<!-- knjiga -->
|
||||||
<div class="kartica animiraj" style="padding:0;overflow:hidden;">
|
<div class="kartica animiraj" style="padding:0;overflow:hidden;">
|
||||||
<div style="overflow-x:auto;">
|
<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>
|
<thead>
|
||||||
<tr style="text-align:left;color:var(--tekst-sporedni);border-bottom:0.5px solid var(--ivica);">
|
<tr style="text-align:left;color:var(--tekst-sporedni);border-bottom:0.5px solid var(--ivica);">
|
||||||
<th style="padding:10px 12px;">Datum prometa</th>
|
<th style="padding:10px 12px;">Datum prometa</th>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
<!-- obračun po stopama -->
|
<!-- obračun po stopama -->
|
||||||
<div class="kartica animiraj" style="padding:0;overflow:hidden;margin-bottom:16px;">
|
<div class="kartica animiraj" style="padding:0;overflow:hidden;margin-bottom:16px;">
|
||||||
<div style="overflow-x:auto;">
|
<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>
|
<thead>
|
||||||
<tr style="text-align:left;color:var(--tekst-sporedni);border-bottom:0.5px solid var(--ivica);">
|
<tr style="text-align:left;color:var(--tekst-sporedni);border-bottom:0.5px solid var(--ivica);">
|
||||||
<th style="padding:10px 12px;"></th>
|
<th style="padding:10px 12px;"></th>
|
||||||
@@ -110,7 +110,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="overflow-x:auto;margin-top:12px;">
|
<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>
|
<thead>
|
||||||
<tr style="text-align:left;color:var(--tekst-sporedni);border-bottom:0.5px solid var(--ivica);">
|
<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>
|
<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}}
|
||||||
@@ -65,6 +65,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<button type="submit" class="dugme">Prijavi se</button>
|
<button type="submit" class="dugme">Prijavi se</button>
|
||||||
</form>
|
</form>
|
||||||
|
<p style="text-align:center;font-size:12px;color:#4b5563;margin-top:16px;">Verzija: {{.Verzija}}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{if .LoginPozadina}}
|
{{if .LoginPozadina}}
|
||||||
|
|||||||
@@ -74,6 +74,104 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</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 -->
|
<!-- kartica: moj avatar -->
|
||||||
<div class="kartica animiraj" style="margin-bottom:16px;">
|
<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);">
|
<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}}
|
{{end}}
|
||||||
|
|
||||||
</div>
|
</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}}
|
{{end}}
|
||||||
|
|||||||
@@ -103,6 +103,28 @@
|
|||||||
<div style="font-size:12px;color:var(--tekst-sporedni);margin-bottom:6px;">Opis kvara</div>
|
<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 style="font-size:14px;color:var(--tekst-glavni);line-height:1.6;white-space:pre-wrap;">{{.Nalog.OpisKvara}}</div>
|
||||||
</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}}
|
{{if .Nalog.Napomena}}
|
||||||
<div>
|
<div>
|
||||||
<div style="font-size:12px;color:var(--tekst-sporedni);margin-bottom:6px;">Napomena</div>
|
<div style="font-size:12px;color:var(--tekst-sporedni);margin-bottom:6px;">Napomena</div>
|
||||||
|
|||||||
@@ -12,11 +12,11 @@
|
|||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="kartica forma-kartica animiraj">
|
<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;">
|
<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:16px;font-weight:500;color:var(--tekst-glavni);">
|
<span style="font-size:15px;font-weight:600;color:var(--tekst-glavni);">
|
||||||
{{if .Izmena}}Izmeni nalog{{else}}Novi nalog{{end}}
|
{{if .Izmena}}Izmeni nalog{{else}}Novi nalog{{end}}
|
||||||
</span>
|
</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}}
|
{{.Nalog.BrojNaloga}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -60,6 +60,26 @@
|
|||||||
placeholder="Opišite problem koji je klijent prijavio..."
|
placeholder="Opišite problem koji je klijent prijavio..."
|
||||||
style="width:100%;resize:vertical;">{{.Nalog.OpisKvara}}</textarea>
|
style="width:100%;resize:vertical;">{{.Nalog.OpisKvara}}</textarea>
|
||||||
</div>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -97,8 +117,8 @@
|
|||||||
<!-- status i datumi -->
|
<!-- status i datumi -->
|
||||||
<div>
|
<div>
|
||||||
<div class="sekcija-naslov">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 class="kolona" style="gap:12px;">
|
||||||
<div style="grid-column:span 2;">
|
<div>
|
||||||
<label class="polje-labela">Status naloga</label>
|
<label class="polje-labela">Status naloga</label>
|
||||||
<select name="status" style="width:100%;">
|
<select name="status" style="width:100%;">
|
||||||
{{range .SviStatusi}}
|
{{range .SviStatusi}}
|
||||||
@@ -106,17 +126,38 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:12px;">
|
||||||
<label class="polje-labela">Datum završetka</label>
|
<div>
|
||||||
<input type="date" name="datum_zavrsetka"
|
<label class="polje-labela">Datum prijema</label>
|
||||||
value="{{if .Nalog.DatumZavrsetka}}{{.Nalog.DatumZavrsetka.Format "2006-01-02"}}{{end}}"
|
<input type="date" name="datum_prijema"
|
||||||
style="width:100%;">
|
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>
|
||||||
<div>
|
<div>
|
||||||
<label class="polje-labela">Garancija do</label>
|
<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}}"
|
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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -172,4 +213,20 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</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}}
|
{{end}}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@
|
|||||||
</script>
|
</script>
|
||||||
{{end}}
|
{{end}}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body{{if .LokalnaAnimacija}} data-animacija="{{.LokalnaAnimacija}}"{{end}}{{if .LokalniHover}} data-hover="{{.LokalniHover}}"{{end}}>
|
||||||
<div class="raspored">
|
<div class="raspored">
|
||||||
<div class="sidebar-overlay" id="sidebar-overlay"></div>
|
<div class="sidebar-overlay" id="sidebar-overlay"></div>
|
||||||
{{template "sidebar" .}}
|
{{template "sidebar" .}}
|
||||||
|
|||||||
Reference in New Issue
Block a user