Servis: radni nalog za servisera, hover napomena, responsive popravke
- Nalepnica: uklonjen QR (ostaje na uređaju u servisu, klijent nema šta da skenira);
oslobođen prostor iskorišćen za telefon klijenta i datume (prijem + rok)
- Radni nalog: obrisani „servis_stampa" i „servis_predracun"; nov interni
„servis_radni_nalog" (ruta /servis/{id}/radni-nalog) sa podacima samo za
servisera, bez cena, sa barkodom i praznim poljima (dijagnoza, urađen rad, potpis)
- Forma „Izmeni nalog": kartice „Serviser" i „Avans i napomena" spojene u jednu
„Serviser, avans i napomena"
- Servis kanban: dugme uz SN broj otvara internu napomenu (hover na desktopu,
tap→focus na mobilnom); okidač na omotaču da napomena ne treperi
- Detalji naloga (responsive): forme „Dodaj rad/deo" izvučene iz inline grid-a u
klase + @media (2 kolone na telefonu); tabele radova/delova u tabela-skrol
This commit is contained in:
+1
-2
@@ -355,10 +355,9 @@ func main() {
|
|||||||
r.With(doz("servis.izmeni")).Post("/servis/izmeni/{id}", h.SacuvajIzmenaNaloga)
|
r.With(doz("servis.izmeni")).Post("/servis/izmeni/{id}", h.SacuvajIzmenaNaloga)
|
||||||
r.With(doz("servis.obrisi")).Post("/servis/obrisi/{id}", h.ObrisiNalog)
|
r.With(doz("servis.obrisi")).Post("/servis/obrisi/{id}", h.ObrisiNalog)
|
||||||
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "servis.pregled")).Get("/servis/{id}", h.DetaljiNaloga)
|
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "servis.pregled")).Get("/servis/{id}", h.DetaljiNaloga)
|
||||||
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "servis.pregled")).Get("/servis/{id}/stampa", h.StampaServisa)
|
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "servis.pregled")).Get("/servis/{id}/radni-nalog", h.StampaRadnogNaloga)
|
||||||
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "servis.pregled")).Get("/servis/{id}/otpremnica", h.StampaOtpremnice)
|
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "servis.pregled")).Get("/servis/{id}/otpremnica", h.StampaOtpremnice)
|
||||||
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "servis.pregled")).Get("/servis/{id}/nalepnica", h.StampaNalepnice)
|
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "servis.pregled")).Get("/servis/{id}/nalepnica", h.StampaNalepnice)
|
||||||
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "servis.pregled")).Get("/servis/{id}/predracun", h.StampaPredracuna)
|
|
||||||
r.With(doz("servis.izmeni")).Post("/servis/{id}/status", h.PromeniStatus)
|
r.With(doz("servis.izmeni")).Post("/servis/{id}/status", h.PromeniStatus)
|
||||||
r.With(doz("servis.izmeni")).Post("/servis/{id}/garancija", h.AzurirajGaranciju)
|
r.With(doz("servis.izmeni")).Post("/servis/{id}/garancija", h.AzurirajGaranciju)
|
||||||
r.With(doz("servis.izmeni")).Post("/servis/{id}/garancija-dana", h.AzurirajGarancijaDana)
|
r.With(doz("servis.izmeni")).Post("/servis/{id}/garancija-dana", h.AzurirajGarancijaDana)
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ var saSidebar = []string{
|
|||||||
|
|
||||||
// standalone su šabloni bez base layouta
|
// standalone su šabloni bez base layouta
|
||||||
var standaloneIme = []string{
|
var standaloneIme = []string{
|
||||||
"prijava", "setup", "totp_provera", "prodaja_stampa", "servis_stampa", "servis_otpremnica", "servis_predracun", "servis_nalepnica", "servis_status_javni",
|
"prijava", "setup", "totp_provera", "prodaja_stampa", "servis_radni_nalog", "servis_otpremnica", "servis_nalepnica", "servis_status_javni",
|
||||||
}
|
}
|
||||||
|
|
||||||
// sablonskeFunkcije su pomoćne funkcije dostupne u svim šablonima.
|
// sablonskeFunkcije su pomoćne funkcije dostupne u svim šablonima.
|
||||||
|
|||||||
+30
-185
@@ -1105,23 +1105,19 @@ func (h *Handler) renderujFormuNaloga(w http.ResponseWriter, podaci PodaciFormeN
|
|||||||
h.renderujTemplate(w, "servis_forma", podaci)
|
h.renderujTemplate(w, "servis_forma", podaci)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PodaciStampeServisa su podaci za print-friendly prikaz servisnog naloga
|
// PodaciRadnogNaloga su podaci za interni radni list servisera (bez cena)
|
||||||
type PodaciStampeServisa struct {
|
type PodaciRadnogNaloga struct {
|
||||||
Nalog model.ServisniNalog
|
Nalog model.ServisniNalog
|
||||||
ServisniDelovi []model.ServisniDeoSaArtiklom
|
ServisniDelovi []model.ServisniDeoSaArtiklom
|
||||||
UkupnoDelovi float64
|
|
||||||
KlijentNaziv string
|
KlijentNaziv string
|
||||||
|
KlijentTelefon string
|
||||||
TehnicarNaziv string
|
TehnicarNaziv string
|
||||||
NazivFirme string
|
NazivFirme string
|
||||||
Podnazlov string
|
Barkod string // base64 PNG Code128 barkoda broja naloga (za skener)
|
||||||
Adresa string
|
|
||||||
Telefon string
|
|
||||||
PIB string
|
|
||||||
QRKod string // base64 PNG QR koda sa URL-om naloga
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// StampaServisa renderuje print-friendly stranicu za servisni nalog
|
// StampaRadnogNaloga renderuje interni radni list koji serviser preuzima uz uređaj
|
||||||
func (h *Handler) StampaServisa(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) StampaRadnogNaloga(w http.ResponseWriter, r *http.Request) {
|
||||||
id, err := parseID(chi.URLParam(r, "id"))
|
id, err := parseID(chi.URLParam(r, "id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Neispravan ID naloga", http.StatusBadRequest)
|
http.Error(w, "Neispravan ID naloga", http.StatusBadRequest)
|
||||||
@@ -1147,6 +1143,7 @@ func (h *Handler) StampaServisa(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
klijentNaziv := ""
|
klijentNaziv := ""
|
||||||
|
klijentTelefon := ""
|
||||||
if nalog.KlijentID != nil {
|
if nalog.KlijentID != nil {
|
||||||
klijent, err := h.KlijentiRepo.DohvatiID(r.Context(), *nalog.KlijentID)
|
klijent, err := h.KlijentiRepo.DohvatiID(r.Context(), *nalog.KlijentID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -1155,6 +1152,7 @@ func (h *Handler) StampaServisa(w http.ResponseWriter, r *http.Request) {
|
|||||||
} else {
|
} else {
|
||||||
klijentNaziv = strings.TrimSpace(klijent.Ime + " " + klijent.Prezime)
|
klijentNaziv = strings.TrimSpace(klijent.Ime + " " + klijent.Prezime)
|
||||||
}
|
}
|
||||||
|
klijentTelefon = klijent.Telefon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1166,30 +1164,14 @@ func (h *Handler) StampaServisa(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var ukupnoDelovi float64
|
h.renderujStandalone(w, "servis_radni_nalog", PodaciRadnogNaloga{
|
||||||
for _, d := range delovi {
|
|
||||||
ukupnoDelovi += d.Ukupno()
|
|
||||||
}
|
|
||||||
|
|
||||||
// QR kod vodi na javnu status stranicu — dostupnu bez prijave
|
|
||||||
nalogURL := qrNalogURL(r, nalog.JavniToken)
|
|
||||||
var qrKod string
|
|
||||||
if png, err := qrcode.Encode(nalogURL, qrcode.Medium, 160); err == nil {
|
|
||||||
qrKod = base64.StdEncoding.EncodeToString(png)
|
|
||||||
}
|
|
||||||
|
|
||||||
h.renderujStandalone(w, "servis_stampa", PodaciStampeServisa{
|
|
||||||
Nalog: *nalog,
|
Nalog: *nalog,
|
||||||
ServisniDelovi: delovi,
|
ServisniDelovi: delovi,
|
||||||
UkupnoDelovi: ukupnoDelovi,
|
|
||||||
KlijentNaziv: klijentNaziv,
|
KlijentNaziv: klijentNaziv,
|
||||||
|
KlijentTelefon: klijentTelefon,
|
||||||
TehnicarNaziv: tehnicarNaziv,
|
TehnicarNaziv: tehnicarNaziv,
|
||||||
NazivFirme: podesavanja["naziv_firme"],
|
NazivFirme: podesavanja["naziv_firme"],
|
||||||
Podnazlov: podesavanja["podnazlov"],
|
Barkod: barkodNaloga(nalog.BrojNaloga),
|
||||||
Adresa: podesavanja["adresa"],
|
|
||||||
Telefon: podesavanja["telefon"],
|
|
||||||
PIB: podesavanja["pib"],
|
|
||||||
QRKod: qrKod,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1304,10 +1286,12 @@ func (h *Handler) StampaOtpremnice(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// PodaciNalepnice su podaci za malu nalepnicu (70×40 mm) koja se lepi na uređaj
|
// PodaciNalepnice su podaci za malu nalepnicu (70×40 mm) koja se lepi na uređaj
|
||||||
type PodaciNalepnice struct {
|
type PodaciNalepnice struct {
|
||||||
Nalog model.ServisniNalog
|
Nalog model.ServisniNalog
|
||||||
KlijentNaziv string
|
KlijentNaziv string
|
||||||
QRKod string // base64 PNG QR koda sa URL-om naloga
|
Telefon string // sirov telefon klijenta (formatira se u šablonu)
|
||||||
Barkod string // base64 PNG Code128 barkoda sa brojem naloga (za laserski skener)
|
DatumPrijema string // kratki format, npr. "20.06."
|
||||||
|
PredvidjenRok string // kratki format predviđenog datuma; prazno ako nije postavljen
|
||||||
|
Barkod string // base64 PNG Code128 barkoda sa brojem naloga (za laserski skener)
|
||||||
}
|
}
|
||||||
|
|
||||||
// barkodNaloga generiše Code128 barkod broja naloga kao base64 PNG; prazan string ako ne uspe
|
// barkodNaloga generiše Code128 barkod broja naloga kao base64 PNG; prazan string ako ne uspe
|
||||||
@@ -1343,6 +1327,7 @@ func (h *Handler) StampaNalepnice(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
klijentNaziv := ""
|
klijentNaziv := ""
|
||||||
|
telefon := ""
|
||||||
if nalog.KlijentID != nil {
|
if nalog.KlijentID != nil {
|
||||||
k, err := h.KlijentiRepo.DohvatiID(r.Context(), *nalog.KlijentID)
|
k, err := h.KlijentiRepo.DohvatiID(r.Context(), *nalog.KlijentID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -1351,164 +1336,24 @@ func (h *Handler) StampaNalepnice(w http.ResponseWriter, r *http.Request) {
|
|||||||
} else {
|
} else {
|
||||||
klijentNaziv = strings.TrimSpace(k.Ime + " " + k.Prezime)
|
klijentNaziv = strings.TrimSpace(k.Ime + " " + k.Prezime)
|
||||||
}
|
}
|
||||||
|
telefon = k.Telefon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nalogURL := qrNalogURL(r, nalog.JavniToken)
|
// kratki datumi za nalepnicu (npr. "20.06.")
|
||||||
var qrKod string
|
datumPrijema := nalog.DatumPrijema.Format("02.01.")
|
||||||
if png, err := qrcode.Encode(nalogURL, qrcode.Medium, 160); err == nil {
|
predvidjenRok := ""
|
||||||
qrKod = base64.StdEncoding.EncodeToString(png)
|
if nalog.PredvidjenDatum != nil {
|
||||||
|
predvidjenRok = nalog.PredvidjenDatum.Format("02.01.")
|
||||||
}
|
}
|
||||||
|
|
||||||
h.renderujStandalone(w, "servis_nalepnica", PodaciNalepnice{
|
h.renderujStandalone(w, "servis_nalepnica", PodaciNalepnice{
|
||||||
Nalog: *nalog,
|
Nalog: *nalog,
|
||||||
KlijentNaziv: klijentNaziv,
|
KlijentNaziv: klijentNaziv,
|
||||||
QRKod: qrKod,
|
Telefon: telefon,
|
||||||
Barkod: barkodNaloga(nalog.BrojNaloga),
|
DatumPrijema: datumPrijema,
|
||||||
})
|
PredvidjenRok: predvidjenRok,
|
||||||
}
|
Barkod: barkodNaloga(nalog.BrojNaloga),
|
||||||
|
|
||||||
// PodaciPredracuna su podaci za predračun/ponudu koja se šalje klijentu pre rada
|
|
||||||
type PodaciPredracuna struct {
|
|
||||||
Nalog model.ServisniNalog
|
|
||||||
ServisniDelovi []model.ServisniDeoSaArtiklom
|
|
||||||
UkupnoDelovi float64
|
|
||||||
|
|
||||||
ImaCenuRada bool // ima li nalog uopšte cenu rada (raspon ili fiksnu)
|
|
||||||
CenaRaspon bool // true → prikaži procenu Od–Do; false → fiksnu cenu
|
|
||||||
CenaRadaOd float64 // donja granica procene
|
|
||||||
CenaRadaDo float64 // gornja granica procene
|
|
||||||
CenaRada float64 // fiksna cena rada
|
|
||||||
|
|
||||||
UkupnoOd float64 // delovi + CenaRadaOd (kad je raspon)
|
|
||||||
UkupnoDo float64 // delovi + CenaRadaDo (kad je raspon)
|
|
||||||
Ukupno float64 // delovi + fiksna cena (ili samo delovi ako nema cene rada)
|
|
||||||
|
|
||||||
DatumIzdavanja time.Time
|
|
||||||
VaziDo time.Time
|
|
||||||
|
|
||||||
QRKod string
|
|
||||||
Klijent *model.Klijent
|
|
||||||
KlijentNaziv string
|
|
||||||
TehnicarNaziv string
|
|
||||||
NazivFirme string
|
|
||||||
Podnazlov string
|
|
||||||
Adresa string
|
|
||||||
Telefon string
|
|
||||||
PIB string
|
|
||||||
}
|
|
||||||
|
|
||||||
// StampaPredracuna renderuje predračun/ponudu koja se šalje klijentu kada se utvrdi kvar
|
|
||||||
func (h *Handler) StampaPredracuna(w http.ResponseWriter, r *http.Request) {
|
|
||||||
id, err := parseID(chi.URLParam(r, "id"))
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, "Neispravan ID naloga", http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
nalog, err := h.ServisRepo.DohvatiID(r.Context(), id)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, "Nalog nije pronađen", http.StatusNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
delovi, err := h.deloviSaPotrazivanima(r.Context(), id)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, "Greška pri učitavanju delova", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
podesavanja, err := sqlite.DohvatiSvaPodesavanja(r.Context(), h.DB)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, "Greška pri učitavanju podešavanja", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var klijent *model.Klijent
|
|
||||||
klijentNaziv := ""
|
|
||||||
if nalog.KlijentID != nil {
|
|
||||||
k, err := h.KlijentiRepo.DohvatiID(r.Context(), *nalog.KlijentID)
|
|
||||||
if err == nil {
|
|
||||||
klijent = k
|
|
||||||
if k.NazivFirme != "" {
|
|
||||||
klijentNaziv = k.NazivFirme
|
|
||||||
} else {
|
|
||||||
klijentNaziv = strings.TrimSpace(k.Ime + " " + k.Prezime)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tehnicarNaziv := ""
|
|
||||||
if nalog.TehnicarID != nil {
|
|
||||||
tehnicar, err := h.KorisniciRepo.DohvatiPoID(r.Context(), *nalog.TehnicarID)
|
|
||||||
if err == nil {
|
|
||||||
tehnicarNaziv = tehnicar.KorisnickoIme
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var ukupnoDelovi float64
|
|
||||||
for _, d := range delovi {
|
|
||||||
ukupnoDelovi += d.Ukupno()
|
|
||||||
}
|
|
||||||
|
|
||||||
// cena rada: ako postoji procena raspona (Od i Do) prikaži je, inače padni na fiksnu cenu
|
|
||||||
var imaCenuRada, cenaRaspon bool
|
|
||||||
var cenaRadaOd, cenaRadaDo, cenaRada float64
|
|
||||||
var ukupnoOd, ukupnoDo, ukupno float64
|
|
||||||
switch {
|
|
||||||
case nalog.CenaOd != nil && nalog.CenaDo != nil:
|
|
||||||
imaCenuRada = true
|
|
||||||
cenaRaspon = true
|
|
||||||
cenaRadaOd = *nalog.CenaOd
|
|
||||||
cenaRadaDo = *nalog.CenaDo
|
|
||||||
ukupnoOd = ukupnoDelovi + cenaRadaOd
|
|
||||||
ukupnoDo = ukupnoDelovi + cenaRadaDo
|
|
||||||
case nalog.CenaKonacna != nil:
|
|
||||||
imaCenuRada = true
|
|
||||||
cenaRada = *nalog.CenaKonacna
|
|
||||||
ukupno = ukupnoDelovi + cenaRada
|
|
||||||
default:
|
|
||||||
ukupno = ukupnoDelovi
|
|
||||||
}
|
|
||||||
|
|
||||||
// rok važenja iz podešavanja (default 7 dana)
|
|
||||||
rok := 7
|
|
||||||
if v, err := strconv.Atoi(podesavanja["predracun_rok_dana"]); err == nil && v > 0 {
|
|
||||||
rok = v
|
|
||||||
}
|
|
||||||
datumIzdavanja := time.Now()
|
|
||||||
vaziDo := datumIzdavanja.AddDate(0, 0, rok)
|
|
||||||
|
|
||||||
// QR kod vodi na javnu status stranicu — dostupnu bez prijave
|
|
||||||
nalogURL := qrNalogURL(r, nalog.JavniToken)
|
|
||||||
var qrKod string
|
|
||||||
if png, err := qrcode.Encode(nalogURL, qrcode.Medium, 160); err == nil {
|
|
||||||
qrKod = base64.StdEncoding.EncodeToString(png)
|
|
||||||
}
|
|
||||||
|
|
||||||
h.renderujStandalone(w, "servis_predracun", PodaciPredracuna{
|
|
||||||
Nalog: *nalog,
|
|
||||||
ServisniDelovi: delovi,
|
|
||||||
UkupnoDelovi: ukupnoDelovi,
|
|
||||||
ImaCenuRada: imaCenuRada,
|
|
||||||
CenaRaspon: cenaRaspon,
|
|
||||||
CenaRadaOd: cenaRadaOd,
|
|
||||||
CenaRadaDo: cenaRadaDo,
|
|
||||||
CenaRada: cenaRada,
|
|
||||||
UkupnoOd: ukupnoOd,
|
|
||||||
UkupnoDo: ukupnoDo,
|
|
||||||
Ukupno: ukupno,
|
|
||||||
DatumIzdavanja: datumIzdavanja,
|
|
||||||
VaziDo: vaziDo,
|
|
||||||
QRKod: qrKod,
|
|
||||||
Klijent: klijent,
|
|
||||||
KlijentNaziv: klijentNaziv,
|
|
||||||
TehnicarNaziv: tehnicarNaziv,
|
|
||||||
NazivFirme: podesavanja["naziv_firme"],
|
|
||||||
Podnazlov: podesavanja["podnazlov"],
|
|
||||||
Adresa: podesavanja["adresa"],
|
|
||||||
Telefon: podesavanja["telefon"],
|
|
||||||
PIB: podesavanja["pib"],
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1298,6 +1298,7 @@ select {
|
|||||||
/* kartica naloga u koloni — nasleđuje .kartica, dodaje kompaktan padding i hover */
|
/* kartica naloga u koloni — nasleđuje .kartica, dodaje kompaktan padding i hover */
|
||||||
.kanban-karta {
|
.kanban-karta {
|
||||||
display: block;
|
display: block;
|
||||||
|
position: relative;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -1307,6 +1308,72 @@ select {
|
|||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12);
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12);
|
||||||
}
|
}
|
||||||
|
/* dugme uz SN broj — otvara internu napomenu */
|
||||||
|
.napomena-omot {
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
.napomena-dugme {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 2px;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--sb-akcent);
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 5px;
|
||||||
|
line-height: 0;
|
||||||
|
opacity: 0.75;
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
transition: opacity 0.12s ease, background 0.12s ease;
|
||||||
|
}
|
||||||
|
.napomena-dugme:hover,
|
||||||
|
.napomena-dugme:focus {
|
||||||
|
opacity: 1;
|
||||||
|
background: var(--pozadina-hover);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
/* napomena kao overlay preko karte; ostaje u granicama karte → overflow kanbana je ne seče */
|
||||||
|
.karta-napomena {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
padding: 10px 12px;
|
||||||
|
background: var(--pozadina-kartica, var(--pozadina));
|
||||||
|
border: 1px solid var(--sb-akcent);
|
||||||
|
border-radius: inherit;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.45;
|
||||||
|
color: var(--tekst-glavni);
|
||||||
|
white-space: pre-wrap;
|
||||||
|
overflow: auto;
|
||||||
|
text-align: left;
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
transition: opacity 0.12s ease;
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
/* okidač je omot (ne dugme): pošto je napomena DOM-dete omota, hover nad samom
|
||||||
|
napomenom drži omot „hovered" → ostaje stabilno vidljiva, ne treperi.
|
||||||
|
focus-within pokriva tap na mobilnom (fokus dugmeta unutar omota). */
|
||||||
|
.napomena-omot:hover .karta-napomena,
|
||||||
|
.napomena-omot:focus-within .karta-napomena {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* forme „Dodaj rad/deo" u detaljima naloga — grid u CSS (ne inline) da ga @media može nadjačati */
|
||||||
|
.detalji-forma-rad { display: grid; grid-template-columns: 1fr 80px 120px auto; gap: 10px; align-items: flex-end; }
|
||||||
|
.detalji-forma-deo { display: grid; grid-template-columns: 1fr 70px 80px 120px auto; gap: 10px; align-items: flex-end; }
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
/* na telefonu: dve kolone, dugme preko cele širine */
|
||||||
|
.detalji-forma-rad,
|
||||||
|
.detalji-forma-deo { grid-template-columns: 1fr 1fr; }
|
||||||
|
.detalji-forma-rad > :last-child,
|
||||||
|
.detalji-forma-deo > :last-child { grid-column: 1 / -1; }
|
||||||
|
.detalji-forma-rad > :last-child .btn-primarno,
|
||||||
|
.detalji-forma-deo > :last-child .btn-primarno { width: 100%; }
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.nabavke-tabela { display: none; } .nabavke-kartice { display: flex; }
|
.nabavke-tabela { display: none; } .nabavke-kartice { display: flex; }
|
||||||
|
|||||||
@@ -48,8 +48,25 @@
|
|||||||
{{range $.Nalozi}}
|
{{range $.Nalozi}}
|
||||||
{{if eq .Status $status}}
|
{{if eq .Status $status}}
|
||||||
<a hx-boost="true" hx-target="#glavni-sadrzaj" hx-select="#glavni-sadrzaj" hx-swap="outerHTML" href="/servis/{{.ID}}" class="kartica kanban-karta">
|
<a hx-boost="true" hx-target="#glavni-sadrzaj" hx-select="#glavni-sadrzaj" hx-swap="outerHTML" href="/servis/{{.ID}}" class="kartica kanban-karta">
|
||||||
<div style="font-size:14px;font-weight:500;color:var(--sb-akcent);font-family:monospace;">
|
<div style="display:flex;align-items:center;gap:6px;">
|
||||||
{{.BrojNaloga}}
|
<span style="font-size:14px;font-weight:500;color:var(--sb-akcent);font-family:monospace;">{{.BrojNaloga}}</span>
|
||||||
|
{{if .Napomena}}
|
||||||
|
<!-- dugme uz SN broj otvara internu napomenu (hover na desktopu, tap→focus na mobilnom);
|
||||||
|
onclick sprečava da klik na dugme otvori sam nalog (kartica je hx-boost link) -->
|
||||||
|
<span class="napomena-omot">
|
||||||
|
<button type="button" class="napomena-dugme" aria-label="Interna napomena"
|
||||||
|
onclick="event.preventDefault();event.stopPropagation();">
|
||||||
|
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||||
|
stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
|
||||||
|
<polyline points="14 2 14 8 20 8"/>
|
||||||
|
<line x1="8" y1="13" x2="16" y2="13"/>
|
||||||
|
<line x1="8" y1="17" x2="13" y2="17"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div class="karta-napomena">{{.Napomena}}</div>
|
||||||
|
</span>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div style="font-size:13px;color:var(--tekst-glavni);margin-top:4px;">{{.Uredjaj}}</div>
|
<div style="font-size:13px;color:var(--tekst-glavni);margin-top:4px;">{{.Uredjaj}}</div>
|
||||||
{{if .KlijentNaziv}}
|
{{if .KlijentNaziv}}
|
||||||
|
|||||||
@@ -47,14 +47,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="display:flex;gap:8px;flex-wrap:wrap;">
|
<div style="display:flex;gap:8px;flex-wrap:wrap;">
|
||||||
{{if not (or (eq .Nalog.Status "Završeno") (eq .Nalog.Status "Preuzeto"))}}
|
<a href="/servis/{{.Nalog.ID}}/radni-nalog" target="_blank" class="btn-sekundarno">
|
||||||
<a href="/servis/{{.Nalog.ID}}/stampa" target="_blank" class="btn-sekundarno">
|
|
||||||
Radni nalog
|
Radni nalog
|
||||||
</a>
|
</a>
|
||||||
<a href="/servis/{{.Nalog.ID}}/predracun" target="_blank" class="btn-sekundarno">
|
|
||||||
Predračun
|
|
||||||
</a>
|
|
||||||
{{end}}
|
|
||||||
{{if or (eq .Nalog.Status "Završeno") (eq .Nalog.Status "Preuzeto")}}
|
{{if or (eq .Nalog.Status "Završeno") (eq .Nalog.Status "Preuzeto")}}
|
||||||
<a href="/servis/{{.Nalog.ID}}/otpremnica" target="_blank" class="btn-sekundarno">
|
<a href="/servis/{{.Nalog.ID}}/otpremnica" target="_blank" class="btn-sekundarno">
|
||||||
Otpremnica
|
Otpremnica
|
||||||
@@ -263,7 +258,7 @@
|
|||||||
{{if index .Dozvole "servis.izmeni"}}
|
{{if index .Dozvole "servis.izmeni"}}
|
||||||
<form method="POST" action="/servis/{{.Nalog.ID}}/radovi" style="margin-bottom:16px;" data-refresh="#radovi-spisak">
|
<form method="POST" action="/servis/{{.Nalog.ID}}/radovi" style="margin-bottom:16px;" data-refresh="#radovi-spisak">
|
||||||
<input type="hidden" name="_csrf" value="{{.CsrfToken}}">
|
<input type="hidden" name="_csrf" value="{{.CsrfToken}}">
|
||||||
<div style="display:grid;grid-template-columns:1fr 80px 120px auto;gap:10px;align-items:flex-end;">
|
<div class="detalji-forma-rad">
|
||||||
<div>
|
<div>
|
||||||
<label style="font-size:12px;color:var(--tekst-sporedni);display:block;margin-bottom:4px;">Usluga</label>
|
<label style="font-size:12px;color:var(--tekst-sporedni);display:block;margin-bottom:4px;">Usluga</label>
|
||||||
<select name="usluga_id" id="rad-usluga" style="width:100%;" required>
|
<select name="usluga_id" id="rad-usluga" style="width:100%;" required>
|
||||||
@@ -289,6 +284,7 @@
|
|||||||
<!-- lista radova -->
|
<!-- lista radova -->
|
||||||
<div id="radovi-spisak">
|
<div id="radovi-spisak">
|
||||||
{{if .ServisniRadovi}}
|
{{if .ServisniRadovi}}
|
||||||
|
<div class="tabela-skrol">
|
||||||
<table class="tabela">
|
<table class="tabela">
|
||||||
<thead>
|
<thead>
|
||||||
<tr style="border-bottom:0.5px solid var(--ivica);">
|
<tr style="border-bottom:0.5px solid var(--ivica);">
|
||||||
@@ -322,6 +318,7 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div style="font-size:13px;color:var(--tekst-sporedni);text-align:center;padding:16px 0;">
|
<div style="font-size:13px;color:var(--tekst-sporedni);text-align:center;padding:16px 0;">
|
||||||
Nema unetih radova. Dodaj uslugu iz cenovnika.
|
Nema unetih radova. Dodaj uslugu iz cenovnika.
|
||||||
@@ -344,7 +341,7 @@
|
|||||||
<label style="font-size:12px;color:var(--tekst-sporedni);display:block;margin-bottom:4px;">Kategorija</label>
|
<label style="font-size:12px;color:var(--tekst-sporedni);display:block;margin-bottom:4px;">Kategorija</label>
|
||||||
<select id="deo-kategorija" style="width:100%;"></select>
|
<select id="deo-kategorija" style="width:100%;"></select>
|
||||||
</div>
|
</div>
|
||||||
<div style="display:grid;grid-template-columns:1fr 70px 80px 120px auto;gap:10px;align-items:flex-end;">
|
<div class="detalji-forma-deo">
|
||||||
<div>
|
<div>
|
||||||
<label style="font-size:12px;color:var(--tekst-sporedni);display:block;margin-bottom:4px;">Artikal</label>
|
<label style="font-size:12px;color:var(--tekst-sporedni);display:block;margin-bottom:4px;">Artikal</label>
|
||||||
<select name="artikal_id" id="deo-artikal" style="width:100%;" required>
|
<select name="artikal_id" id="deo-artikal" style="width:100%;" required>
|
||||||
@@ -373,6 +370,7 @@
|
|||||||
<!-- lista delova -->
|
<!-- lista delova -->
|
||||||
<div id="delovi-spisak">
|
<div id="delovi-spisak">
|
||||||
{{if .ServisniDelovi}}
|
{{if .ServisniDelovi}}
|
||||||
|
<div class="tabela-skrol">
|
||||||
<table class="tabela">
|
<table class="tabela">
|
||||||
<thead>
|
<thead>
|
||||||
<tr style="border-bottom:0.5px solid var(--ivica);">
|
<tr style="border-bottom:0.5px solid var(--ivica);">
|
||||||
@@ -412,6 +410,7 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div style="font-size:13px;color:var(--tekst-sporedni);text-align:center;padding:16px 0;">
|
<div style="font-size:13px;color:var(--tekst-sporedni);text-align:center;padding:16px 0;">
|
||||||
Nema ugrađenih delova za ovaj nalog.
|
Nema ugrađenih delova za ovaj nalog.
|
||||||
|
|||||||
@@ -98,22 +98,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ===================== KARTICA: TEHNIČAR (izmena) / KLIJENT I TEHNIČAR (novi) ===================== -->
|
<!-- ===================== KARTICA: KLIJENT I SERVISER (samo novi nalog) ===================== -->
|
||||||
{{if .Izmena}}
|
{{if not .Izmena}}
|
||||||
<!-- pri izmeni klijent se ne menja (vezan pri prijemu) — ostaje samo serviser -->
|
|
||||||
<div class="kartica forma-kartica animiraj" style="margin-bottom:20px;">
|
|
||||||
<div class="sekcija-naslov">Serviser</div>
|
|
||||||
<div>
|
|
||||||
<label class="polje-labela">Serviser</label>
|
|
||||||
<select name="tehnicar_id" style="width:100%;">
|
|
||||||
<option value="">— nedodeljen —</option>
|
|
||||||
{{range .Tehnicari}}
|
|
||||||
<option value="{{.ID}}"{{if eq .ID $.Nalog.TehnicarIDVrednost}}selected{{end}}>{{.KorisnickoIme}}</option>
|
|
||||||
{{end}}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{else}}
|
|
||||||
<div class="kartica forma-kartica animiraj" x-data="klijentNalog" style="margin-bottom:20px;">
|
<div class="kartica forma-kartica animiraj" x-data="klijentNalog" style="margin-bottom:20px;">
|
||||||
<div class="sekcija-naslov">Klijent</div>
|
<div class="sekcija-naslov">Klijent</div>
|
||||||
<div class="kolona" style="gap:12px;">
|
<div class="kolona" style="gap:12px;">
|
||||||
@@ -269,11 +255,23 @@
|
|||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
<!-- ===================== KARTICA: AVANS, GARANCIJA I NAPOMENA ===================== -->
|
<!-- ===================== KARTICA: SERVISER, AVANS I NAPOMENA ===================== -->
|
||||||
<div class="kartica forma-kartica animiraj" style="margin-bottom:20px;">
|
<div class="kartica forma-kartica animiraj" style="margin-bottom:20px;">
|
||||||
<div class="sekcija-naslov">{{if .Izmena}}Avans, garancija i napomena{{else}}Avans i napomena{{end}}</div>
|
<div class="sekcija-naslov">{{if .Izmena}}Serviser, avans i napomena{{else}}Avans i napomena{{end}}</div>
|
||||||
<!-- cena rada se računa iz radova (usluga) u detaljima naloga; ovde samo avans -->
|
<!-- cena rada se računa iz radova (usluga) u detaljima naloga; ovde samo avans -->
|
||||||
<div class="forma-grid-2" style="display:grid;grid-template-columns:1fr 1fr;gap:12px;align-items:start;">
|
<div class="forma-grid-2" style="display:grid;grid-template-columns:1fr 1fr;gap:12px;align-items:start;">
|
||||||
|
{{if .Izmena}}
|
||||||
|
<!-- pri izmeni klijent se ne menja (vezan pri prijemu) — ostaje samo serviser -->
|
||||||
|
<div>
|
||||||
|
<label class="polje-labela">Serviser</label>
|
||||||
|
<select name="tehnicar_id" style="width:100%;">
|
||||||
|
<option value="">— nedodeljen —</option>
|
||||||
|
{{range .Tehnicari}}
|
||||||
|
<option value="{{.ID}}"{{if eq .ID $.Nalog.TehnicarIDVrednost}}selected{{end}}>{{.KorisnickoIme}}</option>
|
||||||
|
{{end}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
<div>
|
<div>
|
||||||
<label class="polje-labela">{{if .Izmena}}Avans{{else}}Avans / kapara{{end}}</label>
|
<label class="polje-labela">{{if .Izmena}}Avans{{else}}Avans / kapara{{end}}</label>
|
||||||
<input type="number" name="avans" min="0" step="0.01"
|
<input type="number" name="avans" min="0" step="0.01"
|
||||||
|
|||||||
@@ -29,17 +29,18 @@
|
|||||||
.barkod { flex: 0 0 auto; text-align: center; }
|
.barkod { flex: 0 0 auto; text-align: center; }
|
||||||
.barkod img { display: block; width: 100%; height: 9mm; object-fit: fill; }
|
.barkod img { display: block; width: 100%; height: 9mm; object-fit: fill; }
|
||||||
|
|
||||||
.donji-red { flex: 1; min-width: 0; display: flex; align-items: center; gap: 3mm; }
|
.donji-red { flex: 1; min-width: 0; display: flex; align-items: stretch; }
|
||||||
|
|
||||||
.podaci { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: 1.5mm; }
|
.podaci { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: 1.2mm; }
|
||||||
.broj { font-family: monospace; font-size: 14pt; font-weight: 700; line-height: 1.1; }
|
.broj { font-family: monospace; font-size: 14pt; font-weight: 700; line-height: 1.1; }
|
||||||
.red { font-size: 8pt; line-height: 1.25; }
|
.red { font-size: 8pt; line-height: 1.25; display: flex; gap: 2mm; }
|
||||||
.red .labela { color: #777; text-transform: uppercase; letter-spacing: .3px; font-size: 6.5pt; }
|
.red .labela { color: #777; text-transform: uppercase; letter-spacing: .3px; font-size: 6.5pt; flex: 0 0 14mm; align-self: center; }
|
||||||
.red .vrednost { font-weight: 600; word-break: break-word; }
|
.red .vrednost { font-weight: 600; word-break: break-word; }
|
||||||
.prazno { color: #aaa; font-style: italic; font-weight: 400; }
|
.prazno { color: #aaa; font-style: italic; font-weight: 400; }
|
||||||
|
.datumi { display: flex; gap: 5mm; font-size: 8pt; }
|
||||||
.qr { flex: 0 0 auto; }
|
.datumi .stavka { display: flex; gap: 1.5mm; align-items: baseline; }
|
||||||
.qr img { display: block; width: 22mm; height: 22mm; }
|
.datumi .labela { color: #777; text-transform: uppercase; letter-spacing: .3px; font-size: 6.5pt; }
|
||||||
|
.datumi .vrednost { font-weight: 600; }
|
||||||
|
|
||||||
@page { size: 70mm 40mm; margin: 0; }
|
@page { size: 70mm 40mm; margin: 0; }
|
||||||
@media print {
|
@media print {
|
||||||
@@ -60,14 +61,27 @@
|
|||||||
<div class="labela">Klijent</div>
|
<div class="labela">Klijent</div>
|
||||||
<div class="vrednost">{{if .KlijentNaziv}}{{.KlijentNaziv}}{{else}}<span class="prazno">—</span>{{end}}</div>
|
<div class="vrednost">{{if .KlijentNaziv}}{{.KlijentNaziv}}{{else}}<span class="prazno">—</span>{{end}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="red">
|
||||||
|
<div class="labela">Telefon</div>
|
||||||
|
<div class="vrednost">{{if .Telefon}}{{telefon .Telefon}}{{else}}<span class="prazno">—</span>{{end}}</div>
|
||||||
|
</div>
|
||||||
<div class="red">
|
<div class="red">
|
||||||
<div class="labela">Uređaj</div>
|
<div class="labela">Uređaj</div>
|
||||||
<div class="vrednost">{{if .Nalog.Uredjaj}}{{.Nalog.Uredjaj}}{{else}}<span class="prazno">—</span>{{end}}</div>
|
<div class="vrednost">{{if .Nalog.Uredjaj}}{{.Nalog.Uredjaj}}{{else}}<span class="prazno">—</span>{{end}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="datumi">
|
||||||
|
<div class="stavka">
|
||||||
|
<span class="labela">Primljen</span>
|
||||||
|
<span class="vrednost">{{.DatumPrijema}}</span>
|
||||||
|
</div>
|
||||||
|
{{if .PredvidjenRok}}
|
||||||
|
<div class="stavka">
|
||||||
|
<span class="labela">Rok</span>
|
||||||
|
<span class="vrednost">{{.PredvidjenRok}}</span>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{if .QRKod}}
|
|
||||||
<div class="qr"><img src="data:image/png;base64,{{.QRKod}}" alt="QR"></div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>window.addEventListener('load', function(){ window.print(); });</script>
|
<script>window.addEventListener('load', function(){ window.print(); });</script>
|
||||||
|
|||||||
@@ -1,263 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="sr">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Predračun — {{.Nalog.BrojNaloga}}</title>
|
|
||||||
<style>
|
|
||||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
||||||
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif; font-size: 13px; color: #111; background: #fff; }
|
|
||||||
|
|
||||||
.strana { max-width: 780px; margin: 0 auto; padding: 32px 40px; }
|
|
||||||
|
|
||||||
/* zaglavlje */
|
|
||||||
.zaglavlje { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 24px; padding-bottom: 16px; border-bottom: 2px solid #111; gap: 20px; }
|
|
||||||
.firma-naziv { font-size: 20px; font-weight: 700; }
|
|
||||||
.firma-info { font-size: 11px; color: #555; margin-top: 4px; line-height: 1.7; }
|
|
||||||
.dok-naslov { text-align: right; }
|
|
||||||
.dok-tip { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 1px; color: #555; margin-bottom: 4px; }
|
|
||||||
.dok-broj { font-size: 22px; font-weight: 700; font-family: monospace; }
|
|
||||||
.dok-datum { font-size: 12px; color: #555; margin-top: 6px; }
|
|
||||||
|
|
||||||
/* strane */
|
|
||||||
.strane-blok { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 20px; }
|
|
||||||
.strana-kartica { padding: 12px 14px; border: 0.5px solid #ddd; border-radius: 6px; }
|
|
||||||
.strana-tip { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.6px; color: #888; margin-bottom: 6px; }
|
|
||||||
.strana-naziv { font-size: 14px; font-weight: 600; }
|
|
||||||
.strana-info { font-size: 12px; color: #555; margin-top: 3px; line-height: 1.6; }
|
|
||||||
|
|
||||||
/* odeljci */
|
|
||||||
.odeljak { margin-bottom: 18px; }
|
|
||||||
.odeljak-naslov { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.8px; color: #555; margin-bottom: 8px; padding-bottom: 4px; border-bottom: 0.5px solid #ccc; }
|
|
||||||
|
|
||||||
/* podaci */
|
|
||||||
.podaci-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
|
|
||||||
.polje-labela { font-size: 10px; color: #777; text-transform: uppercase; letter-spacing: 0.4px; margin-bottom: 3px; }
|
|
||||||
.polje-vrednost { font-size: 13px; font-weight: 500; }
|
|
||||||
.polje-vrednost-mono { font-family: monospace; font-size: 13px; font-weight: 500; }
|
|
||||||
.polje-tekst { font-size: 13px; line-height: 1.6; white-space: pre-wrap; }
|
|
||||||
.prazno { color: #aaa; font-style: italic; }
|
|
||||||
|
|
||||||
/* tabela delova */
|
|
||||||
.tabela { width: 100%; border-collapse: collapse; margin-top: 6px; }
|
|
||||||
.tabela th { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.4px; color: #555; padding: 6px 8px; border-bottom: 1.5px solid #111; text-align: left; }
|
|
||||||
.tabela th.desno { text-align: right; }
|
|
||||||
.tabela td { padding: 7px 8px; border-bottom: 0.5px solid #ddd; font-size: 13px; vertical-align: middle; }
|
|
||||||
.tabela td.desno { text-align: right; }
|
|
||||||
.tabela .ukupno-red td { font-weight: 600; border-top: 1.5px solid #111; border-bottom: none; background: #fafafa; }
|
|
||||||
|
|
||||||
/* iznos procene */
|
|
||||||
.naplata-blok { display: flex; justify-content: space-between; align-items: center; padding: 12px 16px; border: 1.5px solid #111; border-radius: 6px; margin-top: 12px; }
|
|
||||||
.naplata-labela { font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.4px; }
|
|
||||||
.naplata-iznos { font-size: 22px; font-weight: 700; }
|
|
||||||
|
|
||||||
/* rok važenja */
|
|
||||||
.rok-blok { padding: 10px 14px; border: 0.5px solid #fcd34d; background: #fffbeb; border-radius: 6px; display: flex; justify-content: space-between; align-items: center; }
|
|
||||||
.rok-tekst { font-size: 12px; color: #92400e; font-weight: 500; }
|
|
||||||
.rok-datum { font-size: 15px; font-weight: 700; color: #92400e; }
|
|
||||||
|
|
||||||
/* potpisi */
|
|
||||||
.potpisi { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; margin-top: 36px; padding-top: 16px; border-top: 0.5px solid #ccc; }
|
|
||||||
.potpis-linija { border-top: 1px solid #888; margin-top: 44px; padding-top: 6px; font-size: 11px; color: #555; text-align: center; }
|
|
||||||
|
|
||||||
/* napomena na dnu */
|
|
||||||
.napomena-dno { margin-top: 20px; padding: 10px 14px; background: #f9fafb; border-left: 3px solid #ddd; font-size: 12px; color: #555; line-height: 1.6; }
|
|
||||||
|
|
||||||
@media print {
|
|
||||||
body { font-size: 12px; }
|
|
||||||
.strana { padding: 16px 20px; max-width: 100%; }
|
|
||||||
.dugme-stampa { display: none !important; }
|
|
||||||
@page { size: A4; margin: 12mm 14mm; }
|
|
||||||
}
|
|
||||||
.dugme-stampa { position: fixed; bottom: 24px; right: 24px; background: #111; color: #fff; border: none; padding: 12px 22px; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.2); }
|
|
||||||
.dugme-stampa:hover { background: #333; }
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="strana">
|
|
||||||
|
|
||||||
<!-- zaglavlje -->
|
|
||||||
<div class="zaglavlje">
|
|
||||||
<div>
|
|
||||||
<div class="firma-naziv">{{if .NazivFirme}}{{.NazivFirme}}{{else}}— naziv firme —{{end}}</div>
|
|
||||||
<div class="firma-info">
|
|
||||||
{{if .Podnazlov}}{{.Podnazlov}}<br>{{end}}
|
|
||||||
{{if .Adresa}}{{.Adresa}}<br>{{end}}
|
|
||||||
{{if .Telefon}}Tel: {{telefon .Telefon}}<br>{{end}}
|
|
||||||
{{if .PIB}}PIB: {{.PIB}}{{end}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="display:flex;align-items:flex-start;gap:14px;">
|
|
||||||
<div class="dok-naslov">
|
|
||||||
<div class="dok-tip">Predračun / Ponuda</div>
|
|
||||||
<div class="dok-broj">{{.Nalog.BrojNaloga}}</div>
|
|
||||||
<div class="dok-datum">Datum izdavanja: {{.DatumIzdavanja.Format "02.01.2006."}}</div>
|
|
||||||
<div class="dok-datum">Važi do: {{.VaziDo.Format "02.01.2006."}}</div>
|
|
||||||
</div>
|
|
||||||
{{if .QRKod}}
|
|
||||||
<img src="data:image/png;base64,{{.QRKod}}" width="76" height="76"
|
|
||||||
alt="QR {{.Nalog.BrojNaloga}}"
|
|
||||||
style="image-rendering:pixelated;border:1px solid #ddd;border-radius:4px;flex-shrink:0;">
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- izdavalac i klijent -->
|
|
||||||
<div class="strane-blok">
|
|
||||||
<div class="strana-kartica">
|
|
||||||
<div class="strana-tip">Izdaje</div>
|
|
||||||
<div class="strana-naziv">{{if .NazivFirme}}{{.NazivFirme}}{{else}}—{{end}}</div>
|
|
||||||
<div class="strana-info">
|
|
||||||
{{if .Adresa}}{{.Adresa}}<br>{{end}}
|
|
||||||
{{if .Telefon}}{{telefon .Telefon}}{{end}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="strana-kartica">
|
|
||||||
<div class="strana-tip">Za klijenta</div>
|
|
||||||
{{if .KlijentNaziv}}
|
|
||||||
<div class="strana-naziv">{{.KlijentNaziv}}</div>
|
|
||||||
<div class="strana-info">
|
|
||||||
{{if .Klijent}}
|
|
||||||
{{if .Klijent.Telefon}}Tel: {{telefon .Klijent.Telefon}}<br>{{end}}
|
|
||||||
{{if .Klijent.Email}}{{.Klijent.Email}}<br>{{end}}
|
|
||||||
{{if .Klijent.Mesto}}{{.Klijent.Mesto}}{{end}}
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
{{else}}
|
|
||||||
<div class="strana-naziv prazno">— klijent nije naveden —</div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- uređaj na servisu -->
|
|
||||||
<div class="odeljak">
|
|
||||||
<div class="odeljak-naslov">Uređaj na servisu</div>
|
|
||||||
<div class="podaci-grid" style="margin-bottom:10px;">
|
|
||||||
<div>
|
|
||||||
<div class="polje-labela">Naziv uređaja</div>
|
|
||||||
<div class="polje-vrednost">{{.Nalog.Uredjaj}}</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="polje-labela">Serijski broj</div>
|
|
||||||
<div class="polje-vrednost-mono">{{if .Nalog.SerijskiBroj}}{{.Nalog.SerijskiBroj}}{{else}}<span class="prazno">—</span>{{end}}</div>
|
|
||||||
</div>
|
|
||||||
{{if .TehnicarNaziv}}
|
|
||||||
<div>
|
|
||||||
<div class="polje-labela">Serviser</div>
|
|
||||||
<div class="polje-vrednost">{{.TehnicarNaziv}}</div>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- opis kvara -->
|
|
||||||
<div class="odeljak">
|
|
||||||
<div class="odeljak-naslov">Utvrđeni kvar</div>
|
|
||||||
<div class="polje-tekst">{{if .Nalog.OpisKvara}}{{.Nalog.OpisKvara}}{{else}}<span class="prazno">—</span>{{end}}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- predloženi delovi -->
|
|
||||||
{{if .ServisniDelovi}}
|
|
||||||
<div class="odeljak">
|
|
||||||
<div class="odeljak-naslov">Predloženi delovi i materijal</div>
|
|
||||||
<table class="tabela">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Artikal</th>
|
|
||||||
<th class="desno" style="width:70px;">Kol.</th>
|
|
||||||
<th class="desno" style="width:120px;">Cena/kom</th>
|
|
||||||
<th class="desno" style="width:120px;">Ukupno</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{{range .ServisniDelovi}}
|
|
||||||
<tr>
|
|
||||||
<td>{{.ArtikalNaziv}}</td>
|
|
||||||
<td class="desno">{{.Kolicina}}</td>
|
|
||||||
<td class="desno">{{dinari .CenaKomada}} din</td>
|
|
||||||
<td class="desno">{{dinari .Ukupno}} din</td>
|
|
||||||
</tr>
|
|
||||||
{{end}}
|
|
||||||
<tr class="ukupno-red">
|
|
||||||
<td colspan="3">Ukupno delovi</td>
|
|
||||||
<td class="desno">{{dinari .UkupnoDelovi}} din</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
<!-- procena troška -->
|
|
||||||
{{if .ImaCenuRada}}
|
|
||||||
<div class="odeljak">
|
|
||||||
<div class="odeljak-naslov">Procena troška</div>
|
|
||||||
<table class="tabela" style="margin-bottom:10px;">
|
|
||||||
<tbody>
|
|
||||||
{{if .CenaRaspon}}
|
|
||||||
<tr>
|
|
||||||
<td>Cena rada (procena)</td>
|
|
||||||
<td class="desno" style="width:200px;">{{dinari .CenaRadaOd}} – {{dinari .CenaRadaDo}} din</td>
|
|
||||||
</tr>
|
|
||||||
{{else}}
|
|
||||||
<tr>
|
|
||||||
<td>Cena rada</td>
|
|
||||||
<td class="desno" style="width:200px;">{{dinari .CenaRada}} din</td>
|
|
||||||
</tr>
|
|
||||||
{{end}}
|
|
||||||
{{if gt .UkupnoDelovi 0.0}}
|
|
||||||
<tr>
|
|
||||||
<td>Predloženi delovi i materijal</td>
|
|
||||||
<td class="desno">{{dinari .UkupnoDelovi}} din</td>
|
|
||||||
</tr>
|
|
||||||
{{end}}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div class="naplata-blok">
|
|
||||||
<div class="naplata-labela">Procena ukupnog troška:</div>
|
|
||||||
{{if .CenaRaspon}}
|
|
||||||
<div class="naplata-iznos">{{dinari .UkupnoOd}} – {{dinari .UkupnoDo}} din</div>
|
|
||||||
{{else}}
|
|
||||||
<div class="naplata-iznos">{{dinari .Ukupno}} din</div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{else}}
|
|
||||||
<div class="odeljak">
|
|
||||||
<div class="napomena-dno">Procena troška još nije utvrđena.</div>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
<!-- rok važenja -->
|
|
||||||
<div class="odeljak">
|
|
||||||
<div class="rok-blok">
|
|
||||||
<div class="rok-tekst">Ova ponuda važi do:</div>
|
|
||||||
<div class="rok-datum">{{.VaziDo.Format "02.01.2006."}}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{if .Nalog.Napomena}}
|
|
||||||
<div class="napomena-dno"><strong>Napomena:</strong> {{.Nalog.Napomena}}</div>
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
<div class="napomena-dno">
|
|
||||||
Ovo je predračun (ponuda) i ne predstavlja fiskalni dokument. Navedene cene su procena na osnovu
|
|
||||||
utvrđenog kvara; konačan iznos može odstupati ako se tokom servisa otkriju dodatni kvarovi.
|
|
||||||
Servis se započinje nakon saglasnosti klijenta.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- potpisi -->
|
|
||||||
<div class="potpisi">
|
|
||||||
<div>
|
|
||||||
<div class="potpis-linija">Ponudu izdao (firma)</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="potpis-linija">Saglasan sa ponudom (klijent)</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button class="dugme-stampa" onclick="window.print()">Štampaj</button>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
+61
-105
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Servisni nalog {{.Nalog.BrojNaloga}}</title>
|
<title>Radni nalog {{.Nalog.BrojNaloga}}</title>
|
||||||
<style>
|
<style>
|
||||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif; font-size: 13px; color: #111; background: #fff; }
|
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif; font-size: 13px; color: #111; background: #fff; }
|
||||||
@@ -11,15 +11,18 @@
|
|||||||
.strana { max-width: 780px; margin: 0 auto; padding: 32px 40px; }
|
.strana { max-width: 780px; margin: 0 auto; padding: 32px 40px; }
|
||||||
|
|
||||||
/* zaglavlje */
|
/* zaglavlje */
|
||||||
.zaglavlje { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 28px; padding-bottom: 16px; border-bottom: 2px solid #111; }
|
.zaglavlje { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 24px; padding-bottom: 14px; border-bottom: 2px solid #111; gap: 20px; }
|
||||||
.firma-naziv { font-size: 20px; font-weight: 700; }
|
.firma-naziv { font-size: 16px; font-weight: 700; }
|
||||||
.firma-info { font-size: 11px; color: #555; margin-top: 4px; line-height: 1.6; }
|
.firma-podnaslov { font-size: 11px; color: #666; text-transform: uppercase; letter-spacing: 1px; margin-top: 2px; }
|
||||||
.nalog-broj { text-align: right; }
|
.nalog-desno { text-align: right; }
|
||||||
.nalog-broj-vrednost { font-size: 22px; font-weight: 700; font-family: monospace; }
|
.nalog-naslov { font-size: 11px; color: #555; text-transform: uppercase; letter-spacing: 0.6px; margin-bottom: 2px; }
|
||||||
.nalog-naslov { font-size: 11px; color: #555; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px; }
|
.nalog-broj { font-size: 22px; font-weight: 700; font-family: monospace; }
|
||||||
|
.status { display: inline-block; margin-top: 6px; padding: 2px 10px; border-radius: 20px; font-size: 11px; font-weight: 600; border: 1.5px solid #111; }
|
||||||
|
.barkod { margin-top: 8px; }
|
||||||
|
.barkod img { display: block; height: 11mm; width: 52mm; object-fit: fill; margin-left: auto; }
|
||||||
|
|
||||||
/* odeljci */
|
/* odeljci */
|
||||||
.odeljak { margin-bottom: 20px; }
|
.odeljak { margin-bottom: 18px; }
|
||||||
.odeljak-naslov { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.8px; color: #555; margin-bottom: 8px; padding-bottom: 4px; border-bottom: 0.5px solid #ccc; }
|
.odeljak-naslov { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.8px; color: #555; margin-bottom: 8px; padding-bottom: 4px; border-bottom: 0.5px solid #ccc; }
|
||||||
|
|
||||||
/* grid sa podacima */
|
/* grid sa podacima */
|
||||||
@@ -27,76 +30,60 @@
|
|||||||
.podaci-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
|
.podaci-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
|
||||||
.polje-labela { font-size: 10px; color: #777; text-transform: uppercase; letter-spacing: 0.4px; margin-bottom: 3px; }
|
.polje-labela { font-size: 10px; color: #777; text-transform: uppercase; letter-spacing: 0.4px; margin-bottom: 3px; }
|
||||||
.polje-vrednost { font-size: 13px; font-weight: 500; }
|
.polje-vrednost { font-size: 13px; font-weight: 500; }
|
||||||
.polje-vrednost-mono { font-family: monospace; font-size: 13px; }
|
.polje-vrednost-mono { font-family: monospace; font-size: 14px; font-weight: 600; }
|
||||||
.polje-tekst { font-size: 13px; line-height: 1.6; white-space: pre-wrap; }
|
.polje-tekst { font-size: 13px; line-height: 1.6; white-space: pre-wrap; }
|
||||||
|
.prazno { color: #aaa; font-style: italic; }
|
||||||
|
|
||||||
/* status bedž */
|
/* istaknut PIN/lozinka — serviseru treba pristup */
|
||||||
.status { display: inline-block; padding: 2px 10px; border-radius: 20px; font-size: 11px; font-weight: 600; border: 1.5px solid #111; }
|
.pin-blok { display: inline-block; padding: 4px 12px; background: #fef9c3; border: 1px solid #facc15; border-radius: 6px; }
|
||||||
|
|
||||||
/* tabela delova */
|
/* tabela delova bez cena */
|
||||||
.tabela { width: 100%; border-collapse: collapse; margin-top: 8px; }
|
.tabela { width: 100%; border-collapse: collapse; margin-top: 6px; }
|
||||||
.tabela th { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.4px; color: #555; padding: 6px 8px; border-bottom: 1.5px solid #111; text-align: left; }
|
.tabela th { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.4px; color: #555; padding: 6px 8px; border-bottom: 1.5px solid #111; text-align: left; }
|
||||||
.tabela th.desno { text-align: right; }
|
.tabela th.desno { text-align: right; }
|
||||||
.tabela td { padding: 7px 8px; border-bottom: 0.5px solid #ddd; font-size: 13px; vertical-align: middle; }
|
.tabela td { padding: 7px 8px; border-bottom: 0.5px solid #ddd; font-size: 13px; }
|
||||||
.tabela td.desno { text-align: right; }
|
.tabela td.desno { text-align: right; }
|
||||||
.tabela .ukupno-red td { font-weight: 600; border-top: 1.5px solid #111; border-bottom: none; }
|
|
||||||
|
|
||||||
/* cene */
|
/* prazni okviri za rukom upisivanje */
|
||||||
.cene-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
|
.upis-okvir { border: 0.5px solid #bbb; border-radius: 6px; padding: 10px 12px; min-height: 70px; background:
|
||||||
.cena-blok { padding: 10px; border: 0.5px solid #ddd; border-radius: 6px; }
|
repeating-linear-gradient(to bottom, transparent, transparent 27px, #eee 27px, #eee 28px); }
|
||||||
.cena-labela { font-size: 10px; color: #777; text-transform: uppercase; letter-spacing: 0.4px; margin-bottom: 4px; }
|
.upis-veliki { min-height: 110px; }
|
||||||
.cena-vrednost { font-size: 16px; font-weight: 700; }
|
.upis-labela { font-size: 10px; color: #777; text-transform: uppercase; letter-spacing: 0.4px; margin-bottom: 6px; }
|
||||||
.cena-konacna { border-color: #111; }
|
|
||||||
|
|
||||||
/* potpisi */
|
/* zavrsetak — vreme i potpis */
|
||||||
.potpisi { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; margin-top: 32px; padding-top: 16px; border-top: 0.5px solid #ccc; }
|
.zavrsetak { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; margin-top: 28px; padding-top: 16px; border-top: 0.5px solid #ccc; }
|
||||||
.potpis-linija { border-top: 1px solid #888; margin-top: 40px; padding-top: 6px; font-size: 11px; color: #555; }
|
.linija { border-top: 1px solid #888; margin-top: 40px; padding-top: 6px; font-size: 11px; color: #555; }
|
||||||
|
|
||||||
/* štampa */
|
|
||||||
@media print {
|
@media print {
|
||||||
body { font-size: 12px; }
|
body { font-size: 12px; }
|
||||||
.strana { padding: 16px 20px; max-width: 100%; }
|
.strana { padding: 16px 20px; max-width: 100%; }
|
||||||
.dugme-stampa { display: none !important; }
|
.dugme-stampa { display: none !important; }
|
||||||
@page { size: A4; margin: 12mm 14mm; }
|
@page { size: A4; margin: 12mm 14mm; }
|
||||||
}
|
}
|
||||||
|
|
||||||
.dugme-stampa { position: fixed; bottom: 24px; right: 24px; background: #111; color: #fff; border: none; padding: 12px 22px; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.2); }
|
.dugme-stampa { position: fixed; bottom: 24px; right: 24px; background: #111; color: #fff; border: none; padding: 12px 22px; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.2); }
|
||||||
.dugme-stampa:hover { background: #333; }
|
.dugme-stampa:hover { background: #333; }
|
||||||
|
|
||||||
.prazno { color: #aaa; font-style: italic; }
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="strana">
|
<div class="strana">
|
||||||
|
|
||||||
<!-- zaglavlje firme i broj naloga -->
|
<!-- zaglavlje -->
|
||||||
<div class="zaglavlje">
|
<div class="zaglavlje">
|
||||||
<div>
|
<div>
|
||||||
<div class="firma-naziv">{{if .NazivFirme}}{{.NazivFirme}}{{else}}— naziv firme —{{end}}</div>
|
<div class="firma-naziv">{{if .NazivFirme}}{{.NazivFirme}}{{else}}— naziv firme —{{end}}</div>
|
||||||
<div class="firma-info">
|
<div class="firma-podnaslov">Radni nalog — interni</div>
|
||||||
{{if .Podnazlov}}{{.Podnazlov}}<br>{{end}}
|
|
||||||
{{if .Adresa}}{{.Adresa}}<br>{{end}}
|
|
||||||
{{if .Telefon}}Tel: {{telefon .Telefon}}<br>{{end}}
|
|
||||||
{{if .PIB}}PIB: {{.PIB}}{{end}}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="nalog-broj">
|
<div class="nalog-desno">
|
||||||
<div style="display:flex;align-items:flex-start;gap:14px;justify-content:flex-end;">
|
<div class="nalog-naslov">Broj naloga</div>
|
||||||
<div>
|
<div class="nalog-broj">{{.Nalog.BrojNaloga}}</div>
|
||||||
<div class="nalog-naslov">Servisni nalog</div>
|
<div><span class="status">{{.Nalog.Status}}</span></div>
|
||||||
<div class="nalog-broj-vrednost">{{.Nalog.BrojNaloga}}</div>
|
{{if .Barkod}}
|
||||||
<div style="margin-top:6px;"><span class="status">{{.Nalog.Status}}</span></div>
|
<div class="barkod"><img src="data:image/png;base64,{{.Barkod}}" alt="Barkod {{.Nalog.BrojNaloga}}"></div>
|
||||||
</div>
|
{{end}}
|
||||||
{{if .QRKod}}
|
|
||||||
<img src="data:image/png;base64,{{.QRKod}}" width="80" height="80"
|
|
||||||
alt="QR {{.Nalog.BrojNaloga}}"
|
|
||||||
style="image-rendering:pixelated;border:1px solid #ddd;border-radius:4px;">
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- datumi i klijent -->
|
<!-- osnovni podaci -->
|
||||||
<div class="odeljak">
|
<div class="odeljak">
|
||||||
<div class="odeljak-naslov">Osnovni podaci</div>
|
<div class="odeljak-naslov">Osnovni podaci</div>
|
||||||
<div class="podaci-grid">
|
<div class="podaci-grid">
|
||||||
@@ -104,26 +91,26 @@
|
|||||||
<div class="polje-labela">Datum prijema</div>
|
<div class="polje-labela">Datum prijema</div>
|
||||||
<div class="polje-vrednost">{{.Nalog.DatumPrijema.Format "02.01.2006. u 15:04"}}</div>
|
<div class="polje-vrednost">{{.Nalog.DatumPrijema.Format "02.01.2006. u 15:04"}}</div>
|
||||||
</div>
|
</div>
|
||||||
{{if .Nalog.DatumZavrsetka}}
|
{{if .Nalog.PredvidjenDatum}}
|
||||||
<div>
|
<div>
|
||||||
<div class="polje-labela">Datum završetka</div>
|
<div class="polje-labela">Predviđen rok</div>
|
||||||
<div class="polje-vrednost">{{.Nalog.DatumZavrsetka.Format "02.01.2006."}}</div>
|
<div class="polje-vrednost">{{.Nalog.PredvidjenDatum.Format "02.01.2006."}}</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .Nalog.GarancijaDo}}
|
{{if .TehnicarNaziv}}
|
||||||
<div>
|
<div>
|
||||||
<div class="polje-labela">Garancija do</div>
|
<div class="polje-labela">Serviser</div>
|
||||||
<div class="polje-vrednost">{{.Nalog.GarancijaDo.Format "02.01.2006."}}</div>
|
<div class="polje-vrednost">{{.TehnicarNaziv}}</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
<div>
|
<div>
|
||||||
<div class="polje-labela">Klijent</div>
|
<div class="polje-labela">Klijent</div>
|
||||||
<div class="polje-vrednost">{{if .KlijentNaziv}}{{.KlijentNaziv}}{{else}}<span class="prazno">—</span>{{end}}</div>
|
<div class="polje-vrednost">{{if .KlijentNaziv}}{{.KlijentNaziv}}{{else}}<span class="prazno">—</span>{{end}}</div>
|
||||||
</div>
|
</div>
|
||||||
{{if .TehnicarNaziv}}
|
{{if .KlijentTelefon}}
|
||||||
<div>
|
<div>
|
||||||
<div class="polje-labela">Serviser</div>
|
<div class="polje-labela">Telefon klijenta</div>
|
||||||
<div class="polje-vrednost">{{.TehnicarNaziv}}</div>
|
<div class="polje-vrednost">{{telefon .KlijentTelefon}}</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
@@ -144,12 +131,12 @@
|
|||||||
{{if .Nalog.PinUredjaja}}
|
{{if .Nalog.PinUredjaja}}
|
||||||
<div>
|
<div>
|
||||||
<div class="polje-labela">PIN / lozinka</div>
|
<div class="polje-labela">PIN / lozinka</div>
|
||||||
<div class="polje-vrednost-mono">{{.Nalog.PinUredjaja}}</div>
|
<div class="pin-blok polje-vrednost-mono">{{.Nalog.PinUredjaja}}</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-bottom:10px;">
|
<div style="margin-bottom:10px;">
|
||||||
<div class="polje-labela">Opis kvara</div>
|
<div class="polje-labela">Prijavljen kvar</div>
|
||||||
<div class="polje-tekst">{{if .Nalog.OpisKvara}}{{.Nalog.OpisKvara}}{{else}}<span class="prazno">—</span>{{end}}</div>
|
<div class="polje-tekst">{{if .Nalog.OpisKvara}}{{.Nalog.OpisKvara}}{{else}}<span class="prazno">—</span>{{end}}</div>
|
||||||
</div>
|
</div>
|
||||||
{{if .Nalog.TrazeneNadogradnje}}
|
{{if .Nalog.TrazeneNadogradnje}}
|
||||||
@@ -176,17 +163,15 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ugrađeni delovi -->
|
<!-- rezervisani/ugrađeni delovi — bez cena -->
|
||||||
{{if .ServisniDelovi}}
|
{{if .ServisniDelovi}}
|
||||||
<div class="odeljak">
|
<div class="odeljak">
|
||||||
<div class="odeljak-naslov">Ugrađeni delovi</div>
|
<div class="odeljak-naslov">Delovi na nalogu</div>
|
||||||
<table class="tabela">
|
<table class="tabela">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Artikal</th>
|
<th>Artikal</th>
|
||||||
<th class="desno" style="width:80px;">Kol.</th>
|
<th class="desno" style="width:90px;">Količina</th>
|
||||||
<th class="desno" style="width:130px;">Cena/kom</th>
|
|
||||||
<th class="desno" style="width:130px;">Ukupno</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -194,62 +179,33 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td>{{.ArtikalNaziv}}</td>
|
<td>{{.ArtikalNaziv}}</td>
|
||||||
<td class="desno">{{.Kolicina}}</td>
|
<td class="desno">{{.Kolicina}}</td>
|
||||||
<td class="desno">{{dinari .CenaKomada}} din</td>
|
|
||||||
<td class="desno">{{dinari .Ukupno}} din</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
<tr class="ukupno-red">
|
|
||||||
<td colspan="3">Ukupno delovi</td>
|
|
||||||
<td class="desno">{{dinari .UkupnoDelovi}} din</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
<!-- cene -->
|
<!-- prazna polja za servisera -->
|
||||||
<div class="odeljak">
|
<div class="odeljak">
|
||||||
<div class="odeljak-naslov">Cene usluge</div>
|
<div class="upis-labela">Dijagnoza / utvrđen kvar</div>
|
||||||
<div class="cene-grid">
|
<div class="upis-okvir upis-veliki"></div>
|
||||||
<div class="cena-blok">
|
|
||||||
<div class="cena-labela">Procena od</div>
|
|
||||||
<div class="cena-vrednost">{{if .Nalog.CenaOd}}{{.Nalog.CenaOdStr}} din{{else}}—{{end}}</div>
|
|
||||||
</div>
|
|
||||||
<div class="cena-blok">
|
|
||||||
<div class="cena-labela">Procena do</div>
|
|
||||||
<div class="cena-vrednost">{{if .Nalog.CenaDo}}{{.Nalog.CenaDoStr}} din{{else}}—{{end}}</div>
|
|
||||||
</div>
|
|
||||||
<div class="cena-blok">
|
|
||||||
<div class="cena-labela">Avans</div>
|
|
||||||
<div class="cena-vrednost">{{if .Nalog.Avans}}{{.Nalog.AvansStr}} din{{else}}—{{end}}</div>
|
|
||||||
</div>
|
|
||||||
<div class="cena-blok cena-konacna">
|
|
||||||
<div class="cena-labela">Cena rada</div>
|
|
||||||
<div class="cena-vrednost">{{if .Nalog.CenaKonacna}}{{.Nalog.CenaKonacnaStr}} din{{else}}—{{end}}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{if .Nalog.PreostaloZaNaplatu}}
|
|
||||||
<div style="margin-top:10px;padding:10px 14px;background:#f0fdf4;border:1px solid #86efac;border-radius:6px;display:flex;justify-content:space-between;align-items:center;">
|
|
||||||
<span style="font-size:12px;color:#15803d;font-weight:500;">Preostalo za naplatu:</span>
|
|
||||||
<span style="font-size:18px;font-weight:700;color:#15803d;">{{.Nalog.PreostaloZaNaplatuStr}} din</span>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{if .Nalog.Napomena}}
|
|
||||||
<div class="odeljak">
|
<div class="odeljak">
|
||||||
<div class="odeljak-naslov">Napomena</div>
|
<div class="upis-labela">Urađen rad</div>
|
||||||
<div class="polje-tekst" style="color:#555;">{{.Nalog.Napomena}}</div>
|
<div class="upis-okvir upis-veliki"></div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
|
||||||
|
|
||||||
<!-- potpisi -->
|
<!-- vreme i potpis -->
|
||||||
<div class="potpisi">
|
<div class="zavrsetak">
|
||||||
<div>
|
<div>
|
||||||
<div class="potpis-linija">Predao klijent</div>
|
<div class="polje-labela">Datum završetka / utrošeno vreme</div>
|
||||||
|
<div class="linija"> </div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="potpis-linija">Primio serviser</div>
|
<div class="polje-labela">Potpis servisera</div>
|
||||||
|
<div class="linija"> </div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
Reference in New Issue
Block a user