import React, { useEffect, useMemo, useState } from "react";
import { createRoot } from "react-dom/client";
import logo from "./assets/sentrypro-logo.png";
import "./styles.css";

const today = "2026-09-13";

const seedVisitors = [
  { id: 1, firstName:"Elvis", lastName:"Bukal", company:"AKD Zaštita", visiting:"Irma Kudrnja", reason:"Poslovni sastanak", site:"Skladište Istok", date:today, expected:"11:40", enteredAt:"10:29", exitedAt:"", status:"U OBJEKTU", plate:"ZG 1234 AB", card:"K-014", documentNumber:"OI 123456789", note:"" },
  { id: 2, firstName:"Ivan", lastName:"Horvat", company:"ABC d.o.o.", visiting:"Marko Marić", reason:"Servis protupožarnog sustava", site:"Poslovni centar Alfa", date:today, expected:"09:00", enteredAt:"10:25", exitedAt:"10:25", status:"IZAŠAO", plate:"", card:"", documentNumber:"OI 987654321", note:"Ulaz B" },
  { id: 3, firstName:"Maja", lastName:"Radić", company:"TechServis d.o.o.", visiting:"Recepcija", reason:"Dostava opreme", site:"Hotel Central", date:today, expected:"10:30", enteredAt:"10:25", exitedAt:"10:25", status:"IZAŠAO", plate:"ZG 5555 TR", card:"", documentNumber:"PUT 45678912", note:"" },
  { id: 4, firstName:"Ante", lastName:"Kovač", company:"ElektroDelta", visiting:"Ivan Jurić", reason:"Tehnički pregled", site:"Upravna zgrada", date:today, expected:"12:00", enteredAt:"", exitedAt:"", status:"NAJAVLJEN", plate:"", card:"K-021", documentNumber:"OI 741852963", note:"" },
  { id: 5, firstName:"Petra", lastName:"Babić", company:"CleanPro", visiting:"Recepcija", reason:"Čišćenje", site:"Poslovni centar Alfa", date:today, expected:"12:30", enteredAt:"", exitedAt:"", status:"NAJAVLJEN", plate:"", card:"", documentNumber:"OI 369258147", note:"" },
];

const seedEmployees = [
  {id:"emp-001",name:"Ivan Horvat",role:"Voditelj",site:"Skladište Istok",assignedSites:["Skladište Istok"],shift:"I",status:"Aktivan",phone:"+385 91 301 401",email:"demo001@sentrypro.invalid",cardNumber:"SI-260001",license:"Z-6001",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:1,baseGross:1350,workOrderNo:"RN-2026-0001",authorities:"Izrada i izmjena rasporeda; evidencija rada; kontrola ophodnji; odobravanje zahtjeva",workplace:"Voditelj",workLocation:"Skladište Istok"},
  {id:"emp-002",name:"Petar Kovač",role:"Zaštitar",site:"Skladište Istok",assignedSites:["Skladište Istok"],shift:"II",status:"Aktivan",phone:"+385 91 302 402",email:"demo002@sentrypro.invalid",cardNumber:"SI-260002",license:"Z-6002",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:2,baseGross:1300,workOrderNo:"RN-2026-0002",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Skladište Istok"},
  {id:"emp-003",name:"Luka Babić",role:"Zaštitar",site:"Skladište Istok",assignedSites:["Skladište Istok"],shift:"SL",status:"Aktivan",phone:"+385 91 303 403",email:"demo003@sentrypro.invalid",cardNumber:"SI-260003",license:"Z-6003",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:true,annualLeaveEntitlement:20,annualLeaveUsed:3,baseGross:1350,workOrderNo:"RN-2026-0003",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Skladište Istok"},
  {id:"emp-004",name:"Marko Marić",role:"Zaštitar",site:"Skladište Istok",assignedSites:["Skladište Istok"],shift:"SL",status:"Aktivan",phone:"+385 91 304 404",email:"demo004@sentrypro.invalid",cardNumber:"SI-260004",license:"Z-6004",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:4,baseGross:1200,workOrderNo:"RN-2026-0004",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Skladište Istok"},
  {id:"emp-005",name:"Josip Novak",role:"Voditelj",site:"Logistički centar Zapad",assignedSites:["Logistički centar Zapad"],shift:"I",status:"Aktivan",phone:"+385 91 305 405",email:"demo005@sentrypro.invalid",cardNumber:"SI-260005",license:"Z-6005",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:5,baseGross:1350,workOrderNo:"RN-2026-0005",authorities:"Izrada i izmjena rasporeda; evidencija rada; kontrola ophodnji; odobravanje zahtjeva",workplace:"Voditelj",workLocation:"Logistički centar Zapad"},
  {id:"emp-006",name:"Tomislav Jurić",role:"Zaštitar",site:"Logistički centar Zapad",assignedSites:["Logistički centar Zapad"],shift:"II",status:"Aktivan",phone:"+385 91 306 406",email:"demo006@sentrypro.invalid",cardNumber:"SI-260006",license:"Z-6006",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:true,annualLeaveEntitlement:20,annualLeaveUsed:6,baseGross:1300,workOrderNo:"RN-2026-0006",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Logistički centar Zapad"},
  {id:"emp-007",name:"Antonio Knežević",role:"Zaštitar",site:"Logistički centar Zapad",assignedSites:["Logistički centar Zapad"],shift:"SL",status:"Aktivan",phone:"+385 91 307 407",email:"demo007@sentrypro.invalid",cardNumber:"SI-260007",license:"Z-6007",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:0,baseGross:1350,workOrderNo:"RN-2026-0007",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Logistički centar Zapad"},
  {id:"emp-008",name:"Filip Pavić",role:"Zaštitar",site:"Logistički centar Zapad",assignedSites:["Logistički centar Zapad"],shift:"SL",status:"Aktivan",phone:"+385 91 308 408",email:"demo008@sentrypro.invalid",cardNumber:"SI-260008",license:"Z-6008",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:1,baseGross:1200,workOrderNo:"RN-2026-0008",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Logistički centar Zapad"},
  {id:"emp-009",name:"Karlo Radić",role:"Voditelj",site:"Poslovni centar Alfa",assignedSites:["Poslovni centar Alfa"],shift:"I",status:"Aktivan",phone:"+385 91 309 409",email:"demo009@sentrypro.invalid",cardNumber:"SI-260009",license:"Z-6009",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:true,annualLeaveEntitlement:20,annualLeaveUsed:2,baseGross:1350,workOrderNo:"RN-2026-0009",authorities:"Izrada i izmjena rasporeda; evidencija rada; kontrola ophodnji; odobravanje zahtjeva",workplace:"Voditelj",workLocation:"Poslovni centar Alfa"},
  {id:"emp-010",name:"Dario Božić",role:"Zaštitar",site:"Poslovni centar Alfa",assignedSites:["Poslovni centar Alfa"],shift:"II",status:"Aktivan",phone:"+385 91 310 410",email:"demo010@sentrypro.invalid",cardNumber:"SI-260010",license:"Z-6010",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:3,baseGross:1300,workOrderNo:"RN-2026-0010",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Poslovni centar Alfa"},
  {id:"emp-011",name:"Stjepan Šarić",role:"Zaštitar",site:"Poslovni centar Alfa",assignedSites:["Poslovni centar Alfa"],shift:"SL",status:"Aktivan",phone:"+385 91 311 411",email:"demo011@sentrypro.invalid",cardNumber:"SI-260011",license:"Z-6011",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:4,baseGross:1350,workOrderNo:"RN-2026-0011",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Poslovni centar Alfa"},
  {id:"emp-012",name:"Nikola Matić",role:"Zaštitar",site:"Poslovni centar Alfa",assignedSites:["Poslovni centar Alfa"],shift:"SL",status:"Aktivan",phone:"+385 91 312 412",email:"demo012@sentrypro.invalid",cardNumber:"SI-260012",license:"Z-6012",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:true,annualLeaveEntitlement:20,annualLeaveUsed:5,baseGross:1200,workOrderNo:"RN-2026-0012",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Poslovni centar Alfa"},
  {id:"emp-013",name:"Matej Perić",role:"Voditelj",site:"Hotel Central",assignedSites:["Hotel Central"],shift:"I",status:"Aktivan",phone:"+385 91 313 413",email:"demo013@sentrypro.invalid",cardNumber:"SI-260013",license:"Z-6013",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:6,baseGross:1350,workOrderNo:"RN-2026-0013",authorities:"Izrada i izmjena rasporeda; evidencija rada; kontrola ophodnji; odobravanje zahtjeva",workplace:"Voditelj",workLocation:"Hotel Central"},
  {id:"emp-014",name:"Ana Grgić",role:"Zaštitar",site:"Hotel Central",assignedSites:["Hotel Central"],shift:"II",status:"Aktivan",phone:"+385 91 314 414",email:"demo014@sentrypro.invalid",cardNumber:"SI-260014",license:"Z-6014",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:0,baseGross:1300,workOrderNo:"RN-2026-0014",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Hotel Central"},
  {id:"emp-015",name:"Marija Vuković",role:"Zaštitar",site:"Hotel Central",assignedSites:["Hotel Central"],shift:"SL",status:"Aktivan",phone:"+385 91 315 415",email:"demo015@sentrypro.invalid",cardNumber:"SI-260015",license:"Z-6015",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:true,annualLeaveEntitlement:20,annualLeaveUsed:1,baseGross:1350,workOrderNo:"RN-2026-0015",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Hotel Central"},
  {id:"emp-016",name:"Ivana Kralj",role:"Zaštitar",site:"Hotel Central",assignedSites:["Hotel Central"],shift:"SL",status:"Aktivan",phone:"+385 91 316 416",email:"demo016@sentrypro.invalid",cardNumber:"SI-260016",license:"Z-6016",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:2,baseGross:1200,workOrderNo:"RN-2026-0016",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Hotel Central"},
  {id:"emp-017",name:"Petra Marković",role:"Voditelj",site:"Upravna zgrada Sjever",assignedSites:["Upravna zgrada Sjever"],shift:"I",status:"Aktivan",phone:"+385 91 317 417",email:"demo017@sentrypro.invalid",cardNumber:"SI-260017",license:"Z-6017",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:3,baseGross:1350,workOrderNo:"RN-2026-0017",authorities:"Izrada i izmjena rasporeda; evidencija rada; kontrola ophodnji; odobravanje zahtjeva",workplace:"Voditelj",workLocation:"Upravna zgrada Sjever"},
  {id:"emp-018",name:"Martina Barišić",role:"Zaštitar",site:"Upravna zgrada Sjever",assignedSites:["Upravna zgrada Sjever"],shift:"II",status:"Aktivan",phone:"+385 91 318 418",email:"demo018@sentrypro.invalid",cardNumber:"SI-260018",license:"Z-6018",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:true,annualLeaveEntitlement:20,annualLeaveUsed:4,baseGross:1300,workOrderNo:"RN-2026-0018",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Upravna zgrada Sjever"},
  {id:"emp-019",name:"Lucija Milić",role:"Zaštitar",site:"Upravna zgrada Sjever",assignedSites:["Upravna zgrada Sjever"],shift:"SL",status:"Aktivan",phone:"+385 91 319 419",email:"demo019@sentrypro.invalid",cardNumber:"SI-260019",license:"Z-6019",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:5,baseGross:1350,workOrderNo:"RN-2026-0019",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Upravna zgrada Sjever"},
  {id:"emp-020",name:"Maja Lončar",role:"Zaštitar",site:"Upravna zgrada Sjever",assignedSites:["Upravna zgrada Sjever"],shift:"SL",status:"Aktivan",phone:"+385 91 320 420",email:"demo020@sentrypro.invalid",cardNumber:"SI-260020",license:"Z-6020",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:6,baseGross:1200,workOrderNo:"RN-2026-0020",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Upravna zgrada Sjever"},
  {id:"emp-021",name:"Katarina Tomić",role:"Voditelj",site:"Industrijski pogon Jug",assignedSites:["Industrijski pogon Jug"],shift:"I",status:"Aktivan",phone:"+385 91 321 421",email:"demo021@sentrypro.invalid",cardNumber:"SI-260021",license:"Z-6021",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:true,annualLeaveEntitlement:20,annualLeaveUsed:0,baseGross:1350,workOrderNo:"RN-2026-0021",authorities:"Izrada i izmjena rasporeda; evidencija rada; kontrola ophodnji; odobravanje zahtjeva",workplace:"Voditelj",workLocation:"Industrijski pogon Jug"},
  {id:"emp-022",name:"Nikolina Pavlović",role:"Zaštitar",site:"Industrijski pogon Jug",assignedSites:["Industrijski pogon Jug"],shift:"II",status:"Aktivan",phone:"+385 91 322 422",email:"demo022@sentrypro.invalid",cardNumber:"SI-260022",license:"Z-6022",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:1,baseGross:1300,workOrderNo:"RN-2026-0022",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Industrijski pogon Jug"},
  {id:"emp-023",name:"Tea Jukić",role:"Zaštitar",site:"Industrijski pogon Jug",assignedSites:["Industrijski pogon Jug"],shift:"SL",status:"Aktivan",phone:"+385 91 323 423",email:"demo023@sentrypro.invalid",cardNumber:"SI-260023",license:"Z-6023",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:2,baseGross:1350,workOrderNo:"RN-2026-0023",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Industrijski pogon Jug"},
  {id:"emp-024",name:"Sara Brkić",role:"Zaštitar",site:"Industrijski pogon Jug",assignedSites:["Industrijski pogon Jug"],shift:"SL",status:"Aktivan",phone:"+385 91 324 424",email:"demo024@sentrypro.invalid",cardNumber:"SI-260024",license:"Z-6024",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:true,annualLeaveEntitlement:20,annualLeaveUsed:3,baseGross:1200,workOrderNo:"RN-2026-0024",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Industrijski pogon Jug"},
  {id:"emp-025",name:"Iva Rajić",role:"Voditelj",site:"Distribucijski centar Sesvete",assignedSites:["Distribucijski centar Sesvete"],shift:"I",status:"Aktivan",phone:"+385 91 325 425",email:"demo025@sentrypro.invalid",cardNumber:"SI-260025",license:"Z-6025",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:4,baseGross:1350,workOrderNo:"RN-2026-0025",authorities:"Izrada i izmjena rasporeda; evidencija rada; kontrola ophodnji; odobravanje zahtjeva",workplace:"Voditelj",workLocation:"Distribucijski centar Sesvete"},
  {id:"emp-026",name:"Dominik Petrović",role:"Zaštitar",site:"Distribucijski centar Sesvete",assignedSites:["Distribucijski centar Sesvete"],shift:"II",status:"Aktivan",phone:"+385 91 326 426",email:"demo026@sentrypro.invalid",cardNumber:"SI-260026",license:"Z-6026",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:5,baseGross:1300,workOrderNo:"RN-2026-0026",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Distribucijski centar Sesvete"},
  {id:"emp-027",name:"Leon Prpić",role:"Zaštitar",site:"Distribucijski centar Sesvete",assignedSites:["Distribucijski centar Sesvete"],shift:"SL",status:"Aktivan",phone:"+385 91 327 427",email:"demo027@sentrypro.invalid",cardNumber:"SI-260027",license:"Z-6027",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:true,annualLeaveEntitlement:20,annualLeaveUsed:6,baseGross:1350,workOrderNo:"RN-2026-0027",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Distribucijski centar Sesvete"},
  {id:"emp-028",name:"Matija Nikolić",role:"Zaštitar",site:"Distribucijski centar Sesvete",assignedSites:["Distribucijski centar Sesvete"],shift:"SL",status:"Aktivan",phone:"+385 91 328 428",email:"demo028@sentrypro.invalid",cardNumber:"SI-260028",license:"Z-6028",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:0,baseGross:1200,workOrderNo:"RN-2026-0028",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Distribucijski centar Sesvete"},
  {id:"emp-029",name:"Fran Đurić",role:"Voditelj",site:"Trgovački centar Meridian",assignedSites:["Trgovački centar Meridian"],shift:"I",status:"Aktivan",phone:"+385 91 329 429",email:"demo029@sentrypro.invalid",cardNumber:"SI-260029",license:"Z-6029",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:1,baseGross:1350,workOrderNo:"RN-2026-0029",authorities:"Izrada i izmjena rasporeda; evidencija rada; kontrola ophodnji; odobravanje zahtjeva",workplace:"Voditelj",workLocation:"Trgovački centar Meridian"},
  {id:"emp-030",name:"Ante Jakšić",role:"Zaštitar",site:"Trgovački centar Meridian",assignedSites:["Trgovački centar Meridian"],shift:"II",status:"Aktivan",phone:"+385 91 330 430",email:"demo030@sentrypro.invalid",cardNumber:"SI-260030",license:"Z-6030",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:true,annualLeaveEntitlement:20,annualLeaveUsed:2,baseGross:1300,workOrderNo:"RN-2026-0030",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Trgovački centar Meridian"},
  {id:"emp-031",name:"Bruno Klarić",role:"Zaštitar",site:"Trgovački centar Meridian",assignedSites:["Trgovački centar Meridian"],shift:"SL",status:"Aktivan",phone:"+385 91 331 431",email:"demo031@sentrypro.invalid",cardNumber:"SI-260031",license:"Z-6031",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:3,baseGross:1350,workOrderNo:"RN-2026-0031",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Trgovački centar Meridian"},
  {id:"emp-032",name:"Mario Savić",role:"Zaštitar",site:"Trgovački centar Meridian",assignedSites:["Trgovački centar Meridian"],shift:"SL",status:"Aktivan",phone:"+385 91 332 432",email:"demo032@sentrypro.invalid",cardNumber:"SI-260032",license:"Z-6032",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:4,baseGross:1200,workOrderNo:"RN-2026-0032",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Trgovački centar Meridian"},
  {id:"emp-033",name:"Kristijan Krpan",role:"Voditelj",site:"Poslovna zgrada Orion",assignedSites:["Poslovna zgrada Orion"],shift:"I",status:"Aktivan",phone:"+385 91 333 433",email:"demo033@sentrypro.invalid",cardNumber:"SI-260033",license:"Z-6033",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:true,annualLeaveEntitlement:20,annualLeaveUsed:5,baseGross:1350,workOrderNo:"RN-2026-0033",authorities:"Izrada i izmjena rasporeda; evidencija rada; kontrola ophodnji; odobravanje zahtjeva",workplace:"Voditelj",workLocation:"Poslovna zgrada Orion"},
  {id:"emp-034",name:"Damir Blažević",role:"Zaštitar",site:"Poslovna zgrada Orion",assignedSites:["Poslovna zgrada Orion"],shift:"II",status:"Aktivan",phone:"+385 91 334 434",email:"demo034@sentrypro.invalid",cardNumber:"SI-260034",license:"Z-6034",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:6,baseGross:1300,workOrderNo:"RN-2026-0034",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Poslovna zgrada Orion"},
  {id:"emp-035",name:"Zoran Lovrić",role:"Zaštitar",site:"Poslovna zgrada Orion",assignedSites:["Poslovna zgrada Orion"],shift:"SL",status:"Aktivan",phone:"+385 91 335 435",email:"demo035@sentrypro.invalid",cardNumber:"SI-260035",license:"Z-6035",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:0,baseGross:1350,workOrderNo:"RN-2026-0035",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Poslovna zgrada Orion"},
  {id:"emp-036",name:"Goran Vidak",role:"Zaštitar",site:"Poslovna zgrada Orion",assignedSites:["Poslovna zgrada Orion"],shift:"SL",status:"Aktivan",phone:"+385 91 336 436",email:"demo036@sentrypro.invalid",cardNumber:"SI-260036",license:"Z-6036",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:true,annualLeaveEntitlement:20,annualLeaveUsed:1,baseGross:1200,workOrderNo:"RN-2026-0036",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Poslovna zgrada Orion"},
  {id:"emp-037",name:"Robert Jelić",role:"Voditelj",site:"Data centar Nova",assignedSites:["Data centar Nova"],shift:"I",status:"Aktivan",phone:"+385 91 337 437",email:"demo037@sentrypro.invalid",cardNumber:"SI-260037",license:"Z-6037",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:2,baseGross:1350,workOrderNo:"RN-2026-0037",authorities:"Izrada i izmjena rasporeda; evidencija rada; kontrola ophodnji; odobravanje zahtjeva",workplace:"Voditelj",workLocation:"Data centar Nova"},
  {id:"emp-038",name:"Marin Benković",role:"Zaštitar",site:"Data centar Nova",assignedSites:["Data centar Nova"],shift:"II",status:"Aktivan",phone:"+385 91 338 438",email:"demo038@sentrypro.invalid",cardNumber:"SI-260038",license:"Z-6038",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:3,baseGross:1300,workOrderNo:"RN-2026-0038",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Data centar Nova"},
  {id:"emp-039",name:"Vedran Gudelj",role:"Zaštitar",site:"Data centar Nova",assignedSites:["Data centar Nova"],shift:"SL",status:"Aktivan",phone:"+385 91 339 439",email:"demo039@sentrypro.invalid",cardNumber:"SI-260039",license:"Z-6039",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:true,annualLeaveEntitlement:20,annualLeaveUsed:4,baseGross:1350,workOrderNo:"RN-2026-0039",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Data centar Nova"},
  {id:"emp-040",name:"Hrvoje Šimić",role:"Zaštitar",site:"Data centar Nova",assignedSites:["Data centar Nova"],shift:"SL",status:"Aktivan",phone:"+385 91 340 440",email:"demo040@sentrypro.invalid",cardNumber:"SI-260040",license:"Z-6040",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:5,baseGross:1200,workOrderNo:"RN-2026-0040",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Data centar Nova"},
  {id:"emp-041",name:"Nina Bilić",role:"Voditelj",site:"Banka Centar",assignedSites:["Banka Centar"],shift:"I",status:"Aktivan",phone:"+385 91 341 441",email:"demo041@sentrypro.invalid",cardNumber:"SI-260041",license:"Z-6041",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:6,baseGross:1350,workOrderNo:"RN-2026-0041",authorities:"Izrada i izmjena rasporeda; evidencija rada; kontrola ophodnji; odobravanje zahtjeva",workplace:"Voditelj",workLocation:"Banka Centar"},
  {id:"emp-042",name:"Laura Mandić",role:"Zaštitar",site:"Banka Centar",assignedSites:["Banka Centar"],shift:"SL",status:"Aktivan",phone:"+385 91 342 442",email:"demo042@sentrypro.invalid",cardNumber:"SI-260042",license:"Z-6042",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:true,annualLeaveEntitlement:20,annualLeaveUsed:0,baseGross:1300,workOrderNo:"RN-2026-0042",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Banka Centar"},
  {id:"emp-043",name:"Ema Zebić",role:"Voditelj",site:"Banka Maksimir",assignedSites:["Banka Maksimir"],shift:"I",status:"Aktivan",phone:"+385 91 343 443",email:"demo043@sentrypro.invalid",cardNumber:"SI-260043",license:"Z-6043",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:1,baseGross:1350,workOrderNo:"RN-2026-0043",authorities:"Izrada i izmjena rasporeda; evidencija rada; kontrola ophodnji; odobravanje zahtjeva",workplace:"Voditelj",workLocation:"Banka Maksimir"},
  {id:"emp-044",name:"Mia Klarić",role:"Zaštitar",site:"Banka Maksimir",assignedSites:["Banka Maksimir"],shift:"SL",status:"Aktivan",phone:"+385 91 344 444",email:"demo044@sentrypro.invalid",cardNumber:"SI-260044",license:"Z-6044",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:2,baseGross:1200,workOrderNo:"RN-2026-0044",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Banka Maksimir"},
  {id:"emp-045",name:"Dora Kozina",role:"Voditelj",site:"Banka Trešnjevka",assignedSites:["Banka Trešnjevka"],shift:"I",status:"Aktivan",phone:"+385 91 345 445",email:"demo045@sentrypro.invalid",cardNumber:"SI-260045",license:"Z-6045",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:true,annualLeaveEntitlement:20,annualLeaveUsed:3,baseGross:1350,workOrderNo:"RN-2026-0045",authorities:"Izrada i izmjena rasporeda; evidencija rada; kontrola ophodnji; odobravanje zahtjeva",workplace:"Voditelj",workLocation:"Banka Trešnjevka"},
  {id:"emp-046",name:"Andrea Mikulić",role:"Zaštitar",site:"Banka Trešnjevka",assignedSites:["Banka Trešnjevka"],shift:"SL",status:"Aktivan",phone:"+385 91 346 446",email:"demo046@sentrypro.invalid",cardNumber:"SI-260046",license:"Z-6046",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:4,baseGross:1300,workOrderNo:"RN-2026-0046",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Banka Trešnjevka"},
  {id:"emp-047",name:"Helena Maretić",role:"Voditelj",site:"Uredski centar Dubrava",assignedSites:["Uredski centar Dubrava"],shift:"I",status:"Aktivan",phone:"+385 91 347 447",email:"demo047@sentrypro.invalid",cardNumber:"SI-260047",license:"Z-6047",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:5,baseGross:1350,workOrderNo:"RN-2026-0047",authorities:"Izrada i izmjena rasporeda; evidencija rada; kontrola ophodnji; odobravanje zahtjeva",workplace:"Voditelj",workLocation:"Uredski centar Dubrava"},
  {id:"emp-048",name:"Lorena Pejić",role:"Zaštitar",site:"Uredski centar Dubrava",assignedSites:["Uredski centar Dubrava"],shift:"SL",status:"Aktivan",phone:"+385 91 348 448",email:"demo048@sentrypro.invalid",cardNumber:"SI-260048",license:"Z-6048",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:true,annualLeaveEntitlement:20,annualLeaveUsed:6,baseGross:1200,workOrderNo:"RN-2026-0048",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Uredski centar Dubrava"},
  {id:"emp-049",name:"Tena Varga",role:"Voditelj",site:"Administrativni objekt Zapad",assignedSites:["Administrativni objekt Zapad"],shift:"I",status:"Aktivan",phone:"+385 91 349 449",email:"demo049@sentrypro.invalid",cardNumber:"SI-260049",license:"Z-6049",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:0,baseGross:1350,workOrderNo:"RN-2026-0049",authorities:"Izrada i izmjena rasporeda; evidencija rada; kontrola ophodnji; odobravanje zahtjeva",workplace:"Voditelj",workLocation:"Administrativni objekt Zapad"},
  {id:"emp-050",name:"Barbara Župan",role:"Zaštitar",site:"Administrativni objekt Zapad",assignedSites:["Administrativni objekt Zapad"],shift:"SL",status:"Aktivan",phone:"+385 91 350 450",email:"demo050@sentrypro.invalid",cardNumber:"SI-260050",license:"Z-6050",licenseExpiry:"2029-12-31",employmentDate:"2024-01-15",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:1,baseGross:1300,workOrderNo:"RN-2026-0050",authorities:"Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Administrativni objekt Zapad"},
  {id:"emp-051",name:"Mislav Barišić",role:"Zaštitar",site:"Erste banka",assignedSites:["Erste banka"],shift:"I",status:"Aktivan",phone:"+385 91 351 451",email:"demo051@sentrypro.invalid",cardNumber:"SI-260051",license:"Z-6051",licenseExpiry:"2029-12-31",employmentDate:"2026-09-14",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:false,annualLeaveEntitlement:20,annualLeaveUsed:0,baseGross:1300,workOrderNo:"RN-2026-0051",authorities:"Kontrola ulaza/izlaza; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Erste banka"},
  {id:"emp-052",name:"Krešimir Vuković",role:"Zaštitar",site:"Erste banka",assignedSites:["Erste banka"],shift:"SL",status:"Aktivan",phone:"+385 91 352 452",email:"demo052@sentrypro.invalid",cardNumber:"SI-260052",license:"Z-6052",licenseExpiry:"2029-12-31",employmentDate:"2026-09-14",active:true,vehiclePlate:"",vehicleAccess:false,replacementAvailable:true,annualLeaveEntitlement:20,annualLeaveUsed:0,baseGross:1300,workOrderNo:"RN-2026-0052",authorities:"Kontrola ulaza/izlaza; evidencija događaja; postupanje prema radnom nalogu",workplace:"Zaštitar",workLocation:"Erste banka"}

];

const seedSites = [
  {id:"site-01",name:"Skladište Istok",client:"Demo klijent 01",city:"Zagreb",address:"Demo adresa 1",contact:"Kontakt objekta 1",phone:"+385 1 600 0100",guards:4,is247:true,workingHours:"00:00–24:00",mail:"objekt01@sentrypro.invalid",camera:true,gate:false,status:"Aktivan"},
  {id:"site-02",name:"Logistički centar Zapad",client:"Demo klijent 02",city:"Zagreb",address:"Demo adresa 2",contact:"Kontakt objekta 2",phone:"+385 1 600 0200",guards:4,is247:true,workingHours:"00:00–24:00",mail:"objekt02@sentrypro.invalid",camera:true,gate:true,status:"Aktivan"},
  {id:"site-03",name:"Poslovni centar Alfa",client:"Demo klijent 03",city:"Zagreb",address:"Demo adresa 3",contact:"Kontakt objekta 3",phone:"+385 1 600 0300",guards:4,is247:true,workingHours:"00:00–24:00",mail:"objekt03@sentrypro.invalid",camera:true,gate:false,status:"Aktivan"},
  {id:"site-04",name:"Hotel Central",client:"Demo klijent 04",city:"Zagreb",address:"Demo adresa 4",contact:"Kontakt objekta 4",phone:"+385 1 600 0400",guards:4,is247:true,workingHours:"00:00–24:00",mail:"objekt04@sentrypro.invalid",camera:true,gate:true,status:"Aktivan"},
  {id:"site-05",name:"Upravna zgrada Sjever",client:"Demo klijent 05",city:"Zagreb",address:"Demo adresa 5",contact:"Kontakt objekta 5",phone:"+385 1 600 0500",guards:4,is247:true,workingHours:"00:00–24:00",mail:"objekt05@sentrypro.invalid",camera:true,gate:false,status:"Aktivan"},
  {id:"site-06",name:"Industrijski pogon Jug",client:"Demo klijent 06",city:"Zagreb",address:"Demo adresa 6",contact:"Kontakt objekta 6",phone:"+385 1 600 0600",guards:4,is247:true,workingHours:"00:00–24:00",mail:"objekt06@sentrypro.invalid",camera:true,gate:true,status:"Aktivan"},
  {id:"site-07",name:"Distribucijski centar Sesvete",client:"Demo klijent 07",city:"Zagreb",address:"Demo adresa 7",contact:"Kontakt objekta 7",phone:"+385 1 600 0700",guards:4,is247:true,workingHours:"00:00–24:00",mail:"objekt07@sentrypro.invalid",camera:true,gate:false,status:"Aktivan"},
  {id:"site-08",name:"Trgovački centar Meridian",client:"Demo klijent 08",city:"Zagreb",address:"Demo adresa 8",contact:"Kontakt objekta 8",phone:"+385 1 600 0800",guards:4,is247:true,workingHours:"00:00–24:00",mail:"objekt08@sentrypro.invalid",camera:true,gate:true,status:"Aktivan"},
  {id:"site-09",name:"Poslovna zgrada Orion",client:"Demo klijent 09",city:"Zagreb",address:"Demo adresa 9",contact:"Kontakt objekta 9",phone:"+385 1 600 0900",guards:4,is247:true,workingHours:"00:00–24:00",mail:"objekt09@sentrypro.invalid",camera:true,gate:false,status:"Aktivan"},
  {id:"site-10",name:"Data centar Nova",client:"Demo klijent 10",city:"Zagreb",address:"Demo adresa 10",contact:"Kontakt objekta 10",phone:"+385 1 600 1000",guards:4,is247:true,workingHours:"00:00–24:00",mail:"objekt10@sentrypro.invalid",camera:true,gate:true,status:"Aktivan"},
  {id:"site-11",name:"Banka Centar",client:"Demo klijent 11",city:"Zagreb",address:"Demo adresa 11",contact:"Kontakt objekta 11",phone:"+385 1 600 1100",guards:2,is247:false,workingHours:"08:00–20:00",mail:"objekt11@sentrypro.invalid",camera:true,gate:false,status:"Aktivan"},
  {id:"site-12",name:"Banka Maksimir",client:"Demo klijent 12",city:"Zagreb",address:"Demo adresa 12",contact:"Kontakt objekta 12",phone:"+385 1 600 1200",guards:2,is247:false,workingHours:"08:00–20:00",mail:"objekt12@sentrypro.invalid",camera:true,gate:true,status:"Aktivan"},
  {id:"site-13",name:"Banka Trešnjevka",client:"Demo klijent 13",city:"Zagreb",address:"Demo adresa 13",contact:"Kontakt objekta 13",phone:"+385 1 600 1300",guards:2,is247:false,workingHours:"08:00–20:00",mail:"objekt13@sentrypro.invalid",camera:true,gate:false,status:"Aktivan"},
  {id:"site-14",name:"Uredski centar Dubrava",client:"Demo klijent 14",city:"Zagreb",address:"Demo adresa 14",contact:"Kontakt objekta 14",phone:"+385 1 600 1400",guards:2,is247:false,workingHours:"07:00–19:00",mail:"objekt14@sentrypro.invalid",camera:true,gate:true,status:"Aktivan"},
  {id:"site-15",name:"Administrativni objekt Zapad",client:"Demo klijent 15",city:"Zagreb",address:"Demo adresa 15",contact:"Kontakt objekta 15",phone:"+385 1 600 1500",guards:2,is247:false,workingHours:"07:00–19:00",mail:"objekt15@sentrypro.invalid",camera:true,gate:false,status:"Aktivan"}
];


const seedAccessEvents = [
  {id:1,type:"KARTICA",employee:"Ivan Horvat",card:"ISK-001",site:"Poslovni centar Alfa",direction:"ULAZ",time:"07:01",date:today,result:"ODOBRENO"},
  {id:2,type:"LPR",employee:"Ana Kovač",plate:"ZG 2002 BB",site:"Hotel Central",direction:"ULAZ",time:"06:55",date:today,result:"RAMPA OTVORENA"},
  {id:3,type:"KARTICA",employee:"Marko Marić",card:"ISK-003",site:"Skladište Istok",direction:"ULAZ",time:"07:43",date:today,result:"ODOBRENO"},
];

const seedMessages = [
  {id:1,from:"Ivan Horvat",site:"Poslovni centar Alfa",to:"Voditelj",priority:"VISOKO",text:"Sumnjivo vozilo zadržava se uz servisni ulaz.",time:"10:12",status:"DOSTAVLJENO",ai:"Provjeriti situaciju; CDS nije automatski aktiviran."},
];

const seedShiftRequests = [
  {id:1,employee:"Ivan Horvat",site:"Poslovni centar Alfa",month:"2026-10",request:"SL",dateWanted:"2026-10-08",note:"Privatna obveza",created:"2026-09-12",status:"NA ČEKANJU"},
];

const seedReports = [
  {id:1,reportNo:"RI-2026-000001",date:"2026-09-13",time:"19:04",site:"Skladište Istok",author:"Petar Kovač",authorId:"emp-002",authorRole:"Zaštitar",type:"REDOVNO",shift:"I",title:"Redovno izvješće smjene",summary:"Smjena protekla uredno. Kontrola ulaza i izlaza te redovni obilasci provedeni prema radnom nalogu.",tasks:"Preuzeta službena oprema i ključevi; provedena kontrola ulaza; izvršeni redovni obilasci objekta.",observations:"Nisu utvrđene sigurnosno značajne nepravilnosti.",handover:"Službena oprema, ključevi i evidencije predani sljedećoj smjeni uredno.",noEvents:true,status:"PREDANO",managerStatus:"NOVO",submittedAt:"2026-09-13T19:04:00",forwardedToDirector:false},
  {id:2,reportNo:"ID-2026-000001",date:"2026-09-12",time:"22:18",site:"Hotel Central",author:"Ana Grgić",authorId:"emp-014",authorRole:"Zaštitar",type:"IZVANREDNO",title:"Izvješće o izvanrednom događaju",eventDate:"2026-09-12",eventTime:"21:42",eventLocation:"Servisni ulaz",chronology:"Tijekom obilaska uočena su otvorena servisna vrata bez prisutnosti ovlaštene osobe. Prostor je odmah provjeren i osiguran.",actions:"Osiguran je pristup, obaviješten voditelj smjene i izvršen dodatni pregled neposrednog prostora.",notified:"Voditelj smjene",persons:"Nema utvrđenih neovlaštenih osoba.",damage:"Nije utvrđena šteta.",finalState:"Vrata su zatvorena i osigurana. Objekt je nastavljen nadzirati bez daljnjih odstupanja.",status:"PREDANO",managerStatus:"PROČITANO",submittedAt:"2026-09-12T22:18:00",requestedBy:"Matej Perić",requestReason:"Sastaviti službeno izvješće o zatečenim otvorenim servisnim vratima.",forwardedToDirector:true,forwardedAt:"2026-09-12T22:25:00",forwardedBy:"Matej Perić"}
];

const seedHandovers = [
  {id:1,handoverNo:"PS-2026-000001",site:"Skladište Istok",date:"2026-09-13",time:"18:54",fromEmployee:"Petar Kovač",fromEmployeeId:"emp-002",toEmployee:"Luka Babić",toEmployeeId:"emp-003",shift:"I",keys:"Glavni komplet ključeva K-01",equipment:"Radio-stanica R-02, ručna svjetiljka",openItems:"Nema otvorenih sigurnosnih događaja.",instructions:"Nastaviti pojačan nadzor servisnog ulaza.",condition:"Oprema i evidencije uredne.",status:"PREUZETO",createdAt:"2026-09-13T18:54:00",acceptedAt:"2026-09-13T18:58:00"}
];

const seedInstructions = [
  {id:1,title:"Pojačan nadzor servisnih ulaza",text:"Do daljnjega pri svakom obilasku provjeriti servisne ulaze i zabilježiti svako odstupanje u dnevnik događaja.",site:"Skladište Istok",priority:"VAŽNO",requireAck:true,createdBy:"Ivan Horvat",createdAt:"2026-09-13T16:30:00",acks:[{employeeId:"emp-002",employee:"Petar Kovač",at:"2026-09-13T16:42:00"}],active:true}
];


function isBankSite(siteName){
  return /banka/i.test(String(siteName || ""));
}

function shiftPreset(code, siteName=""){
  if(code === "I") return isBankSite(siteName) ? ["08:00","20:00",12] : ["07:00","19:00",12];
  if(code === "II") return ["19:00","07:00",12];
  return ["","",0];
}

function workTimeLabel(siteName=""){
  if(isBankSite(siteName)) return "08:00–20:00 (I)";
  return "I 07:00–19:00 · II 19:00–07:00";
}

const seedWorkHours = [
  {id:1,employee:"Ivan Horvat",site:"Poslovni centar Alfa",date:"2026-09-01",shift:"I",start:"07:00",end:"19:00",hours:12},
  {id:2,employee:"Ivan Horvat",site:"Poslovni centar Alfa",date:"2026-09-02",shift:"II",start:"19:00",end:"07:00",hours:12},
  {id:3,employee:"Ana Kovač",site:"Hotel Central",date:"2026-09-01",shift:"I",start:"07:00",end:"19:00",hours:12},
  {id:4,employee:"Marko Marić",site:"Skladište Istok",date:"2026-09-01",shift:"I",start:"07:00",end:"19:00",hours:12},
];
const buildDemoWorkHours = (emps, month="2026-09") => {
  const [yy,mm]=month.split("-").map(Number);
  const days=new Date(yy,mm,0).getDate();
  const rows=[];

  emps.filter(e=>e.active!==false).forEach((e)=>{
    const siteDef=seedSites.find(s=>s.name===e.site) || {name:e.site,is247:false,workingHours:isBankSite(e.site)?"08:00–20:00":"07:00–19:00"};
    const sameSite=emps.filter(x=>x.active!==false && x.site===e.site);
    const localIndex=Math.max(0,sameSite.findIndex(x=>x.id===e.id));

    for(let d=1;d<=days;d++){
      const date=`${month}-${String(d).padStart(2,"0")}`;
      let shift="SL";
      if(siteDef?.is247){
        const cycle=["I","II","SL","SL"];
        shift=cycle[(d-1+localIndex)%4];
      }else{
        shift=((d-1+localIndex)%2===0) ? "I" : "SL";
      }
      const preset=shiftPreset(shift,e.site);
      const seg=shiftSegments(shift,new Date(`${date}T00:00:00`),e.site);
      rows.push({id:`demo-wh-${e.id}-${date}`,employee:e.name,employeeId:e.id,site:e.site,date,shift,start:preset[0],end:preset[1],hours:preset[2],nightHours:seg.night,sundayHours:seg.sunday,holidayHours:seg.holiday});
    }
  });
  return rows;
};


const seedPatrols = [
  {id:1,employee:"Ivan Horvat",cardNumber:"ISK-001",site:"Poslovni centar Alfa",date:"2026-09-13",start:"08:05",end:"08:24",duration:19,checkpointsDone:12,checkpointsTotal:12,missed:0,status:"U REDU",source:"Kerber"},
  {id:2,employee:"Marko Marić",cardNumber:"ISK-003",site:"Skladište Istok",date:"2026-09-13",start:"07:50",end:"08:12",duration:22,checkpointsDone:9,checkpointsTotal:10,missed:1,status:"NEPOTPUNO",source:"Kerber"},
  {id:3,employee:"Ana Kovač",cardNumber:"ISK-002",site:"Hotel Central",date:"2026-09-13",start:"09:10",end:"09:27",duration:17,checkpointsDone:8,checkpointsTotal:8,missed:0,status:"U REDU",source:"Ručni unos"},
];

const seedEvents = [
  {id:1,date:today,time:"08:14",category:"Sigurnosni događaj",title:"Otključan servisni ulaz",description:"Servisni ulaz pronađen otključan. Ulaz provjeren i ponovno zaključan.",site:"Hotel Central",level:"Nisko",recordedBy:"Ana Kovač",followUp:"Voditelj obaviješten.",attachment:""},
  {id:2,date:today,time:"07:42",category:"Kašnjenje",title:"Kašnjenje djelatnika",description:"Djelatnik nije stigao na početak planirane smjene.",site:"Skladište Istok",level:"Srednje",recordedBy:"Administrator",followUp:"Kontaktiran voditelj smjene.",attachment:""},
];

function useStoredState(key, initial) {
  const [value, setValue] = useState(() => {
    try {
      const s = localStorage.getItem(key);
      return s ? JSON.parse(s) : initial;
    } catch { return initial; }
  });
  const setStored = next => {
    setValue(prev => {
      const v = typeof next === "function" ? next(prev) : next;
      localStorage.setItem(key, JSON.stringify(v));
      return v;
    });
  };
  return [value, setStored];
}

const navItems = [
  ["dashboard","⌂","Pregled",""],
  ["visitors","♣","Najave / posjetitelji",""],
  ["log","▤","Dnevnik događaja",""],
  ["sites","▥","Objekti","OPERATIVNO"],
  ["users","●","Djelatnici","OPERATIVNO"],
  ["shifts","▣","Raspored","OPERATIVNO"],
  ["workorder","▤","Radni nalozi","OPERATIVNO"],
  ["hours","◷","Evidencija sati","OPERATIVNO"],
  ["patrols","◎","Obilasci","OPERATIVNO"],
  ["requests","◫","Zahtjevi smjena","OPERATIVNO"],
  ["messages","✉","Poruke / Hitne situacije","KOMUNIKACIJA"],
  ["mail","@","Pošta objekta","KOMUNIKACIJA"],
  ["access","⇄","Vozila i pristup","VOZILA I PRISTUP"],
  ["reports","▥","Izvješća","IZVJEŠĆA"],
  ["handover","⇆","Primopredaja smjene","IZVJEŠĆA"],
  ["instructions","!","Obavijesti i upute","KOMUNIKACIJA"],
  ["payroll","€","Plaće","ADMINISTRACIJA"],
  ["settings","⚙","Postavke","ADMINISTRACIJA"],
];


// --- SENTRYPRO 0.14: obračun fonda sati i posebnih sati ---
const CRO_FIXED_HOLIDAYS = [
  [1,1],   // Nova godina
  [1,6],   // Bogojavljenje
  [5,1],   // Praznik rada
  [5,30],  // Dan državnosti
  [6,22],  // Dan antifašističke borbe
  [8,5],   // Dan pobjede i domovinske zahvalnosti
  [8,15],  // Velika Gospa
  [11,1],  // Svi sveti
  [11,18], // Dan sjećanja
  [12,25], // Božić
  [12,26], // Sveti Stjepan
];

function easterSunday(year){
  const f = Math.floor;
  const G = year % 19, C = f(year/100), H = (C - f(C/4) - f((8*C+13)/25) + 19*G + 15) % 30;
  const I = H - f(H/28) * (1 - f(29/(H+1)) * f((21-G)/11));
  const J = (year + f(year/4) + I + 2 - C + f(C/4)) % 7;
  const L = I - J;
  const month = 3 + f((L+40)/44);
  const day = L + 28 - 31*f(month/4);
  return new Date(year, month-1, day);
}
function addDays(d, n){ const x = new Date(d); x.setDate(x.getDate()+n); return x; }
function ymd(d){ return `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,"0")}-${String(d.getDate()).padStart(2,"0")}`; }

function croatianHolidaySet(year){
  const set = new Set(CRO_FIXED_HOLIDAYS.map(([m,d]) => `${year}-${String(m).padStart(2,"0")}-${String(d).padStart(2,"0")}`));
  const easter = easterSunday(year);
  [easter, addDays(easter,1), addDays(easter,60)].forEach(d => set.add(ymd(d))); // Uskrs, Uskrsni ponedjeljak, Tijelovo
  return set;
}

function monthlyWorkFund(year, monthIndex, weeklyHours=40){
  const holidays = croatianHolidaySet(year);
  const dailyNorm = weeklyHours / 5;
  let workdays = 0, holidayWeekdays = 0;
  const days = new Date(year, monthIndex+1, 0).getDate();
  for(let day=1; day<=days; day++){
    const d = new Date(year, monthIndex, day);
    const wd = d.getDay();
    const weekday = wd >= 1 && wd <= 5;
    const holiday = holidays.has(ymd(d));
    if(weekday && !holiday) workdays++;
    if(weekday && holiday) holidayWeekdays++;
  }
  return {
    hours: +(workdays * dailyNorm).toFixed(2),
    workdays,
    holidayWeekdays,
    weeklyHours
  };
}

function shiftSegments(code, date, siteName=""){
  // Povrat sati: ukupno, noćni (22-06), nedjelja, blagdan.
  if(!["I","II"].includes(code)) return {total:0, night:0, sunday:0, holiday:0};
  const start = new Date(date);
  if(code==="I"){ start.setHours(isBankSite(siteName)?8:7,0,0,0); }
  else { start.setHours(19,0,0,0); }
  const end = new Date(start);
  end.setHours(end.getHours()+12);
  const holidays = croatianHolidaySet(start.getFullYear());
  let total=0, night=0, sunday=0, holiday=0;
  for(let t=new Date(start); t<end; t.setHours(t.getHours()+1)){
    total += 1;
    const h = t.getHours();
    if(h>=22 || h<6) night += 1;
    if(t.getDay()===0) sunday += 1;
    if(holidays.has(ymd(t))) holiday += 1;
  }
  return {total,night,sunday,holiday};
}

function calcEmployeeMonthFromSchedule(scheduleRow, year, monthIndex, weeklyHours=40){
  let worked=0, night=0, sunday=0, holiday=0;
  const days = new Date(year, monthIndex+1, 0).getDate();
  for(let day=1; day<=days; day++){
    const code = scheduleRow?.[day] || scheduleRow?.[String(day)] || "";
    if(code==="I" || code==="II"){
      const s = shiftSegments(code, new Date(year, monthIndex, day));
      worked += s.total; night += s.night; sunday += s.sunday; holiday += s.holiday;
    }
  }
  const fund = monthlyWorkFund(year, monthIndex, weeklyHours).hours;
  return {
    fund,
    worked,
    overtime: Math.max(0, worked - fund),
    deficit: Math.max(0, fund - worked),
    night,
    sunday,
    holiday
  };
}


function PayrollMonthSummary({year, monthIndex, weeklyHours=40, workedHours=0, nightHours=0, sundayHours=0, holidayHours=0}){
  const f = monthlyWorkFund(year, monthIndex, weeklyHours);
  const overtime = Math.max(0, workedHours - f.hours);
  const deficit = Math.max(0, f.hours - workedHours);
  return <div className="payrollSummary">
    <div><span>Fond sati</span><b>{f.hours} h</b><small>{f.workdays} radnih dana</small></div>
    <div><span>Odrađeno</span><b>{workedHours} h</b><small>prema rasporedu/evidenciji</small></div>
    <div><span>Prekovremeni</span><b>{overtime} h</b><small>iznad mjesečnog fonda</small></div>
    <div><span>Manjak do fonda</span><b>{deficit} h</b><small>informativno</small></div>
    <div><span>Noćni 22–06</span><b>{nightHours} h</b><small>posebno evidentirano</small></div>
    <div><span>Nedjelja</span><b>{sundayHours} h</b><small>posebno evidentirano</small></div>
    <div><span>Blagdan</span><b>{holidayHours} h</b><small>posebno evidentirano</small></div>
  </div>
}

const isoDateSafe = () => new Date().toISOString().slice(0,10);

function App(){
  const [page,setPage]=useState("dashboard");
  const [language,setLanguage]=useStoredState("sentrypro_language","hr");
  const [demoLoggedIn,setDemoLoggedIn]=useState(false);
  const [visitors,setVisitors]=useStoredState("sentrypro_visitors_v04",seedVisitors);
  const [employees,setEmployees]=useStoredState("sentrypro_employees_v09",seedEmployees);
  const [sites,setSites]=useStoredState("sentrypro_sites_v11",seedSites);
  const [events,setEvents]=useStoredState("sentrypro_events_v04",seedEvents);
  const [patrols,setPatrols]=useStoredState("sentrypro_patrols_v06",seedPatrols);
  const [workHours,setWorkHours]=useStoredState("sentrypro_workhours_v10",buildDemoWorkHours(seedEmployees,"2026-09"));

  useEffect(()=>{
    const demoVersion="0.24.1";
    if(localStorage.getItem("sentrypro_demo_dataset_version")!==demoVersion){
      // 0.24 migracija čuva objekte koje je korisnik sam dodao (npr. Erste banka).
      setSites(prev=>prev.map(site=>isBankSite(site.name)?{...site,workingHours:"08:00–20:00",is247:false}:site));
      setEmployees(prev=>{
        const byId=new Map(prev.map(e=>[e.id,e]));
        seedEmployees.forEach(e=>{ if(!byId.has(e.id)) byId.set(e.id,e); });
        return Array.from(byId.values());
      });
      setWorkHours(prev=>{
        const ids=new Set(prev.map(w=>`${w.employeeId||w.employee}|${w.date}`));
        const extra=buildDemoWorkHours(seedEmployees.filter(e=>["emp-051","emp-052"].includes(e.id)),"2026-09").filter(w=>!ids.has(`${w.employeeId}|${w.date}`));
        return [...prev,...extra].map(w=>isBankSite(w.site)&&w.shift==="I"?{...w,start:"08:00",end:"20:00",hours:12,nightHours:0}:w);
      });
      setUserSiteFilter("Svi objekti");
      localStorage.setItem("sentrypro_demo_dataset_version",demoVersion);
    }
  },[]);

  const canonicalWorkHours = useMemo(()=>{
    const byKey=new Map();
    workHours.forEach(w=>{
      const matchedEmployee = employees.find(e=>e.id===w.employeeId || e.name===w.employee);
      const employeeKey = matchedEmployee?.id || w.employeeId || w.employee;
      const normalized = matchedEmployee
        ? {...w, employeeId:matchedEmployee.id, employee:matchedEmployee.name, site:w.site||matchedEmployee.site}
        : w;
      const key=`${employeeKey}|${w.date}`;
      byKey.set(key,normalized);
    });
    return Array.from(byKey.values());
  },[workHours,employees]);

  const [scheduleMonth,setScheduleMonth]=useState("2026-09");
  const [showHours,setShowHours]=useState(false);
  const [query,setQuery]=useState("");
  const [siteFilter,setSiteFilter]=useState("Svi objekti");
  const [showVisitor,setShowVisitor]=useState(false);
  const [showEvent,setShowEvent]=useState(false);
  const [showUser,setShowUser]=useState(false);
  const [editingUser,setEditingUser]=useState(null);
  const [currentUserRole,setCurrentUserRole]=useState("Administrator");
  const [clientSite,setClientSite]=useState("Skladište Istok");
  const [showSite,setShowSite]=useState(false);
  const [editingSite,setEditingSite]=useState(null);
  const [userQuery,setUserQuery]=useState("");
  const [patrolQuery,setPatrolQuery]=useState("");
  const [showPatrol,setShowPatrol]=useState(false);
  const [accessEvents,setAccessEvents]=useStoredState("sentrypro_access_v010",seedAccessEvents);
  const [messages,setMessages]=useStoredState("sentrypro_messages_v010",seedMessages);
  const [shiftRequests,setShiftRequests]=useStoredState("sentrypro_shift_requests_v011",seedShiftRequests);
  const [leaveRequests,setLeaveRequests]=useStoredState("sentrypro_leave_requests_v01",[]);
  const [reports,setReports]=useStoredState("sentrypro_reports_v023",seedReports);
  const [incidentRequests,setIncidentRequests]=useStoredState("sentrypro_incident_requests_v023",[]);
  const [handovers,setHandovers]=useStoredState("sentrypro_handovers_v0231",seedHandovers);
  const [instructions,setInstructions]=useStoredState("sentrypro_instructions_v0231",seedInstructions);
  const [auditLog,setAuditLog]=useStoredState("sentrypro_audit_v014",[]);

  const [accessSite,setAccessSite]=useState("Skladište Istok");
  const [lprPlate,setLprPlate]=useState("");
  const [cardScan,setCardScan]=useState("");
  const [messageText,setMessageText]=useState("");
  const [messagePriority,setMessagePriority]=useState("NORMALNO");
  const [requestType,setRequestType]=useState("SL");
  const [requestDate,setRequestDate]=useState("2026-10-01");
  const [requestNote,setRequestNote]=useState("");
  const [leaveFrom,setLeaveFrom]=useState("2026-10-20");
  const [leaveTo,setLeaveTo]=useState("2026-10-27");
  const [leaveNote,setLeaveNote]=useState("");
  const [loggedEmployee,setLoggedEmployee]=useState("Ivan Horvat");
  const [handoverAcceptAmmo,setHandoverAcceptAmmo]=useState({});
  const [managerMessageSite,setManagerMessageSite]=useState("Skladište Istok");
  const [managerMessageText,setManagerMessageText]=useState("");
  const [managerMessagePriority,setManagerMessagePriority]=useState("NORMALNO");
  const [scheduleSite,setScheduleSite]=useState("Skladište Istok");
  const [reportSite,setReportSite]=useState("Skladište Istok");
  const [reportMode,setReportMode]=useState("REDOVNO");
  const [shiftReportSummary,setShiftReportSummary]=useState("");
  const [shiftReportTasks,setShiftReportTasks]=useState("");
  const [shiftReportObservations,setShiftReportObservations]=useState("");
  const [shiftReportHandover,setShiftReportHandover]=useState("");
  const [shiftReportNoEvents,setShiftReportNoEvents]=useState(false);
  const [incidentRequestEmployee,setIncidentRequestEmployee]=useState("emp-002");
  const [incidentRequestReason,setIncidentRequestReason]=useState("");
  const [incidentRequestDeadline,setIncidentRequestDeadline]=useState("");
  const [activeIncidentRequestId,setActiveIncidentRequestId]=useState("");
  const [incidentEventDate,setIncidentEventDate]=useState(isoDateSafe());
  const [incidentEventTime,setIncidentEventTime]=useState("");
  const [incidentLocation,setIncidentLocation]=useState("");
  const [incidentChronology,setIncidentChronology]=useState("");
  const [incidentActions,setIncidentActions]=useState("");
  const [incidentNotified,setIncidentNotified]=useState("");
  const [incidentPersons,setIncidentPersons]=useState("");
  const [incidentDamage,setIncidentDamage]=useState("");
  const [incidentFinalState,setIncidentFinalState]=useState("");
  const [handoverFromEmployeeId,setHandoverFromEmployeeId]=useState("");
  const [handoverToEmployeeId,setHandoverToEmployeeId]=useState("");
  const [handoverKeys,setHandoverKeys]=useState("");
  const [handoverEquipment,setHandoverEquipment]=useState("");
  const [handoverOpenItems,setHandoverOpenItems]=useState("");
  const [handoverInstructions,setHandoverInstructions]=useState("");
  const [handoverCondition,setHandoverCondition]=useState("");
  const [handoverWeaponEnabled,setHandoverWeaponEnabled]=useState(false);
  const [handoverWeaponType,setHandoverWeaponType]=useState("Službeno vatreno oružje");
  const [handoverWeaponSerial,setHandoverWeaponSerial]=useState("");
  const [handoverWeaponCondition,setHandoverWeaponCondition]=useState("Ispravno");
  const [handoverAmmoIssued,setHandoverAmmoIssued]=useState("");
  const [handoverAmmoReturned,setHandoverAmmoReturned]=useState("");
  const [instructionSite,setInstructionSite]=useState("Svi objekti");
  const [instructionTitle,setInstructionTitle]=useState("");
  const [instructionText,setInstructionText]=useState("");
  const [instructionPriority,setInstructionPriority]=useState("VAŽNO");
  const [instructionRequireAck,setInstructionRequireAck]=useState(true);
  const [userSiteFilter,setUserSiteFilter]=useState("Svi objekti");
  const [userStatusFilter,setUserStatusFilter]=useState("Svi statusi");
  const [userReplacementOnly,setUserReplacementOnly]=useState(false);
  const [userSort,setUserSort]=useState("az");
  const [userPage,setUserPage]=useState(1);
  const USERS_PER_PAGE=10;

  // ---- Ovlasti i opseg podataka po ulozi ----
  const employeeSites = e => (e && Array.isArray(e.assignedSites) && e.assignedSites.length
    ? e.assignedSites
    : (e?.site && e.site!=="—" ? [e.site] : []));

  const currentEmployee = useMemo(
    ()=>employees.find(e=>e.name===loggedEmployee) || employees.find(e=>e.active!==false) || null,
    [employees,loggedEmployee]
  );

  const managerEmployee = useMemo(
    ()=>employees.find(e=>/voditelj/i.test(e.role||"") && e.active!==false) || null,
    [employees]
  );

  const managerSites = useMemo(()=>{
    const scoped=employeeSites(managerEmployee);
    return scoped.length ? scoped : (sites[0]?.name ? [sites[0].name] : []);
  },[managerEmployee,sites]);

  const visibleRequests = useMemo(()=>{
    if(currentUserRole==="Zaštitar") return shiftRequests.filter(r=>r.employee===currentEmployee?.name);
    if(currentUserRole==="Voditelj" || currentUserRole==="Administrator") return shiftRequests;
    return [];
  },[shiftRequests,currentUserRole,currentEmployee]);

  const visibleLeaveRequests = useMemo(()=>{
    if(currentUserRole==="Zaštitar") return leaveRequests.filter(r=>r.employeeId===currentEmployee?.id || r.employee===currentEmployee?.name);
    if(currentUserRole==="Voditelj" || currentUserRole==="Administrator") return leaveRequests;
    return [];
  },[leaveRequests,currentUserRole,currentEmployee]);

  const [payrollMonth,setPayrollMonth]=useState(new Date().toISOString().slice(0,7));
  const [payrollAdjustments,setPayrollAdjustments]=useState(()=>JSON.parse(localStorage.getItem("sentry_payroll_adjustments")||"[]"));
  const [payrollRates,setPayrollRates]=useState(()=>JSON.parse(localStorage.getItem("sentry_payroll_rates")||'{"night":30,"sunday":50,"holiday":50,"overtime":50}'));





  const localDateKey = d => {
    const y=d.getFullYear();
    const m=String(d.getMonth()+1).padStart(2,"0");
    const day=String(d.getDate()).padStart(2,"0");
    return `${y}-${m}-${day}`;
  };
  const liveNow = new Date();
  const todayISO = localDateKey(liveNow);
  const yesterdayDate = new Date(liveNow);
  yesterdayDate.setDate(yesterdayDate.getDate()-1);
  const yesterdayISO = localDateKey(yesterdayDate);
  const currentMinutes = liveNow.getHours()*60 + liveNow.getMinutes();

  const employeeScheduleRecord = (emp,dateKey) =>
    canonicalWorkHours.find(w=>(w.employeeId===emp.id || w.employee===emp.name) && w.date===dateKey);

  const isEmployeeOnShiftNow = emp => {
    if(!emp || emp.active===false) return false;
    if(currentMinutes>=420 && currentMinutes<1140) return employeeScheduleRecord(emp,todayISO)?.shift==="I";
    if(currentMinutes>=1140) return employeeScheduleRecord(emp,todayISO)?.shift==="II";
    return employeeScheduleRecord(emp,yesterdayISO)?.shift==="II";
  };

  const getEmployeeOperationalStatus = emp => {
    if(!emp || emp.active===false) return "Neaktivan";
    if(isEmployeeOnShiftNow(emp)) return "Na smjeni";
    const todayShift=employeeScheduleRecord(emp,todayISO)?.shift;
    if(todayShift==="GO") return "Godišnji odmor";
    if(todayShift==="BO") return "Bolovanje";
    return "Slobodan";
  };

  const onShiftNow = employees.filter(isEmployeeOnShiftNow);
  const onShiftCount = onShiftNow.length;

  const inside = visitors.filter(v=>v.status==="U OBJEKTU").length;
  const active = onShiftCount;
  const vehicles = visitors.filter(v=>v.status==="U OBJEKTU" && v.plate).length;
  const cards = visitors.filter(v=>v.status==="U OBJEKTU" && v.card).length;
  const filteredPatrols = useMemo(()=>patrols.filter(p =>
    `${p.employee} ${p.cardNumber} ${p.site} ${p.status} ${p.source}`.toLowerCase().includes(patrolQuery.toLowerCase())
  ),[patrols,patrolQuery]);

  const surnameKey=(name="")=>{const parts=name.trim().split(/\s+/);return `${parts.at(-1)||""} ${parts.slice(0,-1).join(" ")}`.toLocaleLowerCase("hr-HR");};
  const displayEmployeeName=(name="")=>{const parts=name.trim().split(/\s+/);if(parts.length<2) return name;return `${parts.at(-1)} ${parts.slice(0,-1).join(" ")}`;};
  const filteredUsers = useMemo(()=>employees.filter(e =>{
    if(currentUserRole==="Zaštitar" && e.id!==currentEmployee?.id) return false;
    const hay=`${e.name} ${e.role} ${e.site} ${e.phone} ${e.email} ${e.license} ${e.cardNumber||""}`.toLowerCase();
    const byText=hay.includes(userQuery.toLowerCase());
    const bySite=userSiteFilter==="Svi objekti" || employeeSites(e).includes(userSiteFilter);
    const opStatus=getEmployeeOperationalStatus(e);
    const byStatus=userStatusFilter==="Svi statusi"
      || (userStatusFilter==="Aktivni" && e.active!==false)
      || (userStatusFilter==="Neaktivni" && e.active===false)
      || opStatus===userStatusFilter;
    const byReplacement=!userReplacementOnly || e.replacementAvailable===true;
    return byText && bySite && byStatus && byReplacement;
  }).sort((a,b)=>{const cmp=surnameKey(a.name).localeCompare(surnameKey(b.name),"hr-HR");return userSort==="za"?-cmp:cmp}),[employees,currentUserRole,currentEmployee,userQuery,userSiteFilter,userStatusFilter,userReplacementOnly,userSort,canonicalWorkHours]);

  const userPages=Math.max(1,Math.ceil(filteredUsers.length/USERS_PER_PAGE));
  const pagedUsers=filteredUsers.slice((Math.min(userPage,userPages)-1)*USERS_PER_PAGE,Math.min(userPage,userPages)*USERS_PER_PAGE);

  const workOrderEmployees = useMemo(()=>employees.filter(e=>e.active!==false).sort((a,b)=>surnameKey(a.name).localeCompare(surnameKey(b.name),"hr-HR")),[employees]);

  const filtered = useMemo(()=>visitors.filter(v=>{
    const txt = `${v.firstName} ${v.lastName} ${v.company} ${v.visiting} ${v.reason} ${v.plate} ${v.card} ${v.documentNumber||""}`.toLowerCase();
    const okSite = siteFilter==="Svi objekti" || v.site===siteFilter;
    return okSite && txt.includes(query.toLowerCase());
  }),[visitors,query,siteFilter]);

  const canManage = currentUserRole==="Voditelj" || currentUserRole==="Administrator";
  const loggedEmployeeRecord = currentEmployee;
  const visibleScheduleSite = currentUserRole==="Zaštitar"
    ? (loggedEmployeeRecord?.site || scheduleSite)
    : scheduleSite;
  const employeesForSchedule = employees.filter(e=>e.active!==false && employeeSites(e).includes(visibleScheduleSite));
  const employeesForHours = currentUserRole==="Zaštitar"
    ? employees.filter(e=>e.id===loggedEmployeeRecord?.id)
    : employees.filter(e=>e.active!==false);
  const workHoursForRole = canonicalWorkHours.filter(w=>{
    if(currentUserRole==="Zaštitar") return w.employee===loggedEmployeeRecord?.name;
    return true;
  });
  const patrolsForRole = patrols.filter(p=>{
    if(currentUserRole==="Zaštitar") return p.site===loggedEmployeeRecord?.site;
    if(currentUserRole==="Voditelj") return managerSites.includes(p.site);
    return true;
  });
  const reportsForRole = reports.filter(r=>{
    if(currentUserRole==="Zaštitar") return r.authorId===loggedEmployeeRecord?.id || r.author===loggedEmployeeRecord?.name;
    if(currentUserRole==="Direktor") return r.forwardedToDirector===true;
    if(currentUserRole==="Voditelj" || currentUserRole==="Administrator") return true;
    return false;
  }).sort((a,b)=>String(b.submittedAt||`${b.date}T${b.time}`).localeCompare(String(a.submittedAt||`${a.date}T${a.time}`)));
  const incidentRequestsForRole = incidentRequests.filter(r=>{
    if(currentUserRole==="Zaštitar") return r.employeeId===loggedEmployeeRecord?.id;
    if(currentUserRole==="Voditelj" || currentUserRole==="Administrator") return true;
    return false;
  }).sort((a,b)=>String(b.createdAt||"").localeCompare(String(a.createdAt||"")));
  const newManagerReports = reports.filter(r=>r.managerStatus==="NOVO").length;
  const newDirectorReports = reports.filter(r=>r.forwardedToDirector && r.directorStatus!=="PROČITANO").length;
  const scheduleDays = new Date(Number(scheduleMonth.slice(0,4)),Number(scheduleMonth.slice(5,7)),0).getDate();


  const scheduleGridStyle = {gridTemplateColumns:`minmax(92px,1.7fr) repeat(${scheduleDays},minmax(0,1fr))`};

  const now = ()=>new Date().toLocaleTimeString("hr-HR",{hour:"2-digit",minute:"2-digit"});
  const isoDate = ()=>new Date().toISOString().slice(0,10);

  function addAudit(action,detail){
    setAuditLog(prev=>[{id:Date.now(),date:isoDate(),time:now(),actor:currentUserRole==="Administrator"?"Elvis Bukal":currentUserRole,action,detail},...prev].slice(0,500));
  }

  function nextReportNo(prefix){
    const year=new Date().getFullYear();
    const same=reports.filter(r=>String(r.reportNo||"").startsWith(`${prefix}-${year}-`));
    const max=same.reduce((m,r)=>Math.max(m,Number(String(r.reportNo).split("-").pop())||0),0);
    return `${prefix}-${year}-${String(max+1).padStart(6,"0")}`;
  }

  function submitShiftReport(){
    const summary=shiftReportSummary.trim(), tasks=shiftReportTasks.trim(), observations=shiftReportObservations.trim(), handover=shiftReportHandover.trim();
    if(!summary || !tasks || !handover) return alert("Za predaju su obvezni sažetak smjene, provedene aktivnosti i primopredaja.");
    const emp=loggedEmployeeRecord;
    const site=currentUserRole==="Zaštitar"?(emp?.site||reportSite):reportSite;
    const scheduled=emp?employeeScheduleRecord(emp,isoDate()):null;
    const shift=scheduled?.shift || emp?.shift || "—";
    const reportNo=nextReportNo("RI");
    const author=currentUserRole==="Administrator"?"Elvis Bukal":(emp?.name||currentUserRole);
    const row={id:Date.now(),reportNo,date:isoDate(),time:now(),site,author,authorId:emp?.id||"",authorRole:currentUserRole,type:"REDOVNO",shift,title:"Redovno izvješće smjene",summary,tasks,observations:observations||(shiftReportNoEvents?"Nisu utvrđene sigurnosno značajne nepravilnosti.":"—"),handover,noEvents:shiftReportNoEvents,status:"PREDANO",managerStatus:"NOVO",submittedAt:new Date().toISOString(),forwardedToDirector:false};
    setReports(prev=>[row,...prev]);
    addAudit("PREDANO REDOVNO IZVJEŠĆE",`${reportNo} · ${author} · ${site}`);
    setShiftReportSummary("");setShiftReportTasks("");setShiftReportObservations("");setShiftReportHandover("");setShiftReportNoEvents(false);
    alert(`Izvješće ${reportNo} je predano i odmah je dostupno voditelju.`);
  }

  function createIncidentRequest(){
    if(!canManage) return;
    const emp=employees.find(e=>e.id===incidentRequestEmployee);
    if(!emp || !incidentRequestReason.trim()) return alert("Odaberi djelatnika i upiši razlog zahtjeva.");
    const row={id:`req-${Date.now()}`,employeeId:emp.id,employee:emp.name,site:emp.site,reason:incidentRequestReason.trim(),deadline:incidentRequestDeadline||"Bez posebnog roka",requestedBy:currentUserRole==="Administrator"?"Elvis Bukal":(currentEmployee?.name||"Voditelj"),createdAt:new Date().toISOString(),createdDate:isoDate(),createdTime:now(),status:"ZAHTJEV IZDAN"};
    setIncidentRequests(prev=>[row,...prev]);
    addAudit("ZAHTJEV ZA IZVANREDNO IZVJEŠĆE",`${emp.name} · ${emp.site} · ${row.reason}`);
    setIncidentRequestReason("");setIncidentRequestDeadline("");
    alert(`Zahtjev je odmah dodijeljen djelatniku ${emp.name}.`);
  }

  function submitIncidentReport(){
    const req=incidentRequests.find(r=>r.id===activeIncidentRequestId);
    if(!req) return alert("Odaberi aktivni zahtjev voditelja.");
    if(!incidentEventDate || !incidentEventTime || !incidentLocation.trim() || !incidentChronology.trim() || !incidentActions.trim() || !incidentFinalState.trim()) return alert("Popuni sva obvezna polja označena zvjezdicom.");
    const reportNo=nextReportNo("ID");
    const row={id:Date.now(),reportNo,date:isoDate(),time:now(),site:req.site,author:req.employee,authorId:req.employeeId,authorRole:"Zaštitar",type:"IZVANREDNO",title:"Izvješće o izvanrednom događaju",eventDate:incidentEventDate,eventTime:incidentEventTime,eventLocation:incidentLocation.trim(),chronology:incidentChronology.trim(),actions:incidentActions.trim(),notified:incidentNotified.trim()||"—",persons:incidentPersons.trim()||"—",damage:incidentDamage.trim()||"Nije navedeno",finalState:incidentFinalState.trim(),status:"PREDANO",managerStatus:"NOVO",submittedAt:new Date().toISOString(),requestedBy:req.requestedBy,requestReason:req.reason,requestId:req.id,forwardedToDirector:false};
    setReports(prev=>[row,...prev]);
    setIncidentRequests(prev=>prev.map(x=>x.id===req.id?{...x,status:"IZVJEŠĆE PREDANO",reportNo,completedAt:new Date().toISOString()}:x));
    addAudit("PREDANO IZVANREDNO IZVJEŠĆE",`${reportNo} · ${req.employee} · ${req.site}`);
    setActiveIncidentRequestId("");setIncidentLocation("");setIncidentChronology("");setIncidentActions("");setIncidentNotified("");setIncidentPersons("");setIncidentDamage("");setIncidentFinalState("");setIncidentEventTime("");
    alert(`Izvješće ${reportNo} je predano i odmah je dostupno voditelju.`);
  }

  function markReportRead(id){
    setReports(prev=>prev.map(r=>r.id===id?{...r,managerStatus:"PROČITANO",managerReadAt:new Date().toISOString()}:r));
    const r=reports.find(x=>x.id===id); if(r) addAudit("IZVJEŠĆE PROČITANO",`${r.reportNo||r.id} · ${r.site}`);
  }

  function forwardReportToDirector(id){
    const r=reports.find(x=>x.id===id); if(!r) return;
    const by=currentUserRole==="Administrator"?"Elvis Bukal":(currentEmployee?.name||"Voditelj");
    setReports(prev=>prev.map(x=>x.id===id?{...x,managerStatus:"PROČITANO",forwardedToDirector:true,forwardedAt:new Date().toISOString(),forwardedBy:by,directorStatus:"NOVO"}:x));
    addAudit("IZVJEŠĆE PROSLIJEĐENO DIREKTORU",`${r.reportNo||r.id} · ${by}`);
    alert("Izvješće je odmah dostupno direktoru u probnom sustavu.");
  }

  function markDirectorRead(id){
    setReports(prev=>prev.map(r=>r.id===id?{...r,directorStatus:"PROČITANO",directorReadAt:new Date().toISOString()}:r));
  }

  function printReportPdf(r){
    const w=window.open("","_blank","width=980,height=780");
    if(!w) return;
    const esc=v=>String(v??"").replace(/[&<>"']/g,m=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#039;"}[m]));
    const row=(label,value)=>`<div class="metaRow"><span>${esc(label)}</span><b>${esc(value||"—")}</b></div>`;
    const section=(title,value)=>`<section><h2>${esc(title)}</h2><div class="text">${esc(value||"—")}</div></section>`;
    const isIncident=r.type==="IZVANREDNO";
    const body=isIncident
      ? `${section("1. Opis i kronologija događaja",r.chronology)}${section("2. Poduzete mjere i postupanje",r.actions)}${section("3. Obaviještene osobe / službe",r.notified)}${section("4. Uključene osobe / svjedoci",r.persons)}${section("5. Posljedice / šteta",r.damage)}${section("6. Završno stanje",r.finalState)}`
      : `${section("1. Sažetak smjene",r.summary)}${section("2. Provedene aktivnosti i zadaće",r.tasks)}${section("3. Zapažanja i nepravilnosti",r.observations)}${section("4. Primopredaja smjene",r.handover)}`;
    w.document.write(`<!doctype html><html lang="hr"><head><meta charset="utf-8"><title>${esc(r.reportNo||"SENTRYPRO izvješće")}</title><style>
      @page{size:A4;margin:16mm 15mm 17mm}*{box-sizing:border-box}body{font-family:Arial,Helvetica,sans-serif;color:#17283a;margin:0;background:#fff;font-size:11px}.doc{max-width:800px;margin:auto}.top{display:flex;justify-content:space-between;align-items:flex-start;border-bottom:3px solid #b58a2a;padding-bottom:13px}.brand{display:flex;gap:12px;align-items:center}.mark{width:48px;height:48px;border:2px solid #b58a2a;border-radius:50%;display:grid;place-items:center;color:#b58a2a;font-weight:900;font-size:16px}.brand h1{margin:0;color:#102d48;font-size:24px;letter-spacing:1.4px}.brand small{display:block;color:#6f7c89;margin-top:3px}.docId{text-align:right}.docId b{display:block;color:#102d48;font-size:13px}.docId span{font-size:9px;color:#798692}.title{text-align:center;margin:24px 0 16px}.title h2{font-size:18px;color:#102d48;margin:0 0 5px;text-transform:uppercase;letter-spacing:.7px}.title p{margin:0;color:#7b8792}.meta{border:1px solid #cfd8e0;display:grid;grid-template-columns:1fr 1fr;margin-bottom:16px}.metaRow{padding:8px 10px;border-bottom:1px solid #e4e9ee;display:flex;justify-content:space-between;gap:12px}.metaRow:nth-child(odd){border-right:1px solid #e4e9ee}.metaRow span{color:#6b7885;font-size:9px;text-transform:uppercase;letter-spacing:.3px}.metaRow b{text-align:right;color:#20364c}section{border:1px solid #d8e0e7;margin:10px 0;page-break-inside:avoid}section h2{font-size:10px;text-transform:uppercase;letter-spacing:.5px;background:#f1f4f7;color:#183b5b;margin:0;padding:7px 10px;border-bottom:1px solid #d8e0e7}.text{white-space:pre-wrap;line-height:1.6;padding:11px 12px;min-height:42px}.routing{margin-top:14px;border-left:4px solid #b58a2a;background:#faf8f1;padding:9px 11px;line-height:1.55}.signatures{display:grid;grid-template-columns:1fr 1fr;gap:70px;margin-top:50px}.sig{border-top:1px solid #475868;text-align:center;padding-top:6px;color:#6d7882;font-size:9px}.foot{margin-top:28px;border-top:1px solid #d9e0e6;padding-top:8px;display:flex;justify-content:space-between;color:#87919b;font-size:8px}.printBtn{margin:20px 0;padding:10px 16px;background:#102d48;color:#fff;border:0;border-radius:4px}@media print{.printBtn{display:none}.doc{max-width:none}}
    </style></head><body><div class="doc"><header class="top"><div class="brand"><div class="mark">SP</div><div><h1>SENTRYPRO</h1><small>Sustav evidencije zaštitarske službe</small></div></div><div class="docId"><b>${esc(r.reportNo||"—")}</b><span>SLUŽBENI OPERATIVNI DOKUMENT</span></div></header>
    <div class="title"><h2>${isIncident?"Izvješće o izvanrednom događaju":"Redovno izvješće smjene"}</h2><p>${esc(r.site)}</p></div>
    <div class="meta">${row("Broj izvješća",r.reportNo)}${row("Status",r.status)}${row("Objekt",r.site)}${row("Djelatnik",r.author)}${row("Datum predaje",`${r.date} ${r.time}`)}${row("Smjena",isIncident?"—":r.shift)}${isIncident?row("Vrijeme događaja",`${r.eventDate||"—"} ${r.eventTime||""}`):row("Vrsta","Redovno izvješće smjene")}${isIncident?row("Mjesto događaja",r.eventLocation):row("Bez posebnih događaja",r.noEvents?"DA":"NE")}</div>
    ${isIncident && r.requestReason?`<div class="routing"><b>Zahtjev voditelja:</b> ${esc(r.requestReason)}<br><b>Zahtjev izdao:</b> ${esc(r.requestedBy||"—")}</div>`:""}
    ${body}
    <div class="routing"><b>Distribucija:</b> Voditelj — ${esc(r.managerStatus||"NOVO")}${r.forwardedToDirector?` · Direktor — ${esc(r.directorStatus||"NOVO")}`:""}<br><b>Integritet zapisa:</b> Dokument je generiran iz predanog zapisa SENTRYPRO probnog sustava.</div>
    <div class="signatures"><div class="sig">Djelatnik / sastavio</div><div class="sig">Voditelj / pregledao</div></div><footer class="foot"><span>SENTRYPRO · ${esc(r.reportNo||"")}</span><span>Generirano: ${esc(new Date().toLocaleString("hr-HR"))}</span></footer><button class="printBtn" onclick="window.print()">Ispis / Spremi kao PDF</button></div></body></html>`);
    w.document.close(); setTimeout(()=>w.print(),250);
  }


  const nextHandoverNo = () => {
    const year=new Date().getFullYear();
    const same=handovers.filter(h=>String(h.handoverNo||"").startsWith(`PS-${year}-`));
    const max=same.reduce((m,h)=>Math.max(m,Number(String(h.handoverNo||"").split("-").pop())||0),0);
    return `PS-${year}-${String(max+1).padStart(6,"0")}`;
  };

  const relevantInstructions = useMemo(()=>{
    if(currentUserRole==="Zaštitar") return instructions.filter(i=>i.active!==false && (i.site==="Svi objekti" || i.site===currentEmployee?.site));
    return instructions.filter(i=>i.active!==false);
  },[instructions,currentUserRole,currentEmployee]);

  const relevantHandovers = useMemo(()=>{
    if(currentUserRole==="Zaštitar") return handovers.filter(h=>h.fromEmployeeId===currentEmployee?.id || h.toEmployeeId===currentEmployee?.id || h.site===currentEmployee?.site);
    if(currentUserRole==="Voditelj") return handovers;
    if(currentUserRole==="Administrator") return handovers;
    return [];
  },[handovers,currentUserRole,currentEmployee]);

  const unreadImportantInstructions = relevantInstructions.filter(i=>i.requireAck && !i.acks?.some(a=>a.employeeId===currentEmployee?.id)).length;
  const pendingHandovers = handovers.filter(h=>h.status==="ČEKA PREUZIMANJE").length;
  const todayMissingShiftReports = canonicalWorkHours.filter(w=>w.date===todayISO && ["I","II"].includes(w.shift)).filter(w=>!reports.some(r=>r.type==="REDOVNO" && r.authorId===w.employeeId && r.date===w.date)).length;

  const operationalTimeline = useMemo(()=>{
    const eventRows=events.map(e=>({id:`ev-${e.id}`,sort:`${e.date}T${e.time||"00:00"}`,date:e.date,time:e.time,type:"DOGAĐAJ",site:e.site,title:e.title,detail:e.description,person:e.recordedBy,status:e.level||"EVIDENTIRANO"}));
    const reportRows=reports.map(r=>({id:`rep-${r.id}`,sort:r.submittedAt||`${r.date}T${r.time||"00:00"}`,date:r.date,time:r.time,type:r.type==="IZVANREDNO"?"IZVANREDNO IZVJEŠĆE":"IZVJEŠĆE SMJENE",site:r.site,title:r.reportNo,detail:r.type==="IZVANREDNO"?(r.finalState||r.chronology):(r.summary||"Predano redovno izvješće"),person:r.author,status:r.managerStatus||r.status}));
    const handoverRows=handovers.map(h=>({id:`ho-${h.id}`,sort:h.createdAt||`${h.date}T${h.time||"00:00"}`,date:h.date,time:h.time,type:"PRIMOPREDAJA",site:h.site,title:h.handoverNo,detail:`${h.fromEmployee} → ${h.toEmployee}. ${h.openItems||""}`,person:h.fromEmployee,status:h.status}));
    const instructionRows=instructions.map(i=>{const d=new Date(i.createdAt);return {id:`ins-${i.id}`,sort:i.createdAt,date:Number.isNaN(d.getTime())?"—":localDateKey(d),time:Number.isNaN(d.getTime())?"—":d.toLocaleTimeString("hr-HR",{hour:"2-digit",minute:"2-digit"}),type:"UPUTA",site:i.site,title:i.title,detail:i.text,person:i.createdBy,status:i.priority};});
    let rows=[...eventRows,...reportRows,...handoverRows,...instructionRows].sort((a,b)=>String(b.sort).localeCompare(String(a.sort)));
    if(currentUserRole==="Zaštitar") rows=rows.filter(x=>x.site===currentEmployee?.site || x.site==="Svi objekti");
    return rows;
  },[events,reports,handovers,instructions,currentUserRole,currentEmployee]);

  function submitHandover(){
    const from = currentUserRole==="Zaštitar" ? currentEmployee : employees.find(e=>e.id===handoverFromEmployeeId);
    const to = employees.find(e=>e.id===handoverToEmployeeId);
    const fail = (message) => { alert(message); return false; };
    if(!from) return fail("Odaberite djelatnika koji predaje smjenu.");
    if(!to) return fail("Odaberite djelatnika koji preuzima smjenu.");
    if(to.id===from.id) return fail("Djelatnik koji predaje i preuzima ne može biti ista osoba.");
    if(to.site!==from.site) return fail("Za primopredaju odaberite djelatnika s istog objekta.");
    if(!handoverKeys.trim()) return fail("Upišite ključeve / kartice prije predaje.");
    if(!handoverEquipment.trim()) return fail("Upišite službenu opremu prije predaje.");
    if(!handoverCondition.trim()) return fail("Upišite stanje pri predaji prije slanja.");
    if(handoverWeaponEnabled && (!handoverWeaponSerial.trim() || handoverAmmoIssued==="")) return fail("Za zaduženo službeno naoružanje unesite serijski broj i broj metaka pri predaji.");
    const ammoIssued = handoverWeaponEnabled ? Number(handoverAmmoIssued) : null;
    const weapon=handoverWeaponEnabled?{enabled:true,type:handoverWeaponType.trim(),serial:handoverWeaponSerial.trim(),condition:handoverWeaponCondition,ammoIssued,ammoReturned:null,ammoDifference:null}:{enabled:false};
    const row={id:Date.now(),handoverNo:nextHandoverNo(),site:from.site||"—",date:todayISO,time:new Date().toLocaleTimeString("hr-HR",{hour:"2-digit",minute:"2-digit"}),fromEmployee:from.name,fromEmployeeId:from.id||"",toEmployee:to.name,toEmployeeId:to.id,shift:employeeScheduleRecord(from,todayISO)?.shift||from.shift||"—",keys:handoverKeys.trim(),equipment:handoverEquipment.trim(),weapon,openItems:handoverOpenItems.trim()||"Nema otvorenih stavki.",instructions:handoverInstructions.trim()||"Nema dodatnih uputa.",condition:handoverCondition.trim(),status:"ČEKA PREUZIMANJE",createdAt:new Date().toISOString()};
    setHandovers(prev=>[row,...prev]);
    addAudit("PRIMOPREDAJA PREDANA",`${row.handoverNo} · ${row.fromEmployee} → ${row.toEmployee} · ${row.site}${weapon.enabled?" · evidentirano službeno naoružanje i streljivo":""}`);
    setHandoverFromEmployeeId("");setHandoverToEmployeeId("");setHandoverKeys("");setHandoverEquipment("");setHandoverWeaponEnabled(false);setHandoverWeaponType("Službeno vatreno oružje");setHandoverWeaponSerial("");setHandoverWeaponCondition("Ispravno");setHandoverAmmoIssued("");setHandoverAmmoReturned("");setHandoverOpenItems("");setHandoverInstructions("");setHandoverCondition("");
    alert(`Primopredaja ${row.handoverNo} je evidentirana i čeka potvrdu preuzimanja.`);
    return true;
  }

  function acceptHandover(id){
    const h=handovers.find(x=>x.id===id);
    if(!h) return alert("Primopredaja više nije dostupna. Osvježite prikaz.");
    const sameReceiver = (h.toEmployeeId && currentEmployee?.id && h.toEmployeeId===currentEmployee.id) || (!h.toEmployeeId && h.toEmployee===currentEmployee?.name);
    if(!sameReceiver) return alert(`Ovu primopredaju može potvrditi samo preuzimatelj: ${h.toEmployee}. U demo načinu gore odaberite tog djelatnika kao prijavljenog korisnika.`);
    let weaponUpdate = h.weapon || {enabled:false};
    if(h.weapon?.enabled){
      const raw = handoverAcceptAmmo[id];
      if(raw===undefined || raw===null || String(raw).trim()==="") return alert("Upišite broj metaka pri preuzimanju prije potvrde.");
      const returned=Number(String(raw).replace(",","."));
      if(!Number.isInteger(returned) || returned<0) return alert("Broj metaka pri preuzimanju mora biti cijeli broj 0 ili veći.");
      weaponUpdate={...h.weapon,ammoReturned:returned,ammoDifference:Number(h.weapon.ammoIssued||0)-returned};
    }
    const acceptedBy=currentEmployee?.name||loggedEmployee||currentUserRole;
    setHandovers(prev=>prev.map(x=>x.id===id?{...x,status:"PREUZETO",acceptedAt:new Date().toISOString(),acceptedBy,acceptedById:currentEmployee?.id||"",weapon:weaponUpdate}:x));
    setHandoverAcceptAmmo(prev=>{const next={...prev};delete next[id];return next;});
    addAudit("PRIMOPREDAJA PREUZETA",`${h.handoverNo} · ${acceptedBy}`);
    alert(`Primopredaja ${h.handoverNo} je potvrđena. Preuzeo/la: ${acceptedBy}.`);
  }

  function createInstruction(){
    if(currentUserRole!=="Voditelj" && currentUserRole!=="Administrator") return;
    if(!instructionTitle.trim() || !instructionText.trim()) return alert("Upišite naslov i sadržaj službene upute.");
    const createdBy=currentUserRole==="Administrator"?"Elvis Bukal":(currentEmployee?.name||"Voditelj");
    const row={id:Date.now(),title:instructionTitle.trim(),text:instructionText.trim(),site:instructionSite,priority:instructionPriority,requireAck:instructionRequireAck,createdBy,createdAt:new Date().toISOString(),acks:[],active:true};
    setInstructions(prev=>[row,...prev]);
    addAudit("OBJAVLJENA SLUŽBENA UPUTA",`${row.title} · ${row.site} · ${createdBy}`);
    setInstructionTitle("");setInstructionText("");setInstructionPriority("VAŽNO");setInstructionRequireAck(true);
    alert("Službena uputa je objavljena i odmah je vidljiva djelatnicima u probnom sustavu.");
  }

  function acknowledgeInstruction(id){
    if(currentUserRole!=="Zaštitar" || !currentEmployee) return;
    const i=instructions.find(x=>x.id===id); if(!i) return;
    if(i.acks?.some(a=>a.employeeId===currentEmployee.id)) return;
    const ack={employeeId:currentEmployee.id,employee:currentEmployee.name,at:new Date().toISOString()};
    setInstructions(prev=>prev.map(x=>x.id===id?{...x,acks:[...(x.acks||[]),ack]}:x));
    addAudit("POTVRĐENO ČITANJE UPUTE",`${i.title} · ${currentEmployee.name}`);
  }

  function closeInstruction(id){
    if(currentUserRole!=="Voditelj" && currentUserRole!=="Administrator") return;
    setInstructions(prev=>prev.map(x=>x.id===id?{...x,active:false,closedAt:new Date().toISOString()}:x));
  }

  function annualLeaveRemaining(emp){
    const entitlement=Number(emp.annualLeaveEntitlement ?? 20);
    const used=Number(emp.annualLeaveUsed ?? 0);
    return Math.max(0,entitlement-used);
  }

  function toggleReplacement(emp){
    if(currentUserRole!=="Voditelj" && currentUserRole!=="Administrator") return;
    setEmployees(prev=>prev.map(x=>x.id===emp.id?{...x,replacementAvailable:!x.replacementAvailable}:x));
  }

  function addPayrollSimulation(emp){
    if(currentUserRole!=="Voditelj") return;
    const raw=prompt(`Simulacija/dodatak za ${emp.name} (€). Unesi pozitivan ili negativan iznos:`,"0");
    if(raw===null) return;
    const amount=Number(String(raw).replace(",","."));
    if(!Number.isFinite(amount)) return alert("Neispravan iznos.");
    const note=prompt("Napomena za odjel Plaća:","Simulacija voditelja")||"Simulacija voditelja";
    setPayrollAdjustments(prev=>[...prev,{id:Date.now(),employeeId:emp.id,employee:emp.name,month:payrollMonth,amount,note,createdBy:"Voditelj",createdAt:new Date().toISOString()}]);
    alert("Simulacija je spremljena. Vidljiva je u odjelu Plaće.");
  }

  function employeeMonthStats(emp){
    const [yy,mm]=payrollMonth.split("-").map(Number);
    const rows=canonicalWorkHours.filter(w=>(w.employeeId===emp.id || w.employee===emp.name) && String(w.date||"").startsWith(payrollMonth));
    const worked=rows.reduce((s,w)=>s+Number(w.hours||0),0);
    const goPaid=rows.reduce((s,w)=>s+(w.shift==="GO"?Number(w.paidHours||8):0),0);
    const paidTotal=worked+goPaid;
    const night=rows.reduce((s,w)=>s+Number(w.nightHours||0),0);
    const sunday=rows.reduce((s,w)=>s+Number(w.sundayHours||0),0);
    const holiday=rows.reduce((s,w)=>s+Number(w.holidayHours||0),0);
    const fund=monthlyWorkFund(yy,mm-1,40).hours;
    const overtime=Math.max(0,worked-fund);
    const adjustment=payrollAdjustments.filter(a=>a.employeeId===emp.id && a.month===payrollMonth).reduce((s,a)=>s+Number(a.amount||0),0);
    const baseGross=Number(emp.baseGross||0);
    const hourly=fund>0?baseGross/fund:0;
    const regularGross=hourly*Math.min(paidTotal,fund);
    const overtimeAdd=hourly*overtime*(Number(payrollRates.overtime||0)/100);
    const nightAdd=hourly*night*(Number(payrollRates.night||0)/100);
    const sundayAdd=hourly*sunday*(Number(payrollRates.sunday||0)/100);
    const holidayAdd=hourly*holiday*(Number(payrollRates.holiday||0)/100);
    const grossEstimate=regularGross+overtimeAdd+nightAdd+sundayAdd+holidayAdd+adjustment;
    return {worked,goPaid,paidTotal,night,sunday,holiday,fund,overtime,adjustment,baseGross,hourly,regularGross,overtimeAdd,nightAdd,sundayAdd,holidayAdd,grossEstimate};
  }


  function printWorkOrder(emp){
    if(!emp) return;
    const esc=s=>String(s??"").replace(/[&<>"']/g,m=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;",'\'':"&#039;"}[m]));
    const employeeName=displayEmployeeName(emp.name||"");
    const site=emp.workLocation||emp.site||"—";
    const html=`<!doctype html><html><head><meta charset="utf-8"><title>${esc(emp.workOrderNo||"Radni nalog")}</title>
    <style>
      @page{size:A4;margin:16mm}*{box-sizing:border-box}body{font-family:Inter,Segoe UI,Arial,sans-serif;color:#18334d;margin:0;background:#fff}
      .top{display:flex;justify-content:space-between;align-items:center;border-bottom:3px solid #b78b2e;padding-bottom:14px;margin-bottom:18px}
      .brand{font-size:22px;font-weight:950;letter-spacing:.4px}.brand span{color:#b78b2e}.doc{font-size:10px;color:#718091;text-align:right}.doc b{display:block;color:#173957;font-size:14px;margin-top:2px}
      .title{background:linear-gradient(135deg,#102d48,#173f63);color:#fff;border-radius:10px;padding:16px 18px;margin-bottom:14px}.title small{font-size:9px;letter-spacing:1px;color:#d9e1e8;font-weight:800}.title h1{margin:4px 0 0;font-size:22px}
      .grid{display:grid;grid-template-columns:1fr 1fr;gap:9px;margin-bottom:14px}.field{border:1px solid #dce4eb;border-radius:8px;padding:10px 12px;background:#fbfcfd}.field.wide{grid-column:1/-1}.label{display:block;font-size:8px;text-transform:uppercase;letter-spacing:.6px;color:#7b8996;font-weight:900;margin-bottom:4px}.value{font-size:11px;font-weight:750;color:#1b3852;line-height:1.45}
      .section{border:1px solid #dce4eb;border-radius:8px;overflow:hidden;margin-top:12px}.sectionHead{background:#f1f4f7;padding:8px 11px;font-size:9px;font-weight:900;color:#173957;text-transform:uppercase;letter-spacing:.6px}.sectionBody{padding:12px;font-size:10px;line-height:1.55;color:#40566a;min-height:65px}
      .sign{display:grid;grid-template-columns:1fr 1fr;gap:70px;margin-top:65px}.sign div{border-top:1px solid #43515d;padding-top:7px;text-align:center;font-size:9px;color:#566879}.foot{display:flex;justify-content:space-between;margin-top:28px;padding-top:8px;border-top:1px solid #e2e7eb;color:#8895a1;font-size:8px}
      button{margin-top:18px;border:0;background:#b78b2e;color:#fff;border-radius:7px;padding:9px 13px;font-weight:800}@media print{button{display:none}}
    </style></head><body>
      <div class="top"><div class="brand">SENTRY<span>PRO</span></div><div class="doc">RADNI NALOG<b>${esc(emp.workOrderNo||"—")}</b></div></div>
      <div class="title"><small>SLUŽBENI OPERATIVNI DOKUMENT</small><h1>Radni nalog djelatnika</h1></div>
      <div class="grid">
        <div class="field"><span class="label">Djelatnik</span><div class="value">${esc(employeeName)}</div></div>
        <div class="field"><span class="label">Broj iskaznice</span><div class="value">${esc(emp.cardNumber||"—")}</div></div>
        <div class="field"><span class="label">Licenca</span><div class="value">${esc(emp.license||"—")} · vrijedi do ${esc(emp.licenseExpiry||"—")}</div></div>
        <div class="field"><span class="label">Radno mjesto</span><div class="value">${esc(emp.workplace||emp.role||"—")}</div></div>
        <div class="field wide"><span class="label">Objekt</span><div class="value">${esc(site)}</div></div>
        <div class="field wide"><span class="label">Radno vrijeme</span><div class="value">${esc(workTimeLabel(site))}</div></div>
      </div>
      <div class="section"><div class="sectionHead">Ovlasti i operativne zadaće</div><div class="sectionBody">${esc(emp.authorities||"—")}</div></div>
      <div class="section"><div class="sectionHead">Napomena</div><div class="sectionBody">Radni nalog vrijedi za navedeni objekt i razdoblje rada. Sve promjene radnog naloga evidentiraju se u SENTRYPRO sustavu.</div></div>
      <div class="sign"><div>Djelatnik</div><div>Voditelj / ovlaštena osoba</div></div>
      <div class="foot"><span>SENTRYPRO · ${esc(emp.workOrderNo||"")}</span><span>Generirano: ${esc(new Date().toLocaleString("hr-HR"))}</span></div>
      <button onclick="window.print()">Ispis / Spremi kao PDF</button><script>window.onload=()=>setTimeout(()=>window.print(),250)</script></body></html>`;
    const w=window.open("","_blank","width=900,height=900"); if(w){w.document.write(html);w.document.close();}
  }

  function printPayslip(emp){
    const s=employeeMonthStats(emp);
    const [yy,mm]=payrollMonth.split("-").map(Number);
    const label=new Date(yy,mm-1,1).toLocaleDateString("hr-HR",{month:"long",year:"numeric"});
    const w=window.open("","_blank","width=850,height=900");
    if(!w) return;
    w.document.write(`<!doctype html><html><head><meta charset="utf-8"><title>Obračunski pregled - ${emp.name}</title><style>
      body{font-family:Arial,sans-serif;color:#173957;padding:32px}h1{color:#a67c24;margin-bottom:4px}.muted{color:#71808f}table{border-collapse:collapse;width:100%;margin-top:24px}th,td{border:1px solid #d8dee5;padding:10px;text-align:left}th{background:#eef2f6}.warn{margin-top:20px;padding:12px;background:#fff6df;border:1px solid #ead8a3;font-size:12px}@media print{button{display:none}}</style></head><body>
      <h1>SENTRYPRO</h1><div><b>Mjesečni obračunski pregled</b></div><div class="muted">${emp.name} · ${label}</div>
      <table><tr><th>Fond sati</th><td>${s.fund.toFixed(1)}</td></tr><tr><th>Odrađeno</th><td>${s.worked.toFixed(1)}</td></tr><tr><th>GO (plaćeno)</th><td>${s.goPaid.toFixed(1)} h</td></tr><tr><th>Ukupno sati za isplatu</th><td>${s.paidTotal.toFixed(1)} h</td></tr><tr><th>Prekovremeno</th><td>${s.overtime.toFixed(1)}</td></tr><tr><th>Noćni rad</th><td>${s.night.toFixed(1)}</td></tr><tr><th>Nedjelja</th><td>${s.sunday.toFixed(1)}</td></tr><tr><th>Blagdan</th><td>${s.holiday.toFixed(1)}</td></tr><tr><th>Osnovna bruto plaća</th><td>${s.baseGross.toFixed(2)} €</td></tr><tr><th>Redovni bruto prema evidentiranim satima</th><td>${s.regularGross.toFixed(2)} €</td></tr><tr><th>Dodatak prekovremeni</th><td>${s.overtimeAdd.toFixed(2)} €</td></tr><tr><th>Dodatak noćni</th><td>${s.nightAdd.toFixed(2)} €</td></tr><tr><th>Dodatak nedjelja</th><td>${s.sundayAdd.toFixed(2)} €</td></tr><tr><th>Dodatak blagdan</th><td>${s.holidayAdd.toFixed(2)} €</td></tr><tr><th>Simulacije/korekcije</th><td>${s.adjustment.toFixed(2)} €</td></tr><tr><th><b>PROCJENA BRUTO</b></th><td><b>${s.grossEstimate.toFixed(2)} €</b></td></tr><tr><th>Preostali GO</th><td>${annualLeaveRemaining(emp)} dana</td></tr></table>
      <div class="warn"><b>Važno:</b> Ovo je obračunski pregled/simulacija. Konačna službena platna lista zahtijeva konfigurirane ugovorene bruto iznose, dodatke, porezne parametre, neoporezive primitke, doprinose i druga pravila konkretne tvrtke.</div>
      <button onclick="window.print()">Ispis / Spremi kao PDF</button></body></html>`);
    w.document.close(); setTimeout(()=>w.print(),250);
  }

  function printSchedulePdf(){
    const [yy,mm]=scheduleMonth.split("-").map(Number);
    const monthLabel=new Date(yy,mm-1,1).toLocaleDateString("hr-HR",{month:"long",year:"numeric"});
    const days=new Date(yy,mm,0).getDate();
    const rows=employeesForSchedule.map(emp=>{
      const cells=Array.from({length:days},(_,i)=>{
        const day=String(i+1).padStart(2,"0");
        const rec=workHours.find(w=>w.employee===emp.name && w.site===visibleScheduleSite && w.date===`${scheduleMonth}-${day}`);
        return `<td>${rec?.shift||"·"}</td>`;
      }).join("");
      return `<tr><th>${emp.name}</th>${cells}</tr>`;
    }).join("");
    const heads=Array.from({length:days},(_,i)=>`<th>${i+1}</th>`).join("");
    const w=window.open("","_blank","width=1200,height=800");
    if(!w) return;
    w.document.write(`<!doctype html><html><head><meta charset="utf-8"><title>SENTRYPRO raspored - ${visibleScheduleSite}</title>
      <style>body{font-family:Arial,sans-serif;color:#173957;padding:22px}h1{margin:0;color:#a67c24}.meta{margin:4px 0 16px;color:#5f6f7f}table{border-collapse:collapse;width:100%;font-size:8px;table-layout:fixed}th,td{border:1px solid #cfd6dd;text-align:center;padding:4px}th:first-child{width:120px;text-align:left}thead th{background:#eef2f6}.sig{display:flex;justify-content:space-between;margin-top:35px;gap:50px}.sig div{border-top:1px solid #333;padding-top:6px;width:220px;text-align:center;font-size:10px}@media print{button{display:none}body{padding:8px}}</style>
      </head><body><h1>SENTRYPRO</h1><div class="meta"><b>Mjesečni raspored</b> · ${visibleScheduleSite} · ${monthLabel}</div>
      <table><thead><tr><th>Djelatnik</th>${heads}</tr></thead><tbody>${rows}</tbody></table>
      <div class="sig"><div>Voditelj / administrator</div><div>Datum objave rasporeda</div></div>
      <p style="font-size:9px;color:#71808f">Oznake: ${isBankSite(visibleScheduleSite)?"I = 08:00–20:00, SL = slobodan dan (izmjena I / SL)":"I = 07:00–19:00, II = 19:00–07:00, SL = slobodan"}, GO = godišnji odmor, BO = bolovanje.</p>
      <button onclick="window.print()">Ispis / Spremi kao PDF</button></body></html>`);
    w.document.close();
    setTimeout(()=>w.print(),250);
  }

  function emailSchedule(){
    const recipients=employeesForSchedule.map(e=>e.email).filter(Boolean);
    if(!recipients.length){ alert("Za ovaj objekt nema upisanih poslovnih e-mail adresa djelatnika."); return; }
    const [yy,mm]=scheduleMonth.split("-").map(Number);
    const monthLabel=new Date(yy,mm-1,1).toLocaleDateString("hr-HR",{month:"long",year:"numeric"});
    const subject=`SENTRYPRO raspored - ${visibleScheduleSite} - ${monthLabel}`;
    const body=`Poštovani,%0D%0A%0D%0Au privitku je mjesečni raspored rada za objekt ${encodeURIComponent(visibleScheduleSite)} za ${encodeURIComponent(monthLabel)}.%0D%0A%0D%0ALijep pozdrav,%0D%0ASENTRYPRO`;
    window.open(`mailto:${recipients.join(";")}?subject=${encodeURIComponent(subject)}&body=${body}`,"_blank");
  }

  function enterVisitor(id){
    setVisitors(prev=>prev.map(v=>v.id===id?{...v,status:"U OBJEKTU",enteredAt:now(),exitedAt:""}:v));
  }
  function exitVisitor(id){
    const v = visitors.find(x=>x.id===id);
    if(!v) return;
    if(!window.confirm(`Potvrdi izlazak posjetitelja: ${v.firstName} ${v.lastName}`)) return;
    setVisitors(prev=>prev.map(x=>x.id===id?{...x,status:"IZAŠAO",exitedAt:now()}:x));
  }
  function addVisitor(e){
    e.preventDefault();
    const f=new FormData(e.currentTarget);
    const row={
      id:Date.now(), firstName:f.get("firstName"), lastName:f.get("lastName"),
      company:f.get("company"), visiting:f.get("visiting"), reason:f.get("reason"),
      site:f.get("site"), date:f.get("date")||today, expected:f.get("expected")||"",
      plate:f.get("plate")||"", card:f.get("card")||"", documentNumber:f.get("documentNumber")||"", note:f.get("note")||"",
      enteredAt:"", exitedAt:"", status:"NAJAVLJEN"
    };
    setVisitors(prev=>[row,...prev]); setShowVisitor(false);
  }
  function addEvent(e){
    e.preventDefault();
    const f=new FormData(e.currentTarget);
    const file = f.get("attachment");
    setEvents(prev=>[{
      id:Date.now(),
      date:f.get("date")||isoDate(),
      time:f.get("time")||now(),
      category:f.get("category"),
      title:f.get("title"),
      description:f.get("description"),
      site:f.get("site"),
      level:f.get("level"),
      recordedBy:f.get("recordedBy"),
      followUp:f.get("followUp")||"",
      attachment:file && file.name ? file.name : ""
    },...prev]);
    setShowEvent(false);
  }







  function easterDate(year){
    const f=Math.floor, G=year%19, C=f(year/100), H=(C-f(C/4)-f((8*C+13)/25)+19*G+15)%30,
      I=H-f(H/28)*(1-f(29/(H+1))*f((21-G)/11)), J=(year+f(year/4)+I+2-C+f(C/4))%7,
      L=I-J, month=3+f((L+40)/44), day=L+28-31*f(month/4);
    return new Date(year,month-1,day);
  }

  function croatianHolidaySet(year){
    const pad=n=>String(n).padStart(2,"0");
    const fmt=d=>`${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}`;
    const fixed=[
      [1,1],[1,6],[5,1],[5,30],[6,22],[8,5],[8,15],[11,1],[11,18],[12,25],[12,26]
    ];
    const s=new Set(fixed.map(([m,d])=>`${year}-${pad(m)}-${pad(d)}`));
    const easter=easterDate(year);
    const mon=new Date(easter); mon.setDate(mon.getDate()+1);
    const corpus=new Date(easter); corpus.setDate(corpus.getDate()+60);
    s.add(fmt(easter)); s.add(fmt(mon)); s.add(fmt(corpus));
    return s;
  }

  function isSundayOrHoliday(dateStr){
    const d=new Date(dateStr+"T12:00:00");
    const sunday=d.getDay()===0;
    const holiday=croatianHolidaySet(d.getFullYear()).has(dateStr);
    return {sunday,holiday,isPremium:sunday||holiday};
  }

  const canRequestNextMonth = new Date().getDate() <= 17;

  function simulateLpr(){
    const plate=lprPlate.trim().toUpperCase();
    if(!plate) return;
    const emp=employees.find(e=>(e.vehiclePlate||"").toUpperCase()===plate);
    const allowed=!!(emp && emp.active!==false && emp.vehicleAccess && emp.site===accessSite);
    const row={id:Date.now(),type:"LPR",employee:emp?.name||"Nepoznato vozilo",plate,site:accessSite,direction:"ULAZ",time:now(),date:isoDate(),result:allowed?"RAMPA OTVORENA":"PRISTUP ODBIJEN"};
    setAccessEvents(prev=>[row,...prev]);
    setLprPlate("");
  }

  function simulateCard(){
    const card=cardScan.trim().toUpperCase();
    if(!card) return;
    const emp=employees.find(e=>(e.cardNumber||"").toUpperCase()===card);
    const siteOk=emp && emp.active!==false && emp.site===accessSite;
    const last=accessEvents.find(x=>x.type==="KARTICA" && x.employee===emp?.name && x.site===accessSite);
    const direction=last?.direction==="ULAZ"?"IZLAZ":"ULAZ";
    setAccessEvents(prev=>[{id:Date.now(),type:"KARTICA",employee:emp?.name||"Nepoznata kartica",card,site:accessSite,direction,time:now(),date:isoDate(),result:siteOk?"ODOBRENO":"PRISTUP ODBIJEN"},...prev]);
    setCardScan("");
  }

  function aiEmergencyAssessment(text,priority){
    const t=text.toLowerCase();
    const critical=["požar","oružje","napad","provala","eksploz","životno","teško ozlijeđen","pucanj","prijetnja bomb"];
    const isCritical=priority==="HITNO" || critical.some(k=>t.includes(k));
    return isCritical
      ? "AI: moguća kritična situacija — predložena hitna eskalacija prema voditelju i CDS-u. Za stvarno slanje potreban je odobreni CDS protokol/API."
      : "AI: poruka usmjerena voditelju; nema indikacije za CDS eskalaciju.";
  }

  function sendMessage(){
    const text=messageText.trim();
    if(!text) return;
    const emp=employees.find(e=>e.name===loggedEmployee);
    const ai=aiEmergencyAssessment(text,messagePriority);
    setMessages(prev=>[{id:Date.now(),from:loggedEmployee,site:emp?.site||"—",to:messagePriority==="HITNO"?"Voditelj + CDS (na čekanju integracije)":"Voditelj",priority:messagePriority,text,time:now(),date:isoDate(),status:"DOSTAVLJENO",direction:"PREMA VODITELJU",ai},...prev]);
    setMessageText("");
  }

  function sendManagerMessage(){
    const text=managerMessageText.trim();
    if(!text) return;
    const ai=aiEmergencyAssessment(text,managerMessagePriority);
    addAudit("PORUKA NA OBJEKT",`${managerMessageSite} · ${managerMessagePriority}`);
    setMessages(prev=>[{id:Date.now(),from:"Elvis Bukal · Voditelj",site:managerMessageSite,to:`Objekt: ${managerMessageSite}`,priority:managerMessagePriority,text,time:now(),date:isoDate(),status:"DOSTAVLJENO NA OBJEKT",direction:"VODITELJ → OBJEKT",ai},...prev]);
    setManagerMessageText("");
  }

  function leaveDates(from,to){
    if(!from || !to) return [];
    const a=new Date(`${from}T12:00:00`), b=new Date(`${to}T12:00:00`);
    if(Number.isNaN(a.getTime()) || Number.isNaN(b.getTime()) || b<a) return [];
    const out=[]; for(const d=new Date(a);d<=b;d.setDate(d.getDate()+1)) out.push(localDateKey(d));
    return out;
  }

  function addLeaveRequest(){
    if(currentUserRole!=="Zaštitar") return;
    const emp=currentEmployee, dates=leaveDates(leaveFrom,leaveTo);
    if(!emp || !dates.length) return alert("Provjeri datume godišnjeg odmora.");
    const remaining=annualLeaveRemaining(emp);
    if(dates.length>remaining) return alert(`Tražiš ${dates.length} dana, a evidentirano ti je još ${remaining} dana GO.`);
    setLeaveRequests(prev=>[{id:Date.now(),employee:emp.name,employeeId:emp.id,site:emp.site,from:leaveFrom,to:leaveTo,days:dates.length,note:leaveNote,created:isoDate(),status:"NA ČEKANJU"},...prev]);
    setLeaveNote("");
    addAudit("ZAHTJEV GO",`${emp.name} · ${leaveFrom} – ${leaveTo}`);
  }

  function decideLeaveRequest(id,status){
    if(!canManage) return;
    const req=leaveRequests.find(r=>r.id===id); if(!req) return;
    if(status==="ODOBRENO"){
      const emp=employees.find(e=>e.id===req.employeeId || e.name===req.employee);
      const dates=leaveDates(req.from,req.to); if(!emp || !dates.length) return;
      if(req.days>annualLeaveRemaining(emp)) return alert("Nema dovoljno preostalih dana GO.");
      setWorkHours(prev=>{
        const ds=new Set(dates);
        const clean=prev.filter(w=>!((w.employeeId===emp.id || w.employee===emp.name) && ds.has(w.date)));
        const rows=dates.map(date=>({id:`go-${emp.id}-${date}`,employee:emp.name,employeeId:emp.id,site:emp.site,date,shift:"GO",start:"—",end:"—",hours:0,paidHours:8,nightHours:0,sundayHours:0,holidayHours:0}));
        return [...clean,...rows];
      });
      setEmployees(prev=>prev.map(e=>e.id===emp.id?{...e,annualLeaveUsed:Number(e.annualLeaveUsed||0)+req.days}:e));
    }
    setLeaveRequests(prev=>prev.map(r=>r.id===id?{...r,status,decidedBy:"Elvis Bukal",decidedAt:`${isoDate()} ${now()}`}:r));
    addAudit("ODLUKA GO",`${req.employee} · ${req.from} – ${req.to} · ${status}`);
  }

  function decideShiftRequest(id,status){
    if(!canManage) return;
    const req=shiftRequests.find(r=>r.id===id);
    if(!req) return;

    if(status==="ODOBRENO"){
      const emp=employees.find(e=>e.name===req.employee);
      if(emp && req.dateWanted){
        const shift=req.request;
        const preset=shiftPreset(shift,emp?.site||"");
        const seg=shiftSegments(shift,new Date(`${req.dateWanted}T00:00:00`));
        const nextRecord={
          id:`req-${emp.id}-${req.dateWanted}`,
          employee:emp.name,
          employeeId:emp.id,
          site:emp.site,
          date:req.dateWanted,
          shift,
          start:preset[0],
          end:preset[1],
          hours:preset[2],
          nightHours:seg.night,
          sundayHours:seg.sunday,
          holidayHours:seg.holiday
        };
        setWorkHours(prev=>{
          const clean=prev.filter(w=>!((w.employeeId===emp.id || w.employee===emp.name) && w.date===req.dateWanted));
          return [...clean,nextRecord];
        });
      }
    }

    setShiftRequests(prev=>prev.map(r=>r.id===id?{...r,status,decidedBy:"Elvis Bukal",decidedAt:`${isoDate()} ${now()}`}:r));
    addAudit("ODLUKA ZAHTJEVA",`${req.employee} · ${req.dateWanted} · ${req.request} · ${status}`);
  }

  function printEmergencyPdf(message){
    const w=window.open("","_blank","width=900,height=700");
    if(!w) return;
    const esc=s=>String(s||"").replace(/[&<>"']/g,m=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#039;"}[m]));
    w.document.write(`<!doctype html><html><head><meta charset="utf-8"><title>SENTRYPRO - Evidencija hitne situacije</title>
      <style>body{font-family:Arial,sans-serif;padding:42px;color:#15283d}h1{color:#a67c24;margin:0 0 4px}.box{border:1px solid #b7c1cc;padding:18px;margin:18px 0}.row{display:grid;grid-template-columns:180px 1fr;border-bottom:1px solid #e4e7eb;padding:8px 0}.sig{margin-top:70px;display:grid;grid-template-columns:1fr 1fr;gap:60px}.line{border-top:1px solid #333;padding-top:8px;text-align:center}.small{font-size:12px;color:#687789}@media print{button{display:none}}</style>
      </head><body><h1>SENTRYPRO</h1><div class="small">Evidencija hitne / sigurnosne situacije</div>
      <div class="box">
      <div class="row"><b>Datum i vrijeme</b><span>${esc(message.date||isoDate())} ${esc(message.time)}</span></div>
      <div class="row"><b>Objekt</b><span>${esc(message.site)}</span></div>
      <div class="row"><b>Prijavio / poslao</b><span>${esc(message.from)}</span></div>
      <div class="row"><b>Primatelj</b><span>${esc(message.to)}</span></div>
      <div class="row"><b>Prioritet</b><span>${esc(message.priority)}</span></div>
      <div class="row"><b>Opis događaja</b><span>${esc(message.text)}</span></div>
      <div class="row"><b>Procjena sustava</b><span>${esc(message.ai)}</span></div>
      <div class="row"><b>Status</b><span>${esc(message.status)}</span></div>
      </div>
      <p><b>Poduzete mjere / dodatna bilješka:</b></p><div style="height:120px;border:1px solid #bbb"></div>
      <div class="sig"><div class="line">Potpis djelatnika</div><div class="line">Potpis voditelja</div></div>
      <p class="small">Dokument generiran iz SENTRYPRO sustava. Za PDF odaberite "Spremi kao PDF" u prozoru za ispis.</p>
      <button onclick="window.print()">Ispis / Spremi kao PDF</button></body></html>`);
    w.document.close();
    setTimeout(()=>w.print(),250);
  }

  const nextMonthKey = () => {
    const d=new Date();
    return `${d.getFullYear() + (d.getMonth()===11?1:0)}-${String((d.getMonth()+1)%12+1).padStart(2,"0")}`;
  };

  const scheduleBuildOpen = new Date().getDate()>=20;

  function generateNextMonthSchedule(){
    if(!canManage || !scheduleBuildOpen) return;
    const month=nextMonthKey();
    const baseRows=buildDemoWorkHours(employees,month);
    const byKey=new Map();

    baseRows.forEach(w=>byKey.set(`${w.employeeId||w.employee}|${w.date}`,w));

    shiftRequests
      .filter(r=>r.status==="ODOBRENO" && String(r.dateWanted||"").startsWith(month))
      .forEach(r=>{
        const emp=employees.find(e=>e.name===r.employee);
        if(!emp) return;
        const shift=r.request;
        const preset=shiftPreset(shift,emp?.site||"");
        const seg=shiftSegments(shift,new Date(`${r.dateWanted}T00:00:00`));
        byKey.set(`${emp.id}|${r.dateWanted}`,{
          id:`approved-${emp.id}-${r.dateWanted}`,
          employee:emp.name,employeeId:emp.id,site:emp.site,date:r.dateWanted,shift,
          start:preset[0],end:preset[1],hours:preset[2],
          nightHours:seg.night,sundayHours:seg.sunday,holidayHours:seg.holiday
        });
      });

    leaveRequests
      .filter(r=>r.status==="ODOBRENO")
      .forEach(r=>{
        const emp=employees.find(e=>e.id===r.employeeId || e.name===r.employee);
        if(!emp) return;
        leaveDates(r.from,r.to)
          .filter(date=>date.startsWith(month))
          .forEach(date=>{
            byKey.set(`${emp.id}|${date}`,{
              id:`go-${emp.id}-${date}`,
              employee:emp.name,employeeId:emp.id,site:emp.site,date,
              shift:"GO",start:"—",end:"—",hours:0,paidHours:8,
              nightHours:0,sundayHours:0,holidayHours:0
            });
          });
      });

    setWorkHours(prev=>{
      const otherMonths=prev.filter(w=>!String(w.date||"").startsWith(month));
      return [...otherMonths,...Array.from(byKey.values())];
    });
    setScheduleMonth(month);
    setScheduleSite(sites[0]?.name||scheduleSite);
    addAudit("NOVI RASPORED",`Generiran raspored za ${month} s odobrenim zahtjevima i GO.`);
    alert(`Raspored za ${month} je složen. Odobreni SL/I/II i GO su automatski primijenjeni.`);
  }

  function addShiftRequest(){
    if(!canRequestNextMonth) return;
    const emp=employees.find(e=>e.name===loggedEmployee);
    if(!requestDate) return;
    setShiftRequests(prev=>[{id:Date.now(),employee:loggedEmployee,site:emp?.site||"—",month:requestDate.slice(0,7),request:requestType,dateWanted:requestDate,note:requestNote,created:isoDate(),status:"NA ČEKANJU"},...prev]);
    setRequestNote("");
  }


  function addSite(e){
    e.preventDefault();
    const f = new FormData(e.currentTarget);
    const payload = {
      name:f.get("name")||"",
      client:f.get("client")||"",
      city:f.get("city")||"",
      address:f.get("address")||"",
      contact:f.get("contact")||"",
      phone:f.get("phone")||"",
      guards:f.get("guards")||"0/0",
      mail:f.get("mail")||"",
      camera:f.get("camera")||"",
      gate:f.get("gate")||"",
      status:"U REDU"
    };
    if(editingSite){
      setSites(prev=>prev.map(s=>s.id===editingSite.id?{...s,...payload}:s));
    } else {
      setSites(prev=>[{id:Date.now(),...payload},...prev]);
    }
    setEditingSite(null);
    setShowSite(false);
  }

  function editSite(site){
    setEditingSite(site);
    setShowSite(true);
  }

  function addWorkHours(e){
    e.preventDefault();
    const f = new FormData(e.currentTarget);
    const shift = f.get("shift");
    const presets = {I:["07:00","19:00",12],II:["19:00","07:00",12],SL:["—","—",0],GO:["—","—",0],BO:["—","—",0]};
    const pr = presets[shift] || ["—","—",0];
    const emp = employees.find(x=>x.name===f.get("employee"));
    const date=f.get("date");
    const seg=shiftSegments(shift,new Date(`${date}T00:00:00`));
    setWorkHours(prev=>[{
      id:Date.now(), employee:f.get("employee"), site:f.get("site") || emp?.site || "—",
      date, shift, start:pr[0], end:pr[1], hours:pr[2],
      nightHours:seg.night, sundayHours:seg.sunday, holidayHours:seg.holiday
    },...prev]);
    setShowHours(false);
  }

  function editEmployee(emp){
    setEditingUser(emp);
    setShowUser(true);
  }

  function toggleEmployeeActive(emp){
    const next = emp.active === false;
    const msg = next ? "Ponovno aktivirati ovog djelatnika?" : "Deaktivirati djelatnika? Podaci ostaju spremljeni u sustavu.";
    if(window.confirm(msg)){
      setEmployees(prev=>prev.map(x=>x.id===emp.id?{...x,active:next,status:next?x.status:"Neaktivan"}:x));
    }
  }

  function addPatrol(e){
    e.preventDefault();
    const f = new FormData(e.currentTarget);
    const start = f.get("start");
    const end = f.get("end");
    let duration = 0;
    if(start && end){
      const [sh,sm]=start.split(":").map(Number);
      const [eh,em]=end.split(":").map(Number);
      duration=(eh*60+em)-(sh*60+sm);
      if(duration<0) duration+=24*60;
    }
    const done = Number(f.get("checkpointsDone")||0);
    const total = Number(f.get("checkpointsTotal")||0);
    const missed = Math.max(total-done,0);
    setPatrols(prev=>[{
      id:Date.now(),
      employee:f.get("employee"),
      cardNumber:(employees.find(e=>e.name===f.get("employee"))||{}).cardNumber||"",
      site:f.get("site"),
      date:f.get("date")||today,
      start,end,duration,
      checkpointsDone:done,
      checkpointsTotal:total,
      missed,
      status: missed===0 ? "U REDU" : "NEPOTPUNO",
      source:f.get("source")||"Ručni unos"
    },...prev]);
    setShowPatrol(false);
  }

  function addUser(e){
    e.preventDefault();
    const f = new FormData(e.currentTarget);
    const payload = {
      name: f.get("name") || "",
      role: f.get("role") || "Zaštitar",
      site: f.get("site") || "—",
      assignedSites: (()=>{ const a=f.getAll("assignedSites").filter(Boolean); const primary=f.get("site")||"—"; return Array.from(new Set([primary,...a].filter(x=>x && x!=="—"))); })(),
      shift: f.get("shift") || "—",
      status: f.get("status") || "Slobodan",
      phone: f.get("phone") || "",
      email: f.get("email") || "",
      cardNumber: f.get("cardNumber") || "",
      license: f.get("license") || "",
      licenseExpiry: f.get("licenseExpiry") || "",
      employmentDate: f.get("employmentDate") || "",
      active: editingUser ? editingUser.active !== false : true,
      vehiclePlate: f.get("vehiclePlate") || "",
      vehicleAccess: f.get("vehicleAccess")==="on",
      replacementAvailable: f.get("replacementAvailable")==="on",
      annualLeaveEntitlement: Number(f.get("annualLeaveEntitlement")||20),
      annualLeaveUsed: Number(f.get("annualLeaveUsed")||0),
      baseGross: Number(f.get("baseGross")||0),
      authorities: f.get("authorities") || "Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu"
    };
    if(editingUser){
      setEmployees(prev=>prev.map(x=>x.id===editingUser.id?{...x,...payload}:x));
    } else {
      setEmployees(prev=>[{id:Date.now(),...payload},...prev]);
    }
    setEditingUser(null);
    setShowUser(false);
  }

  function cycleSchedule(emp, date){
    if(!canManage) return;
    const order=["","I","II","SL","GO","BO"];
    const existing=canonicalWorkHours.find(w=>(w.employeeId===emp.id || w.employee===emp.name) && w.date===date);
    const current=existing?.shift||""; const next=order[(order.indexOf(current)+1)%order.length];
    const preset=shiftPreset(next,emp.site);
    const seg=shiftSegments(next,new Date(`${date}T00:00:00`),emp.site);
    setWorkHours(prev=>{
      const nextRecord={
        id:existing?.id || `manual-${emp.id}-${date}`,
        employee:emp.name,
        employeeId:emp.id,
        site:emp.site,
        date,
        shift:next,
        start:preset[0],
        end:preset[1],
        hours:preset[2],
        nightHours:seg.night,
        sundayHours:seg.sunday,
        holidayHours:seg.holiday
      };
      const filtered=prev.filter(w=>!((w.employeeId===emp.id || w.employee===emp.name) && w.date===date));
      return [...filtered,nextRecord];
    });
  }

  function deleteUser(id){
    const u = employees.find(x=>x.id===id);
    if(!u) return;
    if(!window.confirm(`Obrisati korisnika: ${u.name}?`)) return;
    setEmployees(prev=>prev.filter(x=>x.id!==id));
  }

  const dateLabel="Sub, 13.09.2026.";

  const uiText={
    hr:{welcome:"Dobro došli",subtitle:"Operativni centar zaštitarske službe",online:"Sustav online",permissions:"Prikaz ovlasti",logout:"Odjava",login:"Ulaz u demo sustav",loginTitle:"Sigurnost. Kontrola. Odgovornost.",loginSub:"Profesionalna platforma za upravljanje zaštitarskom službom.",language:"Jezik",demo:"PROBNA VERZIJA"},
    en:{welcome:"Welcome",subtitle:"Security Operations Center",online:"System online",permissions:"Role preview",logout:"Sign out",login:"Enter demo system",loginTitle:"Security. Control. Accountability.",loginSub:"Professional platform for security operations management.",language:"Language",demo:"DEMO VERSION"},
    de:{welcome:"Willkommen",subtitle:"Operative Zentrale des Sicherheitsdienstes",online:"System online",permissions:"Rollenansicht",logout:"Abmelden",login:"Demo-System öffnen",loginTitle:"Sicherheit. Kontrolle. Verantwortung.",loginSub:"Professionelle Plattform zur Steuerung von Sicherheitsdiensten.",language:"Sprache",demo:"DEMOVERSION"},
    it:{welcome:"Benvenuto",subtitle:"Centro operativo del servizio di sicurezza",online:"Sistema online",permissions:"Anteprima ruolo",logout:"Esci",login:"Accedi al sistema demo",loginTitle:"Sicurezza. Controllo. Responsabilità.",loginSub:"Piattaforma professionale per la gestione dei servizi di sicurezza.",language:"Lingua",demo:"VERSIONE DEMO"}
  };
  const t=(key)=>uiText[language]?.[key]||uiText.hr[key]||key;
  const navTranslations={
    en:{"Pregled":"Overview","Najave / posjetitelji":"Announcements / visitors","Dnevnik događaja":"Event log","Objekti":"Sites","Djelatnici":"Employees","Raspored":"Schedule","Radni nalozi":"Work orders","Evidencija sati":"Time records","Obilasci":"Patrols","Zahtjevi smjena":"Shift requests","Poruke / Hitne situacije":"Messages / Emergencies","Pošta objekta":"Site mail","Vozila i pristup":"Vehicles & access","Izvješća":"Reports","Primopredaja smjene":"Shift handover","Obavijesti i upute":"Notices & instructions","Plaće":"Payroll","Postavke":"Settings","OPERATIVNO":"OPERATIONS","KOMUNIKACIJA":"COMMUNICATION","VOZILA I PRISTUP":"VEHICLES & ACCESS","IZVJEŠĆA":"REPORTS","ADMINISTRACIJA":"ADMINISTRATION"},
    de:{"Pregled":"Übersicht","Najave / posjetitelji":"Anmeldungen / Besucher","Dnevnik događaja":"Ereignisprotokoll","Objekti":"Objekte","Djelatnici":"Mitarbeiter","Raspored":"Dienstplan","Radni nalozi":"Arbeitsaufträge","Evidencija sati":"Arbeitszeiterfassung","Obilasci":"Kontrollgänge","Zahtjevi smjena":"Schichtanträge","Poruke / Hitne situacije":"Nachrichten / Notfälle","Pošta objekta":"Objektpost","Vozila i pristup":"Fahrzeuge & Zutritt","Izvješća":"Berichte","Primopredaja smjene":"Schichtübergabe","Obavijesti i upute":"Mitteilungen & Anweisungen","Plaće":"Lohnabrechnung","Postavke":"Einstellungen","OPERATIVNO":"BETRIEB","KOMUNIKACIJA":"KOMMUNIKATION","VOZILA I PRISTUP":"FAHRZEUGE & ZUTRITT","IZVJEŠĆA":"BERICHTE","ADMINISTRACIJA":"ADMINISTRATION"},
    it:{"Pregled":"Panoramica","Najave / posjetitelji":"Preavvisi / visitatori","Dnevnik događaja":"Registro eventi","Objekti":"Siti","Djelatnici":"Dipendenti","Raspored":"Turni","Radni nalozi":"Ordini di lavoro","Evidencija sati":"Registro ore","Obilasci":"Ronde","Zahtjevi smjena":"Richieste turno","Poruke / Hitne situacije":"Messaggi / Emergenze","Pošta objekta":"Posta del sito","Vozila i pristup":"Veicoli e accessi","Izvješća":"Rapporti","Primopredaja smjene":"Passaggio di consegne","Obavijesti i upute":"Avvisi e istruzioni","Plaće":"Paghe","Postavke":"Impostazioni","OPERATIVNO":"OPERATIVO","KOMUNIKACIJA":"COMUNICAZIONE","VOZILA I PRISTUP":"VEICOLI E ACCESSI","IZVJEŠĆA":"RAPPORTI","ADMINISTRACIJA":"AMMINISTRAZIONE"}
  };
  const tr=(text)=>language==="hr"?text:(navTranslations[language]?.[text]||text);

  if(!demoLoggedIn) return <div className="loginScreen">
    <div className="loginLanguage"><span>{t("language")}</span><select value={language} onChange={e=>setLanguage(e.target.value)}><option value="hr">HR · Hrvatski</option><option value="en">EN · English</option><option value="de">DE · Deutsch</option><option value="it">IT · Italiano</option></select></div>
    <div className="loginCard"><img src={logo} className="loginLogo"/><div className="loginBrand">SENTRY<span>PRO</span></div><div className="demoPill">{t("demo")}</div><h1>{t("loginTitle")}</h1><p>{t("loginSub")}</p><button className="loginBtn" onClick={()=>setDemoLoggedIn(true)}>{t("login")}</button><small>v0.26.2 · Windows Desktop</small></div>
  </div>;

  return <div className="shell">
    <aside className="sidebar">
      <div className="brandBlock">
        <img src={logo} className="brandLogo"/>
        <div className="brandName">SENTRY<span>PRO</span></div>
        
      </div>

      <nav>
        {navItems.filter(([id])=>{
          if(currentUserRole==="Zaštitar") return ["dashboard","log","shifts","workorder","hours","patrols","requests","messages","mail","reports","handover","instructions"].includes(id);
          if(currentUserRole==="Voditelj") return ["dashboard","visitors","log","users","shifts","workorder","hours","patrols","requests","messages","reports","handover","instructions"].includes(id);
          if(currentUserRole==="Direktor") return ["dashboard","reports"].includes(id);
          if(currentUserRole==="Plaće") return ["dashboard","users","payroll"].includes(id);
          if(currentUserRole==="Administrator") return ["dashboard","log","sites","users","shifts","workorder","hours","reports","handover","instructions","settings"].includes(id);
          if(currentUserRole==="Klijent") return ["visitors"].includes(id);
          return false;
        }).map(([id,ico,label,group],idx,items)=>{
          const previousGroup = idx > 0 ? items[idx-1][3] : null;
          return <React.Fragment key={id}>
            {group && group !== previousGroup && <div className="navGroup">{tr(group)}</div>}
            <button className={page===id?"active":""} onClick={()=>setPage(id)}>
              <span className="navIcon">{ico}</span><span>{tr(label)}</span>
            </button>
          </React.Fragment>;
        })}
      </nav>

      <div className="sideProfile">
        <div className="userCircle">EB</div>
        <div><b>Elvis Bukal</b><span>{currentUserRole}</span></div>
      </div>
      <button className="sideLogout" onClick={()=>setDemoLoggedIn(false)}>↪ {t("logout")}</button>
      <div className="version">SENTRYPRO v0.25.0</div>
    </aside>

    <div className="content">
      <header className="topbar">
        <div><h2>{t("welcome")}, Elvis</h2><p>{t("subtitle")}</p></div>
        <div className="topRight">
          <div className="online"><i></i>{t("online")}</div>
          <div className="timeBox"><b>{now()}</b><span>{dateLabel}</span></div>
          <div className="languageMini"><span>{t("language")}</span><select value={language} onChange={e=>setLanguage(e.target.value)}><option value="hr">HR</option><option value="en">EN</option><option value="de">DE</option><option value="it">IT</option></select></div><div className="roleDemo"><span>{t("permissions")}</span><select value={currentUserRole} onChange={e=>{const r=e.target.value;setCurrentUserRole(r);if(r==="Zaštitar"){const g=employees.find(x=>/^zaštitar$/i.test(x.role||"")&&x.active!==false);if(g)setLoggedEmployee(g.name);setPage("dashboard");}else if(r==="Voditelj"){const m=employees.find(x=>/voditelj/i.test(x.role||"")&&x.active!==false);if(m)setLoggedEmployee(m.name);if(sites[0]?.name){setScheduleSite(sites[0].name);setReportSite(sites[0].name);}setPage("dashboard");}else if(r==="Direktor")setPage("reports");else if(r==="Klijent")setPage("visitors");else if(r==="Plaće")setPage("payroll");else setPage("dashboard");}}><option value="Administrator">{language==="de"?"Administrator":language==="it"?"Amministratore":"Administrator"}</option><option value="Voditelj">{language==="en"?"Manager":language==="de"?"Leiter":language==="it"?"Responsabile":"Voditelj"}</option><option value="Zaštitar">{language==="en"?"Security officer":language==="de"?"Sicherheitsmitarbeiter":language==="it"?"Addetto alla sicurezza":"Zaštitar"}</option><option value="Direktor">{language==="en"?"Director":language==="de"?"Direktor":language==="it"?"Direttore":"Direktor"}</option><option value="Plaće">{language==="en"?"Payroll":language==="de"?"Lohnabrechnung":language==="it"?"Paghe":"Plaće"}</option><option value="Klijent">{language==="en"?"Client":language==="de"?"Kunde":language==="it"?"Cliente":"Klijent"}</option></select></div>
        </div>
      </header>

      <main className={page==="shifts"?"schedulePage":""}>
        {page==="dashboard" && <>
          <section className="hero">
            <div><h1>Pregled</h1><p>{currentUserRole==="Zaštitar"?`Tvoj objekt: ${currentEmployee?.site||"—"}`:currentUserRole==="Voditelj"?`Objekti u tvojoj nadležnosti: ${managerSites.join(", ")||"—"}`:currentUserRole==="Plaće"?"Sažetak podataka potrebnih za obračun plaće.":"Administracija sustava i korisničkih ovlasti."}</p></div>
            <div className="heroWords">SIGURNOST<br/>LJUDI<br/>OBJEKATA<br/>INFORMACIJA</div>
          </section>

          <section className="operationsCenter"><div><span>OPERATIVNI STATUS</span><b>UREDNO</b><small>Nema aktivnog incidenta visoke razine</small></div><div><span>IZVJEŠĆA</span><b>{reports.filter(r=>r.status==="NOVO").length}</b><small>novih za pregled</small></div><div><span>PRIMOPREDAJE</span><b>{handovers.filter(h=>!h.acceptedAt).length}</b><small>čeka potvrdu</small></div><div><span>VAŽNE UPUTE</span><b>{instructions.filter(i=>i.priority==="HITNO"||i.priority==="VAŽNO").length}</b><small>aktivne obavijesti</small></div></section>

          {currentUserRole==="Plaće" ? <section className="stats">
            <Stat icon="👥" label="DJELATNICI" value={employees.filter(e=>e.active!==false).length} sub="aktivni zapisi"/>
            <Stat icon="◷" label="MJESEC" value={payrollMonth} sub="obračunsko razdoblje"/>
            <Stat icon="€" label="OBRAČUN" value="SPREMAN" sub="otvori modul Plaće"/>
            <Stat icon="✓" label="PRISTUP" value="OGRANIČEN" sub="bez operativnih modula"/>
          </section> : currentUserRole==="Administrator" ? <section className="stats">
            <Stat icon="🏢" label="OBJEKTI" value={sites.length} sub="registrirani objekti"/>
            <Stat icon="👥" label="DJELATNICI" value={employees.length} sub="registrirani korisnici"/>
            <Stat icon="⚙" label="POSTAVKE" value="AKTIVNE" sub="administracija sustava"/>
            <Stat icon="✓" label="OVLASTI" value="MINIMALNE" sub="princip najmanjih ovlasti"/>
          </section> : <>
            {(()=>{
              const allowedSites=currentUserRole==="Zaštitar"?[currentEmployee?.site].filter(Boolean):managerSites;
              const scopedEmployees=employees.filter(e=>employeeSites(e).some(s=>allowedSites.includes(s)));
              const scopedVisitors=visitors.filter(v=>allowedSites.includes(v.site));
              const scopedEvents=events.filter(ev=>!ev.site || allowedSites.includes(ev.site));
              return <>
                <section className="stats">
                  <Stat icon="👥" label="NA SMJENI" value={scopedEmployees.filter(e=>e.status==="Na smjeni").length} sub={`${scopedEmployees.length} djelatnika u opsegu`} tone="blue"/>
                  <Stat icon="🏢" label="OBJEKTI" value={allowedSites.length} sub="u tvojem opsegu" tone="green"/>
                  <Stat icon="👥" label="POSJETITELJA UNUTRA" value={scopedVisitors.filter(v=>v.status==="U OBJEKTU").length} sub="samo tvoji objekti" tone="gold"/>
                  <Stat icon="!" label="DOGAĐAJI" value={scopedEvents.length} sub="u tvojem opsegu" tone="red"/>
                </section>
              </>;
            })()}
          </>}
          {(currentUserRole==="Voditelj"||currentUserRole==="Administrator")&&<section className="managerControlPanel"><div className="controlPanelHead"><div><h2>Operativna kontrola</h2><p>Stavke koje traže pregled ili dovršetak.</p></div><span>PROBNI SUSTAV</span></div><div className="controlGrid"><button onClick={()=>setPage("reports")}><b>{newManagerReports}</b><span>Nova izvješća</span><small>čekaju pregled voditelja</small></button><button onClick={()=>setPage("handover")}><b>{pendingHandovers}</b><span>Primopredaje</span><small>čekaju potvrdu preuzimanja</small></button><button onClick={()=>setPage("reports")}><b>{todayMissingShiftReports}</b><span>Izvješća smjene</span><small>nema predanog zapisa za današnji raspored</small></button><button onClick={()=>setPage("instructions")}><b>{instructions.filter(i=>i.active!==false&&i.requireAck).length}</b><span>Aktivne važne upute</span><small>prati potvrde čitanja</small></button></div></section>}
          {currentUserRole==="Zaštitar"&&<section className="guardNoticePanel"><div><b>Moje obveze</b><span>Važne stavke za tvoju smjenu i objekt.</span></div><button onClick={()=>setPage("instructions")}><strong>{unreadImportantInstructions}</strong><span>nepotvrđenih važnih uputa</span></button><button onClick={()=>setPage("handover")}><strong>{handovers.filter(h=>h.toEmployeeId===currentEmployee?.id&&h.status==="ČEKA PREUZIMANJE").length}</strong><span>primopredaja za preuzeti</span></button><button onClick={()=>setPage("reports")}><strong>{incidentRequestsForRole.filter(r=>r.status==="ZAHTJEV IZDAN").length}</strong><span>zahtjeva za izvanredno izvješće</span></button></section>}
        </>}

        {page==="visitors" && <>
          <section className="pageTitle"><h1>{currentUserRole==="Klijent"?"Ulazi i izlazi":"Najave / posjetitelji"}</h1><p>{currentUserRole==="Klijent"?"Klijentski pregled evidencije ulazaka i izlazaka.":"Evidencija dolazaka i odlazaka posjetitelja."}</p></section>
          {currentUserRole==="Klijent"&&<div className="clientAccess"><b>Klijentski pristup</b><span>Možete samo pregledavati ulaske i izlaske svojeg objekta.</span><select value={clientSite} onChange={e=>setClientSite(e.target.value)}>{sites.map(s=><option key={s.id}>{s.name}</option>)}</select></div>}
          <VisitorPanel visitors={currentUserRole==="Klijent"?filtered.filter(v=>v.site===clientSite):filtered} query={query} setQuery={setQuery} siteFilter={siteFilter} setSiteFilter={setSiteFilter}
            sites={sites} setShowVisitor={setShowVisitor} enterVisitor={enterVisitor} exitVisitor={exitVisitor} full readOnly={currentUserRole==="Klijent"}/>
        </>}

        {page==="log" && <SimplePage title="Operativni dnevnik objekta" sub="Jedinstvena kronološka evidencija događaja, izvješća, primopredaja i službenih uputa.">
          <div className="sectionToolbar">
            <div><b>{operationalTimeline.length}</b><span> zapisa u operativnom dnevniku</span></div>
            {(currentUserRole==="Zaštitar"||currentUserRole==="Voditelj"||currentUserRole==="Administrator")&&<button className="goldBtn" onClick={()=>setShowEvent(true)}>+ Novi događaj</button>}
          </div>
          <div className="opsTimeline">{operationalTimeline.map(x=><article className="opsRow" key={x.id}><div className="opsStamp"><b>{x.time||"—"}</b><span>{x.date||"—"}</span></div><div className="opsType">{x.type}</div><div className="opsBody"><b>{x.title}</b><p>{x.detail}</p><span>{x.site} · {x.person||"—"}</span></div><strong>{x.status}</strong></article>)}</div>
        </SimplePage>}

        {page==="sites" && <SimplePage title="Objekti" sub="Centralna evidencija svih objekata i klijenata.">
          <div className="sectionToolbar"><div><b>{sites.length}</b><span> aktivnih objekata</span></div><button className="goldBtn" onClick={()=>setShowSite(true)}>＋ Novi objekt</button></div>
          <div className="cardsGrid">{sites.map(s=><div className="infoCard siteCard" key={s.id}><div className="bigIcon">🏢</div><h3>{s.name}</h3><p>{s.address}<br/>{s.city}</p>{s.client&&<small>Klijent: {s.client}</small>}<b>{s.guards} zaštitara</b>{s.contact&&<small>Kontakt: {s.contact} {s.phone}</small>}{s.mail&&<small>Mail: {s.mail}</small>}{s.camera&&<small>LPR: {s.camera} · {s.gate}</small>}<span className="ok">{s.status}</span><button className="miniBtn" onClick={()=>editSite(s)}>Uredi</button></div>)}</div>
        
</SimplePage>}

        {page==="users" && <>
          <section className="pageTitle usersTitleRow">
            <div><h1>Djelatnici</h1><p>Pregled i upravljanje djelatnicima</p></div>
            <div className="usersActions">
              <div className="searchWrap">⌕<input value={userQuery} onChange={e=>{setUserQuery(e.target.value);setUserPage(1)}} placeholder="Pretraži djelatnike..."/></div>
              <label className="sortControl"><span>Sortiranje</span><select value={userSort} onChange={e=>{setUserSort(e.target.value);setUserPage(1)}}><option value="az">A - Ž (prezime)</option><option value="za">Ž - A (prezime)</option></select></label>
              {currentUserRole!=="Plaće"&&<button className="goldBtn" onClick={()=>setShowUser(true)}>＋ Novi djelatnik</button>}
            </div>
          </section>

          <section className="employeeStats">
            <div><span>UKUPNO</span><b>{filteredUsers.length}</b></div>
            <div><span>AKTIVNI</span><b>{filteredUsers.filter(e=>e.active!==false).length}</b></div>
            <div><span>NA SMJENI</span><b>{filteredUsers.filter(isEmployeeOnShiftNow).length}</b></div>
            <div><span>DOSTUPNI ZA ZAMJENU</span><b>{filteredUsers.filter(e=>e.replacementAvailable===true && e.active!==false).length}</b></div>
          </section>

          <div className="employeeFilters">
            <select value={userSiteFilter} onChange={e=>{setUserSiteFilter(e.target.value);setUserPage(1)}}><option>Svi objekti</option>{sites.map(s=><option key={s.id}>{s.name}</option>)}</select>
            <select value={userStatusFilter} onChange={e=>{setUserStatusFilter(e.target.value);setUserPage(1)}}><option>Svi statusi</option><option>Aktivni</option><option>Neaktivni</option><option>Na smjeni</option><option>Slobodan</option><option>Kašnjenje</option><option>Bolovanje</option><option>Godišnji odmor</option></select>
            <label className="replacementFilter"><input type="checkbox" checked={userReplacementOnly} onChange={e=>{setUserReplacementOnly(e.target.checked);setUserPage(1)}}/> Samo dostupni za zamjene</label>
            <span className="resultCount">{filteredUsers.length} pronađenih</span>
          </div>

          <div className="permissionNote">Kontakt podaci su vidljivi voditelju/administratoru radi operativnog kontakta. Zaštitari u produkcijskoj verziji neće imati pristup popisu svih djelatnika firme.</div>

          <section className="simplePanel employeeTableWrap">
            <div className="employeeTable employeeHead">
              <span>DJELATNIK / ID</span><span>ULOGA</span><span>OBJEKT(I)</span><span>KONTAKT</span><span>LICENCA</span><span>STATUS</span><span>ZAHTJEVI</span><span>RADNJE</span>
            </div>
            {pagedUsers.map(e=><div className="employeeTable employeeRow" key={e.id}>
              <div className="employeeNameCell"><b>{displayEmployeeName(e.name)}</b><small>SP-{String(e.id).padStart(5,"0")} · {e.cardNumber||"bez iskaznice"}</small></div>
              <span>{e.role}</span>
              <div className="employeeSitesCell"><b>{e.site}</b><small>{employeeSites(e).filter(x=>x!==e.site).join(" · ")||"—"}</small></div>
              <div className="employeeContact"><a href={`tel:${e.phone}`}>{e.phone||"—"}</a><a href={`mailto:${e.email}`}>{e.email||"—"}</a></div>
              <div><b>{e.license||"—"}</b><small>{e.licenseExpiry||"—"}</small></div>
              <span className={`userStatus ${getEmployeeOperationalStatus(e)==="Na smjeni"?"working":"free"}`}>{getEmployeeOperationalStatus(e)}</span>
              <div className="requestCell"><span>{shiftRequests.filter(r=>r.employee===e.name&&r.status==="NA ČEKANJU").length?`${shiftRequests.filter(r=>r.employee===e.name&&r.status==="NA ČEKANJU").length} na čekanju`:"— Nije dodijeljen"}</span><button className={`replacementBadge ${e.replacementAvailable?"yes":"no"}`} onClick={()=>toggleReplacement(e)} disabled={currentUserRole!=="Voditelj"&&currentUserRole!=="Administrator"}>{e.replacementAvailable?"✓ Dostupan":"Dodijeli"}</button></div>
              <div className="employeeActions">{currentUserRole!=="Plaće"&&<button className="miniBtn" onClick={()=>editEmployee(e)}>Uredi</button>}{currentUserRole==="Voditelj"&&<button className="tinyGhost" onClick={()=>addPayrollSimulation(e)}>Simulacija</button>}{currentUserRole==="Administrator"&&<button className="tinyGhost" onClick={()=>toggleEmployeeActive(e)}>{e.active===false?"Aktiviraj":"Deaktiviraj"}</button>}</div>
            </div>)}
            {pagedUsers.length===0 && <div className="emptyEmployees">Nema djelatnika koji odgovaraju odabranim filtrima.</div>}
          </section>

          <div className="paginationBar">
            <button disabled={userPage<=1} onClick={()=>setUserPage(p=>Math.max(1,p-1))}>‹ Prethodna</button>
            <span>Prikazano {(Math.min(userPage,userPages)-1)*USERS_PER_PAGE+1} – {Math.min(filteredUsers.length,Math.min(userPage,userPages)*USERS_PER_PAGE)} od {filteredUsers.length} djelatnika</span>
            <button disabled={userPage>=userPages} onClick={()=>setUserPage(p=>Math.min(userPages,p+1))}>Sljedeća ›</button>
          </div>
        </>}

        {page==="shifts" && <>
          <section className="pageTitle usersTitleRow">
            <div><h1>Mjesečni raspored</h1><p>Raspored rada djelatnika po danima u mjesecu.</p></div>
            <div className="usersActions scheduleActions">{canManage?<select className="sitePick" value={scheduleSite} onChange={e=>setScheduleSite(e.target.value)}>{sites.map(s=><option key={s.id}>{s.name}</option>)}</select>:<span className="lockedSite">Objekt: {visibleScheduleSite}</span>}<input className="monthPick" type="month" value={scheduleMonth} onChange={e=>setScheduleMonth(e.target.value)}/>{canManage&&<button className="ghostBtn" onClick={printSchedulePdf}>PDF / Ispis</button>}{canManage&&<button className="goldBtn" onClick={emailSchedule}>E-mail djelatnicima</button>}</div>
          </section>
          {canManage&&<div className={`deadlineBox ${scheduleBuildOpen?"open":"locked"}`}>
            <b>{scheduleBuildOpen?"NOVI RASPORED JE OTVOREN":"NOVI RASPORED OD 20. U MJESECU"}</b>
            <span>{scheduleBuildOpen?`Možeš složiti raspored za ${nextMonthKey()}. Odobreni SL / I / II i GO automatski će se primijeniti.`:"Do 19. u mjesecu prikupljaju se i odobravaju zahtjevi. Od 20. se otvara izrada rasporeda za sljedeći mjesec."}</span>
            <button className="goldBtn" disabled={!scheduleBuildOpen} onClick={generateNextMonthSchedule}>Složi raspored za sljedeći mjesec</button>
          </div>}
          <div className="permissionNote scheduleNote">Raspored je odvojen po objektu. Voditelj/administrator bira objekt i uređuje samo djelatnike dodijeljene toj lokaciji. Zaštitar vidi samo raspored svojeg objekta. PDF se može spremiti/ispisati, a e-mail gumb priprema poruku poslovnim adresama djelatnika tog objekta; potpuno automatsko slanje s PDF privitkom dolazi s OAuth/SSO mail integracijom. Oznake: ${isBankSite(visibleScheduleSite)?"I = 08:00–20:00, SL = slobodan dan (izmjena I / SL)":"I = 07:00–19:00, II = 19:00–07:00, SL = slobodan"}, GO = godišnji odmor, BO = bolovanje. Sve oznake smjena prikazane su istom bojom; nedjelje i blagdani ostaju označeni crvenim danom.</div>
          <section className="simplePanel scheduleWrap">
            <div className="scheduleGrid scheduleHead" style={scheduleGridStyle}><b>Djelatnik</b>{Array.from({length:new Date(Number(scheduleMonth.slice(0,4)),Number(scheduleMonth.slice(5,7)),0).getDate()},(_,i)=>{
              const day=String(i+1).padStart(2,"0"), ds=`${scheduleMonth}-${day}`, prem=isSundayOrHoliday(ds);
              return <b key={i} className={prem.isPremium?"premiumDay":""}>{i+1}</b>
            })}</div>
            {employeesForSchedule.map(emp=><div className="scheduleGrid scheduleRow" style={scheduleGridStyle} key={emp.id}>
              <div><strong>{displayEmployeeName(emp.name)}</strong><small>{emp.site}</small></div>
              {Array.from({length:new Date(Number(scheduleMonth.slice(0,4)),Number(scheduleMonth.slice(5,7)),0).getDate()},(_,i)=>{
                const day=String(i+1).padStart(2,"0");
                const rec=canonicalWorkHours.find(w=>(w.employeeId===emp.id || w.employee===emp.name) && w.date===`${scheduleMonth}-${day}`);
                return <button key={i} className={`shiftCell ${rec?.shift||""}`} onClick={()=>canManage&&cycleSchedule(emp,`${scheduleMonth}-${day}`)} disabled={!canManage} title={canManage?"Klikni za promjenu smjene":"Pregled rasporeda"}>{rec?.shift||"·"}</button>
              })}
            </div>)}
          </section>
          <div className="scheduleLegend">
            <b>Legenda smjena:</b>
            <span><strong>I</strong> = {isBankSite(visibleScheduleSite)?"08:00–20:00":"07:00–19:00"}</span>
            {!isBankSite(visibleScheduleSite)&&<span><strong>II</strong> = 19:00–07:00</span>}
            <span><strong>SL</strong> = slobodan dan</span>
            <span><strong>GO</strong> = godišnji odmor</span>
            <span><strong>BO</strong> = bolovanje</span>
            <span className="legendNote">{isBankSite(visibleScheduleSite)?"Banke: radno vrijeme 08:00–20:00, dva djelatnika izmjenjuju I / SL svaki dan.":"24/7 objekti: osnovni ciklus I → II → SL → SL, s pomakom među 4 djelatnika radi neprekidne pokrivenosti."}</span>
          </div>
        </>}


        {page==="workorder" && <SimplePage title="Radni nalozi" sub="Pregled radnih naloga po prezimenu i izrada službenog dokumenta za ispis.">
          {currentUserRole==="Zaštitar" ? (
            <section className="simplePanel workOrderCard">
              <div className="workOrderTitle"><div><span>RADNI NALOG</span><h2>{currentEmployee?.workOrderNo||"—"}</h2></div><button className="goldBtn" onClick={()=>printWorkOrder(currentEmployee)}>PDF / Ispis</button></div>
              <div className="workOrderGrid">
                <div><span>Prezime i ime</span><b>{displayEmployeeName(currentEmployee?.name||"—")}</b></div>
                <div><span>Broj iskaznice</span><b>{currentEmployee?.cardNumber||"—"}</b></div>
                <div><span>Licenca</span><b>{currentEmployee?.license||"—"}</b></div>
                <div><span>Radno mjesto</span><b>{currentEmployee?.workplace||currentEmployee?.role||"—"}</b></div>
                <div className="wide"><span>Objekt</span><b>{currentEmployee?.workLocation||currentEmployee?.site||"—"}</b></div>
                <div className="wide"><span>Ovlasti</span><b>{currentEmployee?.authorities||"—"}</b></div>
                <div className="wide"><span>Radno vrijeme</span><b>{workTimeLabel(currentEmployee?.workLocation||currentEmployee?.site||"")}</b></div>
              </div>
            </section>
          ) : (
            <section className="simplePanel workOrdersTableWrap">
              <div className="workOrdersTable workOrdersHead">
                <span>#</span><span>PREZIME</span><span>IME</span><span>BROJ RADNOG NALOGA</span><span>OBJEKT</span><span>RADNO MJESTO</span><span>PDF</span>
              </div>
              {workOrderEmployees.map((e,index)=>{
                const parts=(e.name||"").trim().split(/\s+/); const firstName=parts.slice(0,-1).join(" ")||parts[0]||"—"; const lastName=parts.at(-1)||"—";
                return <div className="workOrdersTable workOrdersRow" key={e.id}>
                  <span className="rowNo">{index+1}</span>
                  <span><b>{lastName}</b></span>
                  <span><b>{firstName}</b></span>
                  <span><strong>{e.workOrderNo||"—"}</strong><small>{e.cardNumber||"bez iskaznice"}</small></span>
                  <span><b>{e.workLocation||e.site||"—"}</b></span>
                  <span>{e.workplace||e.role||"—"}</span>
                  <span><button className="miniBtn pdfWorkBtn" onClick={()=>printWorkOrder(e)}>PDF</button></span>
                </div>
              })}
            </section>
          )}
        </SimplePage>}

        {page==="hours" && <>
          <section className="pageTitle usersTitleRow">
            <div><h1>Evidencija sati</h1><div className="fundInfo"><b>Automatski fond sati</b><span>Fond se računa po mjesecu prema 40-satnom radnom tjednu, pon–pet, uz hrvatske blagdane. Prekovremeni = odrađeni sati iznad fonda. Noćni rad 22–06, nedjelje i blagdani označavaju dio već odrađenih sati i NE pribrajaju se ponovno ukupnim satima.</span></div><p>Radni sati za kontrolu i pripremu obračuna plaće.</p></div>
            {currentUserRole==="Voditelj"&&<button className="goldBtn" onClick={()=>setShowHours(true)}>＋ Upis smjene</button>}
          </section>
          <div className="permissionNote">{currentUserRole==="Zaštitar"?"Prikazani su isključivo tvoji evidentirani sati.":"Voditelj vidi sate svih djelatnika radi izrade i kontrole rasporeda."}</div>
          <section className="hoursSummary">
            {employeesForHours.map(emp=>{
              const rows=canonicalWorkHours.filter(w=>(w.employeeId===emp.id || w.employee===emp.name) && w.date.startsWith(scheduleMonth));
              const totals=rows.reduce((a,w)=>{
                const seg=shiftSegments(w.shift,new Date(`${w.date}T00:00:00`));
                a.worked+=seg.total;
                a.goPaid+=w.shift==="GO"?Number(w.paidHours||8):0;
                a.night+=seg.night; a.sun+=seg.sunday; a.hol+=seg.holiday; return a;
              },{worked:0,goPaid:0,night:0,sun:0,hol:0});
              const [yy,mm]=scheduleMonth.split("-").map(Number);
              const fund=monthlyWorkFund(yy,mm-1,40).hours;
              const safeWorked=totals.worked;
              const overtime=Math.max(0,safeWorked-fund);
              return <div key={emp.id}><span>{emp.name}</span><b>{safeWorked} h / fond {fund} h</b><small>Prekovremeni: {overtime} h · GO (plaćeno): {totals.goPaid} h · Noćni 22–06: {totals.night} h · Nedjelja: {totals.sun} h · Blagdan: {totals.hol} h</small></div>
            })}
          </section>
          <section className="simplePanel">
            <div className="hoursTable">
              <div className="hoursHead"><span>Djelatnik</span><span>Datum</span><span>Objekt</span><span>Smjena</span><span>Vrijeme</span><span>Sati</span><span>Posebno</span></div>
              {workHoursForRole.filter(w=>w.date.startsWith(scheduleMonth)).sort((a,b)=>a.date.localeCompare(b.date)).map(w=><div className="hoursRow" key={w.id}>
                <b>{w.employee}</b><span>{w.date}<small className="weekdayLabel">{["Ned","Pon","Uto","Sri","Čet","Pet","Sub"][new Date(`${w.date}T12:00:00`).getDay()]}</small></span><span>{w.site}</span><span>{w.shift}</span><span>{w.start} – {w.end}</span><b>{w.hours} h</b><span className={(shiftSegments(w.shift,new Date(`${w.date}T00:00:00`)).sunday||shiftSegments(w.shift,new Date(`${w.date}T00:00:00`)).holiday)?"premiumText":""}>{(()=>{const s=shiftSegments(w.shift,new Date(`${w.date}T00:00:00`)); return `Noć ${s.night}h · Ned ${s.sunday}h · Blag ${s.holiday}h`;})()}</span>
              </div>)}
            </div>
          </section>
        </>}

        {page==="patrols" && <>
          <section className="pageTitle usersTitleRow">
            <div><h1>Obilasci</h1><p>Kontrola obilazaka djelatnika i Kerber evidencija.</p></div>
            <div className="usersActions">
              <div className="searchWrap">⌕<input value={patrolQuery} onChange={e=>setPatrolQuery(e.target.value)} placeholder="Pretraži djelatnika, objekt, status..."/></div>
              <button className="ghostBtn">Uvoz iz Kerbera</button>
              <button className="goldBtn" onClick={()=>setShowPatrol(true)}>＋ Novi obilazak</button>
            </div>
          </section>
          <section className="patrolStats">
            <div><span>UKUPNO OBILAZAKA</span><b>{patrolsForRole.length}</b></div>
            <div><span>U REDU</span><b>{patrolsForRole.filter(p=>p.status==="U REDU").length}</b></div>
            <div><span>NEPOTPUNI</span><b>{patrolsForRole.filter(p=>p.status!=="U REDU").length}</b></div>
            <div><span>PROSJEČNO TRAJANJE</span><b>{patrolsForRole.length?Math.round(patrolsForRole.reduce((a,p)=>a+p.duration,0)/patrolsForRole.length):0} min</b></div>
          </section>
          <section className="simplePanel">
            <div className="patrolTable">
              <div className="patrolHead">
                <span>Djelatnik</span><span>Iskaznica</span><span>Objekt</span><span>Datum</span><span>Početak</span><span>Kraj</span><span>Trajanje</span><span>Točke</span><span>Status</span><span>Izvor</span>
              </div>
              {filteredPatrols.filter(p=>patrolsForRole.some(x=>x.id===p.id)).map(p=><div className="patrolRow" key={p.id}>
                <b>{p.employee}</b><span>{p.cardNumber}</span><span>{p.site}</span><span>{p.date}</span><span>{p.start}</span><span>{p.end}</span><span>{p.duration} min</span>
                <span>{p.checkpointsDone}/{p.checkpointsTotal}{p.missed>0?` (${p.missed} preskočeno)`:""}</span>
                <span className={`patrolStatus ${p.status==="U REDU"?"good":"bad"}`}>{p.status}</span><span>{p.source}</span>
              </div>)}
            </div>
          </section>
        </>}


        {page==="access" && <>
          <section className="pageTitle usersTitleRow">
            <div><h1>Kontrola pristupa</h1><p>LPR rampa i evidencija kartičnih ulazaka/izlazaka djelatnika.</p></div>
            <select className="monthPick" value={accessSite} onChange={e=>setAccessSite(e.target.value)}>{sites.map(s=><option key={s.id}>{s.name}</option>)}</select>
          </section>
          <div className="securityGrid">
            <section className="simplePanel securityCard">
              <span className="eyebrow">LPR / RAMPA</span><h3>Čitanje registracije</h3>
              <p>Rampa se u ovom prototipu označava kao otvorena samo ako je djelatnik aktivan, ima dozvolu za vozilo i pripada odabranom objektu.</p>
              <div className="inlineAction"><input value={lprPlate} onChange={e=>setLprPlate(e.target.value)} placeholder="npr. ZG 1001 AA"/><button className="goldBtn" onClick={simulateLpr}>Simuliraj kameru</button></div>
            </section>
            <section className="simplePanel securityCard">
              <span className="eyebrow">KARTIČNI PRISTUP</span><h3>Ulaz / izlaz djelatnika</h3>
              <p>Svako očitanje kartice stvara zapis s djelatnikom, objektom, datumom, vremenom i smjerom prolaza.</p>
              <div className="inlineAction"><input value={cardScan} onChange={e=>setCardScan(e.target.value)} placeholder="npr. ISK-001"/><button className="goldBtn" onClick={simulateCard}>Očitaj karticu</button></div>
            </section>
          </div>
          <section className="simplePanel">
            <div className="accessHead"><span>Vrsta</span><span>Djelatnik</span><span>Identifikator</span><span>Objekt</span><span>Smjer</span><span>Vrijeme</span><span>Rezultat</span></div>
            {accessEvents.filter(x=>x.site===accessSite).map(x=><div className="accessRow" key={x.id}>
              <b>{x.type}</b><span>{x.employee}</span><span>{x.plate||x.card}</span><span>{x.site}</span><span>{x.direction}</span><span>{x.date} {x.time}</span><strong className={x.result.includes("ODBIJEN")?"badText":"goodText"}>{x.result}</strong>
            </div>)}
          </section>
        </>}

        {page==="messages" && <>
          <section className="pageTitle"><h1>Komunikacija</h1><p>Dvosmjerna operativna komunikacija djelatnik ↔ voditelj i voditelj → objekt.</p></section>
          <div className="permissionNote">HITNO poruke dobivaju poseban zapis. Voditelj ih može odmah ispisati ili spremiti kao PDF za papirnatu evidenciju. Stvarni CDS i dalje zahtijeva odobren protokol/API integraciju.</div>
          <div className="communicationColumns">
            <section className="simplePanel commCompose">
              <h3>Djelatnik → voditelj</h3>
              <div className="formGrid compactForm">
                <label>Djelatnik<select value={loggedEmployee} onChange={e=>setLoggedEmployee(e.target.value)}>{employees.filter(e=>e.active!==false).map(e=><option key={e.id}>{e.name}</option>)}</select></label>
                <label>Prioritet<select value={messagePriority} onChange={e=>setMessagePriority(e.target.value)}><option>NORMALNO</option><option>VISOKO</option><option>HITNO</option></select></label>
                <label className="wide">Poruka<textarea value={messageText} onChange={e=>setMessageText(e.target.value)} placeholder="Opiši situaciju što preciznije..."/></label>
              </div>
              <button className="goldBtn" onClick={sendMessage}>Pošalji voditelju</button>
            </section>
            {canManage && <section className="simplePanel commCompose">
              <h3>Voditelj → objekt</h3>
              <div className="formGrid compactForm">
                <label>Objekt<select value={managerMessageSite} onChange={e=>setManagerMessageSite(e.target.value)}>{sites.map(s=><option key={s.id}>{s.name}</option>)}</select></label>
                <label>Prioritet<select value={managerMessagePriority} onChange={e=>setManagerMessagePriority(e.target.value)}><option>NORMALNO</option><option>VISOKO</option><option>HITNO</option></select></label>
                <label className="wide">Poruka objektu<textarea value={managerMessageText} onChange={e=>setManagerMessageText(e.target.value)} placeholder="Poruka svim djelatnicima odabranog objekta..."/></label>
              </div>
              <button className="goldBtn" onClick={sendManagerMessage}>Pošalji na objekt</button>
            </section>}
          </div>
          <section className="messageList">{messages.map(m=><article className={`messageCard ${m.priority}`} key={m.id}><div><b>{m.from}</b><span>{m.site} · {m.date||today} {m.time} · {m.direction||"PREMA VODITELJU"}</span></div><strong>{m.priority}</strong><p>{m.text}</p><small>{m.ai}</small><div className="messageFooter"><span>{m.status}</span>{canManage && m.priority==="HITNO" && <button className="miniBtn" onClick={()=>printEmergencyPdf(m)}>PDF / Ispis evidencije</button>}</div></article>)}</section>
        </>}
        {page==="requests" && <>
          <section className="pageTitle"><h1>Zahtjevi za raspored</h1><p>Djelatnik može poslati želju za pojedinačnu smjenu ili zaseban zahtjev za godišnji odmor.</p></section>
          <div className={`deadlineBox ${canRequestNextMonth?"open":"locked"}`}>
            <b>{canRequestNextMonth?"ZAHTJEVI OTVORENI":"ZAHTJEVI ZAKLJUČANI"}</b>
            <span>{canRequestNextMonth?"Zahtjev je moguće poslati zaključno do 17. u mjesecu. Voditelj ga pregledava prije izrade novog rasporeda.":"Nakon 17. u mjesecu zahtjevi se više ne mogu slati za idući raspored."}</span>
          </div>
          {currentUserRole==="Zaštitar"&&<div className="privacyPanel"><h3>Moj godišnji odmor</h3><p>Preostalo: <b>{annualLeaveRemaining(currentEmployee||{})} dana</b></p></div>}
          {currentUserRole==="Zaštitar"&&<section className="simplePanel requestPanel">
            <div className="formGrid compactForm">
              <label>Djelatnik{currentUserRole==="Zaštitar"?<input value={currentEmployee?.name||"—"} disabled/>:<input value="Zahtjeve šalju djelatnici" disabled/>}</label>
              <label>Želja<select value={requestType} onChange={e=>setRequestType(e.target.value)}><option>SL</option><option>I</option><option>II</option></select></label>
              <label>Datum<input type="date" value={requestDate} onChange={e=>setRequestDate(e.target.value)}/></label>
              <label>Napomena<input value={requestNote} onChange={e=>setRequestNote(e.target.value)} placeholder="neobavezno"/></label>
            </div>
            <button className="goldBtn" disabled={!canRequestNextMonth} onClick={addShiftRequest}>Pošalji zahtjev</button>
          </section>}
          {currentUserRole==="Zaštitar"&&<section className="simplePanel requestPanel">
            <h3>Zahtjev za godišnji odmor</h3>
            <p className="muted">Nakon odobrenja u rasporedu ostaje oznaka GO. Za obračun plaće svaki odobreni dan GO evidentira se kao 8 plaćenih sati.</p>
            <div className="formGrid compactForm">
              <label>Djelatnik<input value={currentEmployee?.name||"—"} disabled/></label>
              <label>Datum od<input type="date" value={leaveFrom} onChange={e=>setLeaveFrom(e.target.value)}/></label>
              <label>Datum do<input type="date" value={leaveTo} onChange={e=>setLeaveTo(e.target.value)}/></label>
              <label>Napomena<input value={leaveNote} onChange={e=>setLeaveNote(e.target.value)} placeholder="neobavezno"/></label>
            </div>
            <div className="requestActions"><button className="goldBtn" onClick={addLeaveRequest}>Pošalji zahtjev za GO</button><span className="muted">Trajanje: <b>{leaveDates(leaveFrom,leaveTo).length}</b> dana</span></div>
          </section>}
          <section className="simplePanel">
            <div className="requestHead requestHeadManager"><span>Djelatnik</span><span>Objekt</span><span>Datum</span><span>Zahtjev</span><span>Napomena</span><span>Status / odluka</span></div>
            {visibleRequests.map(r=><div className="requestRow requestRowManager" key={r.id}><b>{r.employee}</b><span>{r.site}</span><span>{r.dateWanted}</span><strong>{r.request}</strong><span>{r.note||"—"}</span><span>{canManage && r.status==="NA ČEKANJU"?<span className="decisionBtns"><button className="approveBtn" onClick={()=>decideShiftRequest(r.id,"ODOBRENO")}>Odobri</button><button className="rejectBtn" onClick={()=>decideShiftRequest(r.id,"ODBIJENO")}>Odbij</button></span>:<b className={r.status==="ODOBRENO"?"goodText":r.status==="ODBIJENO"?"badText":""}>{r.status}</b>}</span></div>)}
          </section>
          <section className="simplePanel">
            <h3>Zahtjevi za godišnji odmor</h3>
            <div className="requestHead requestHeadManager"><span>Djelatnik</span><span>Objekt</span><span>Razdoblje</span><span>GO</span><span>Napomena</span><span>Status / odluka</span></div>
            {visibleLeaveRequests.length===0?<p className="muted">Nema zahtjeva za godišnji odmor.</p>:visibleLeaveRequests.map(r=><div className="requestRow requestRowManager" key={r.id}><b>{r.employee}</b><span>{r.site}</span><span>{r.from} – {r.to}</span><strong>{r.days} d. / {r.days*8} h</strong><span>{r.note||"—"}</span><span>{canManage && r.status==="NA ČEKANJU"?<span className="decisionBtns"><button className="approveBtn" onClick={()=>decideLeaveRequest(r.id,"ODOBRENO")}>Odobri</button><button className="rejectBtn" onClick={()=>decideLeaveRequest(r.id,"ODBIJENO")}>Odbij</button></span>:<b className={r.status==="ODOBRENO"?"goodText":r.status==="ODBIJENO"?"badText":""}>{r.status}</b>}</span></div>)}
          </section>
        </>}

        {page==="mail" && <>
          <section className="pageTitle"><h1>Pošta objekta</h1><p>Službeni račun e-pošte vezan isključivo uz pojedini objekt.</p></section>
          <div className="permissionNote">Lozinke se neće spremati u SENTRYPRO. Produkcijska verzija treba OAuth/SSO prema stvarnom Microsoft 365 ili Google Workspace računu i server-side provjeru pripadnosti objektu.</div>
          <div className="cardsGrid">{(currentUserRole==="Zaštitar"?sites.filter(s=>s.name===currentEmployee?.site):sites).map(s=><div className="infoCard siteCard" key={s.id}><div className="bigIcon">@</div><h3>{s.name}</h3><p>{s.mail||"Mail nije postavljen"}</p><small>Izolirani spremnik objekta</small><button className="ghostBtn" disabled>Sigurna prijava — nakon integracije</button></div>)}</div>
        </>}


        {page==="handover" && <SimplePage title="Primopredaja smjene" sub="Službena predaja ključeva, opreme, otvorenih događaja i uputa sljedećoj smjeni.">
          {["Zaštitar","Voditelj","Administrator"].includes(currentUserRole)&&<section className="simplePanel handoverEditor"><div className="sectionHead"><div><h3>Nova primopredaja</h3><p>Upišite stvarno stanje smjene. Djelatnik koji preuzima zatim potvrđuje preuzimanje.</p></div><span className="docTag">PS</span></div>{currentUserRole!=="Zaštitar"&&<div className="demoHandoverNotice">Probni unos: voditelj ili administrator može odabrati djelatnika koji predaje radi testiranja procesa. <b>Potvrdu preuzimanja ne radi voditelj</b> — potvrđuje je isključivo prijavljeni kolega naveden kao preuzimatelj.</div>}{<div className="demoHandoverNotice"><b>Prijavljeni djelatnik (demo)</b><select value={loggedEmployee} onChange={e=>setLoggedEmployee(e.target.value)}>{employees.filter(e=>e.active!==false).map(e=><option key={e.id}>{e.name}</option>)}</select><span>Potvrdu može napraviti bilo koji korisnik ako je upravo on naveden kao preuzimatelj.</span></div>}<div className="structuredForm handoverIdentity">{currentUserRole!=="Zaštitar"&&<label>Djelatnik koji predaje *<select value={handoverFromEmployeeId} onChange={e=>{setHandoverFromEmployeeId(e.target.value);setHandoverToEmployeeId("");}}><option value="">Odaberi djelatnika...</option>{employees.filter(e=>e.active!==false&&e.role==="Zaštitar").map(e=><option key={e.id} value={e.id}>{e.name} · {e.site}</option>)}</select></label>}<label>Djelatnik koji preuzima *<select value={handoverToEmployeeId} onChange={e=>setHandoverToEmployeeId(e.target.value)}><option value="">Odaberi djelatnika...</option>{employees.filter(e=>{const from=currentUserRole==="Zaštitar"?currentEmployee:employees.find(x=>x.id===handoverFromEmployeeId);return from&&e.active!==false&&e.id!==from.id&&e.site===from.site;}).map(e=><option key={e.id} value={e.id}>{e.name}</option>)}</select></label></div><div className="autoMeta">{(()=>{const from=currentUserRole==="Zaštitar"?currentEmployee:employees.find(e=>e.id===handoverFromEmployeeId);return <><span><small>OBJEKT</small><b>{from?.site||"—"}</b></span><span><small>PREDAJE</small><b>{from?.name||"—"}</b></span><span><small>DATUM</small><b>{todayISO}</b></span><span><small>SMJENA</small><b>{from?(employeeScheduleRecord(from,todayISO)?.shift||from.shift||"—"):"—"}</b></span></>;})()}</div><div className="structuredForm"><label>Ključevi / kartice *<textarea rows="3" value={handoverKeys} onChange={e=>setHandoverKeys(e.target.value)} placeholder="Upišite predane ključeve, kartice i evidencijske komplete..."/></label><label>Službena oprema *<textarea rows="3" value={handoverEquipment} onChange={e=>setHandoverEquipment(e.target.value)} placeholder="Upišite radio-stanicu, svjetiljku, telefon i ostalu opremu..."/></label>
<div className="wide handoverWeaponBox">
  <div className="weaponBoxHead"><div><b>Službeno naoružanje / streljivo</b><small>Evidencija stanja i količine pri primopredaji — bez operativnih uputa.</small></div><label className="checkLabel"><input type="checkbox" checked={handoverWeaponEnabled} onChange={e=>setHandoverWeaponEnabled(e.target.checked)}/> Ima zaduženo oružje / streljivo</label></div>
  {handoverWeaponEnabled&&<div className="weaponGrid">
    <label>Vrsta<input value={handoverWeaponType} onChange={e=>setHandoverWeaponType(e.target.value)} /></label>
    <label>Serijski broj<input type="text" inputMode="text" autoComplete="off" spellCheck="false" maxLength="64" value={handoverWeaponSerial} onChange={e=>setHandoverWeaponSerial(e.target.value)} placeholder="Upišite serijski broj" aria-label="Serijski broj službenog naoružanja" /></label>
    <label>Stanje<select value={handoverWeaponCondition} onChange={e=>setHandoverWeaponCondition(e.target.value)}><option>Ispravno</option><option>Oštećeno — izdvojiti i prijaviti</option><option>Neispravno — izdvojeno</option></select></label>
    <label>Broj metaka pri predaji<input type="number" min="0" value={handoverAmmoIssued} onChange={e=>setHandoverAmmoIssued(e.target.value)} /></label>
    <label>Broj metaka pri preuzimanju<div className="handoverPendingField">Upisuje preuzimatelj prilikom potvrde</div></label>
  </div>}
</div><label>Otvoreni događaji / zadaće<textarea rows="3" value={handoverOpenItems} onChange={e=>setHandoverOpenItems(e.target.value)} placeholder="Upišite otvorene događaje, kvarove, čekanje servisa ili posebne kontrole..."/></label><label>Upute za sljedeću smjenu<textarea rows="3" value={handoverInstructions} onChange={e=>setHandoverInstructions(e.target.value)} placeholder="Upišite sve važne informacije koje sljedeća smjena mora znati..."/></label><label className="wide">Stanje pri predaji *<textarea rows="4" value={handoverCondition} onChange={e=>setHandoverCondition(e.target.value)} placeholder="Opišite stanje objekta, opreme i evidencija u trenutku predaje..."/></label></div><div className="reportActions"><span>Sadržaj primopredaje upisuje djelatnik; nakon predaje zapis ostaje evidentiran u audit tragu.</span><button type="button" className="goldBtn handoverSubmitBtn" onClick={(e)=>{e.preventDefault();submitHandover();}}>Predaj smjenu</button></div></section>}
          <section className="simplePanel"><div className="sectionHead"><div><h3>Evidencija primopredaja</h3><p>Status PREUZETO znači da je preuzimatelj potvrdio primitak predanih stavki.</p></div></div><div className="handoverList">{relevantHandovers.length===0?<div className="emptyReportState"><b>Nema primopredaja za prikaz.</b></div>:relevantHandovers.map(h=><article className={`handoverCard ${h.status==="ČEKA PREUZIMANJE"?"waiting":""}`} key={h.id}><div className="handoverTop"><div><span>{h.handoverNo}</span><b>{h.fromEmployee} → {h.toEmployee}</b><small>{h.site} · {h.date} {h.time}</small></div><strong>{h.status}</strong></div><div className="handoverGrid"><div><small>Ključevi / kartice</small><p>{h.keys}</p></div><div><small>Oprema</small><p>{h.equipment}</p></div>{h.weapon?.enabled&&<div className="weaponSummary"><small>Službeno naoružanje / streljivo</small><p><b>{h.weapon.type}</b> · ser. {h.weapon.serial} · stanje: {h.weapon.condition}<br/>Streljivo: {h.weapon.ammoIssued} pri predaji → {h.weapon.ammoReturned} pri preuzimanju · razlika {h.weapon.ammoDifference}</p></div>}<div><small>Otvorene stavke</small><p>{h.openItems}</p></div><div><small>Uputa sljedećoj smjeni</small><p>{h.instructions}</p></div><div className="wide"><small>Stanje pri predaji</small><p>{h.condition}</p></div></div>{h.status==="ČEKA PREUZIMANJE"&&(((h.toEmployeeId&&h.toEmployeeId===currentEmployee?.id)||(!h.toEmployeeId&&h.toEmployee===currentEmployee?.name)))&&<div className="reportActions handoverAcceptActions"><span>Potvrdom se evidentira stvarni preuzimatelj i vrijeme preuzimanja.</span>{h.weapon?.enabled&&<label className="ammoConfirmField">Broj metaka pri preuzimanju<input type="number" min="0" step="1" inputMode="numeric" value={handoverAcceptAmmo[h.id]??(h.weapon.ammoIssued??"")} onChange={e=>setHandoverAcceptAmmo(prev=>({...prev,[h.id]:e.target.value}))}/></label>}<button type="button" className="goldBtn" onClick={(e)=>{e.preventDefault();e.stopPropagation();acceptHandover(h.id);}}>Potvrdi preuzimanje</button></div>}{h.acceptedAt&&<div className="acceptedLine">Preuzeto: {new Date(h.acceptedAt).toLocaleString("hr-HR")} · {h.acceptedBy||h.toEmployee}</div>}</article>)}</div></section>
        </SimplePage>}

        {page==="instructions" && <SimplePage title="Obavijesti i službene upute" sub="Važne operativne upute s evidencijom tko ih je pročitao i kada.">
          {(currentUserRole==="Voditelj"||currentUserRole==="Administrator")&&<section className="simplePanel instructionEditor"><div className="sectionHead"><div><h3>Nova službena uputa</h3><p>Za važne upute uključite obveznu potvrdu čitanja.</p></div><span className="docTag">UPUTA</span></div><div className="structuredForm"><label>Objekt<select value={instructionSite} onChange={e=>setInstructionSite(e.target.value)}><option>Svi objekti</option>{sites.map(s=><option key={s.id}>{s.name}</option>)}</select></label><label>Prioritet<select value={instructionPriority} onChange={e=>setInstructionPriority(e.target.value)}><option>VAŽNO</option><option>HITNO</option><option>INFORMATIVNO</option></select></label><label className="wide">Naslov *<input value={instructionTitle} onChange={e=>setInstructionTitle(e.target.value)} placeholder="Kratak i jasan naziv upute"/></label><label className="wide">Sadržaj službene upute *<textarea rows="5" value={instructionText} onChange={e=>setInstructionText(e.target.value)} placeholder="Navedite što djelatnik mora znati ili poduzeti."/></label></div><label className="reportCheck"><input type="checkbox" checked={instructionRequireAck} onChange={e=>setInstructionRequireAck(e.target.checked)}/><span>Zahtijevaj potvrdu čitanja od djelatnika.</span></label><div className="reportActions"><span>Objava se evidentira u audit tragu i operativnom dnevniku.</span><button className="goldBtn" onClick={createInstruction}>Objavi službenu uputu</button></div></section>}
          <section className="simplePanel instructionList"><div className="sectionHead"><div><h3>Aktivne upute</h3><p>Djelatnik potvrđuje čitanje; voditelj vidi evidenciju potvrda.</p></div></div>{relevantInstructions.length===0?<div className="emptyReportState"><b>Nema aktivnih uputa.</b></div>:relevantInstructions.map(i=>{const read=i.acks?.some(a=>a.employeeId===currentEmployee?.id);return <article className={`instructionCard ${i.priority==="HITNO"?"urgent":i.priority==="VAŽNO"?"important":""}`} key={i.id}><div className="instructionTop"><div><span>{i.priority} · {i.site}</span><b>{i.title}</b><small>Objavio: {i.createdBy} · {new Date(i.createdAt).toLocaleString("hr-HR")}</small></div>{i.requireAck&&<strong>{currentUserRole==="Zaštitar"?(read?"PROČITANO":"POTVRDA POTREBNA"):`${i.acks?.length||0} potvrda`}</strong>}</div><p>{i.text}</p>{currentUserRole==="Zaštitar"&&i.requireAck&&!read&&<button className="goldBtn" onClick={()=>acknowledgeInstruction(i.id)}>Potvrdi da sam pročitao/la</button>}{(currentUserRole==="Voditelj"||currentUserRole==="Administrator")&&<div className="instructionAck"><b>Potvrde čitanja:</b><span>{i.acks?.length?i.acks.map(a=>`${a.employee} (${new Date(a.at).toLocaleString("hr-HR")})`).join(" · "):"Još nema potvrda."}</span><button className="miniBtn" onClick={()=>closeInstruction(i.id)}>Zaključi uputu</button></div>}</article>})}</section>
        </SimplePage>}

        {page==="reports" && <SimplePage title="Izvješća" sub="Službena redovna izvješća smjene i izvješća o izvanrednim događajima.">
          <div className="reportHero">
            <div><b>Službena evidencija izvješća</b><span>Svako predano izvješće dobiva jedinstveni broj, vrijeme predaje i status pregleda.</span></div>
            {(currentUserRole==="Voditelj"||currentUserRole==="Administrator")&&<div className="reportCounters"><span><b>{newManagerReports}</b> novih za voditelja</span></div>}
            {currentUserRole==="Direktor"&&<div className="reportCounters"><span><b>{newDirectorReports}</b> novih za direktora</span></div>}
          </div>

          {canManage && <section className="simplePanel incidentRequestPanel">
            <div className="sectionHead"><div><h3>Zahtjev za izvješće o izvanrednom događaju</h3><p>Voditelj izdaje zahtjev konkretnom djelatniku. Zahtjev je odmah vidljiv djelatniku u probnom sustavu.</p></div><span className="docTag">VODITELJ</span></div>
            <div className="formGrid compactForm">
              <label>Djelatnik<select value={incidentRequestEmployee} onChange={e=>setIncidentRequestEmployee(e.target.value)}>{employees.filter(e=>e.active!==false&&/zaštitar/i.test(e.role||"")).map(e=><option value={e.id} key={e.id}>{e.name} · {e.site}</option>)}</select></label>
              <label>Rok za predaju<input type="datetime-local" value={incidentRequestDeadline} onChange={e=>setIncidentRequestDeadline(e.target.value)}/></label>
              <label className="wide">Razlog / nalog za sastavljanje izvješća *<textarea rows="3" value={incidentRequestReason} onChange={e=>setIncidentRequestReason(e.target.value)} placeholder="Kratko i činjenično navedite događaj o kojem djelatnik mora sastaviti službeno izvješće."/></label>
            </div>
            <div className="reportActions"><span>Zahtjev ostaje evidentiran u audit tragu.</span><button className="goldBtn" onClick={createIncidentRequest} disabled={!incidentRequestReason.trim()}>Izdaj zahtjev djelatniku</button></div>
          </section>}

          {currentUserRole==="Zaštitar" && <div className="reportTabs"><button className={reportMode==="REDOVNO"?"active":""} onClick={()=>setReportMode("REDOVNO")}>Redovno izvješće smjene</button><button className={reportMode==="IZVANREDNO"?"active":""} onClick={()=>setReportMode("IZVANREDNO")}>Izvanredni događaj {incidentRequestsForRole.filter(r=>r.status==="ZAHTJEV IZDAN").length>0?`(${incidentRequestsForRole.filter(r=>r.status==="ZAHTJEV IZDAN").length})`:""}</button></div>}

          {currentUserRole==="Zaštitar" && reportMode==="REDOVNO" && <section className="simplePanel reportEditor professionalEditor">
            <div className="sectionHead"><div><h3>Redovno izvješće smjene</h3><p>Popunjava se za odrađenu smjenu. Podaci moraju biti činjenični, jasni i sažeti.</p></div><span className="docTag">RI</span></div>
            <div className="autoMeta"><span><small>DJELATNIK</small><b>{loggedEmployeeRecord?.name||"—"}</b></span><span><small>OBJEKT</small><b>{loggedEmployeeRecord?.site||"—"}</b></span><span><small>DATUM</small><b>{isoDate()}</b></span><span><small>SMJENA</small><b>{employeeScheduleRecord(loggedEmployeeRecord,isoDate())?.shift||loggedEmployeeRecord?.shift||"—"}</b></span></div>
            <label className="reportCheck"><input type="checkbox" checked={shiftReportNoEvents} onChange={e=>setShiftReportNoEvents(e.target.checked)}/><span>Smjena je protekla bez posebnih sigurnosnih događaja.</span></label>
            <div className="structuredForm">
              <label>Sažetak smjene *<textarea rows="4" value={shiftReportSummary} onChange={e=>setShiftReportSummary(e.target.value)} placeholder="Sažeto opišite tijek smjene i opće stanje objekta."/></label>
              <label>Provedene aktivnosti i zadaće *<textarea rows="4" value={shiftReportTasks} onChange={e=>setShiftReportTasks(e.target.value)} placeholder="Kontrole ulaza/izlaza, obilasci, preuzimanje opreme, postupanja prema radnom nalogu..."/></label>
              <label>Zapažanja / nepravilnosti<textarea rows="4" value={shiftReportObservations} onChange={e=>setShiftReportObservations(e.target.value)} placeholder="Navedite nepravilnosti ili napišite da nisu uočene."/></label>
              <label>Primopredaja smjene *<textarea rows="4" value={shiftReportHandover} onChange={e=>setShiftReportHandover(e.target.value)} placeholder="Stanje pri predaji, ključevi, oprema, otvorene zadaće i informacije za sljedeću smjenu."/></label>
            </div>
            <div className="legalNote">Predajom potvrđujete da je sadržaj izvješća sastavljen prema vašim neposrednim saznanjima i službenim evidencijama.</div>
            <div className="reportActions"><span>Predano izvješće dobiva trajni broj i ide voditelju.</span><button className="goldBtn" onClick={submitShiftReport}>Predaj redovno izvješće</button></div>
          </section>}

          {currentUserRole==="Zaštitar" && reportMode==="IZVANREDNO" && <section className="simplePanel reportEditor professionalEditor">
            <div className="sectionHead"><div><h3>Izvješće o izvanrednom događaju</h3><p>Sastavlja se po zahtjevu voditelja. Opisujte činjenice kronološki i bez pretpostavki.</p></div><span className="docTag alertTag">ID</span></div>
            {incidentRequestsForRole.filter(r=>r.status==="ZAHTJEV IZDAN").length===0?<div className="emptyReportState"><b>Nema aktivnog zahtjeva.</b><span>Izvanredno izvješće otvara se kada voditelj zatraži njegovo sastavljanje.</span></div>:<>
              <label className="requestPicker">Aktivni zahtjev<select value={activeIncidentRequestId} onChange={e=>{setActiveIncidentRequestId(e.target.value);const q=incidentRequests.find(x=>x.id===e.target.value);if(q){setIncidentEventDate(q.createdDate||isoDate());}}}><option value="">— odaberi zahtjev —</option>{incidentRequestsForRole.filter(r=>r.status==="ZAHTJEV IZDAN").map(r=><option value={r.id} key={r.id}>{r.createdDate} · {r.site} · {r.reason.slice(0,70)}</option>)}</select></label>
              {activeIncidentRequestId&&(()=>{const q=incidentRequests.find(x=>x.id===activeIncidentRequestId);return q?<div className="requestBrief"><b>Nalog voditelja</b><p>{q.reason}</p><span>Izdano: {q.createdDate} {q.createdTime} · {q.requestedBy} · Rok: {q.deadline}</span></div>:null})()}
              <div className="formGrid compactForm"><label>Datum događaja *<input type="date" value={incidentEventDate} onChange={e=>setIncidentEventDate(e.target.value)}/></label><label>Vrijeme događaja *<input type="time" value={incidentEventTime} onChange={e=>setIncidentEventTime(e.target.value)}/></label><label className="wide">Točno mjesto događaja *<input value={incidentLocation} onChange={e=>setIncidentLocation(e.target.value)} placeholder="npr. servisni ulaz, skladište B, parkiralište..."/></label></div>
              <div className="structuredForm"><label>Opis i kronologija događaja *<textarea rows="6" value={incidentChronology} onChange={e=>setIncidentChronology(e.target.value)} placeholder="Navedite redoslijed činjenica: što ste uočili, kada, gdje i što se zatim dogodilo."/></label><label>Poduzete mjere i postupanje *<textarea rows="5" value={incidentActions} onChange={e=>setIncidentActions(e.target.value)} placeholder="Što ste konkretno poduzeli u okviru ovlasti i radnog naloga."/></label><label>Obaviještene osobe / službe<textarea rows="3" value={incidentNotified} onChange={e=>setIncidentNotified(e.target.value)} placeholder="Voditelj, odgovorna osoba klijenta, policija, vatrogasci, hitna pomoć..."/></label><label>Uključene osobe / svjedoci<textarea rows="3" value={incidentPersons} onChange={e=>setIncidentPersons(e.target.value)} placeholder="Ime i uloga ako je poznato; bez nepotrebnih osobnih podataka."/></label><label>Posljedice / šteta<textarea rows="3" value={incidentDamage} onChange={e=>setIncidentDamage(e.target.value)} placeholder="Činjenično navedite utvrđenu štetu ili da nije utvrđena."/></label><label>Završno stanje *<textarea rows="4" value={incidentFinalState} onChange={e=>setIncidentFinalState(e.target.value)} placeholder="Stanje nakon poduzetih mjera i otvorene radnje za daljnje postupanje."/></label></div>
              <div className="legalNote warningNote">Ne unosite pretpostavke, dijagnoze ni zaključke koje niste neposredno utvrdili. Zabilježite činjenice i službeno poduzete radnje.</div>
              <div className="reportActions"><span>Predajom se zahtjev označava dovršenim i izvješće ide voditelju.</span><button className="goldBtn" onClick={submitIncidentReport} disabled={!activeIncidentRequestId}>Predaj izvanredno izvješće</button></div>
            </>}
          </section>}

          {(currentUserRole==="Voditelj"||currentUserRole==="Administrator") && incidentRequests.length>0 && <section className="simplePanel requestRegister"><div className="sectionHead"><div><h3>Evidencija zahtjeva za izvanredno izvješće</h3><p>Pregled izdanih zahtjeva i njihove realizacije.</p></div></div>{incidentRequests.slice(0,8).map(q=><div className="requestRegisterRow" key={q.id}><div><b>{q.employee}</b><span>{q.site} · {q.createdDate} {q.createdTime}</span></div><p>{q.reason}</p><strong className={q.status==="IZVJEŠĆE PREDANO"?"done":"pending"}>{q.status}</strong></div>)}</section>}

          <section className="simplePanel reportListPanel professionalList">
            <div className="sectionHead"><div><h3>{currentUserRole==="Direktor"?"Izvješća proslijeđena direktoru":currentUserRole==="Zaštitar"?"Moja predana izvješća":"Ulazna izvješća voditelja"}</h3><p>{currentUserRole==="Voditelj"||currentUserRole==="Administrator"?"Nova predana izvješća pojavljuju se ovdje odmah u probnom sustavu.":"Službena evidencija predanih dokumenata."}</p></div></div>
            <div className="reportList">{reportsForRole.length===0?<div className="emptyReportState"><b>Nema izvješća za prikaz.</b></div>:reportsForRole.map(r=><article className={`reportCard proCard ${r.managerStatus==="NOVO"&&canManage?"unread":""}`} key={r.id}>
              <div className="reportCardTop"><div><div className="reportNo">{r.reportNo||"BEZ BROJA"}</div><b>{r.type==="IZVANREDNO"?"Izvješće o izvanrednom događaju":"Redovno izvješće smjene"}</b><span>{r.site} · {r.author}</span></div><div className="reportStatuses"><strong>{currentUserRole==="Direktor"?(r.directorStatus||"NOVO"):(r.managerStatus||r.status)}</strong>{r.forwardedToDirector&&<em>DIREKTOR</em>}</div></div>
              <div className="reportPreview"><span><small>Predano</small>{r.date} {r.time}</span>{r.type==="REDOVNO"&&<span><small>Smjena</small>{r.shift||"—"}</span>}{r.type==="IZVANREDNO"&&<span><small>Događaj</small>{r.eventDate||"—"} {r.eventTime||""}</span>}</div>
              <p>{r.type==="IZVANREDNO"?(r.chronology||r.content):(r.summary||r.content)}</p>
              <div className="reportMeta"><span>{r.status} · zapis zaključan kao predan</span><div className="reportCardActions">{canManage&&r.managerStatus==="NOVO"&&<button className="miniBtn" onClick={()=>markReportRead(r.id)}>Označi pročitano</button>}{canManage&&!r.forwardedToDirector&&<button className="miniBtn directorBtn" onClick={()=>forwardReportToDirector(r.id)}>Proslijedi direktoru</button>}{currentUserRole==="Direktor"&&r.directorStatus!=="PROČITANO"&&<button className="miniBtn" onClick={()=>markDirectorRead(r.id)}>Označi pročitano</button>}<button className="miniBtn" onClick={()=>printReportPdf(r)}>Službeni PDF / ispis</button></div></div>
            </article>)}</div>
          </section>
          <div className="permissionNote">Probna verzija: predaja i prosljeđivanje rade odmah unutar lokalne SENTRYPRO aplikacije. Za stvarnu dostavu između različitih računala potreban je centralni poslužitelj i autentikacija korisnika.</div>
        </SimplePage>}

        {page==="payroll" && <SimplePage title="Plaće" subtitle="Mjesečni obračunski podaci dostupni samo ovlaštenom odjelu Plaća.">
          <div className="payrollToolbar"><input type="month" value={payrollMonth} onChange={e=>setPayrollMonth(e.target.value)}/><span>{employees.length} djelatnika</span></div>
          <div className="payrollRates"><b>Postavke dodataka (%)</b><label>Noć <input type="number" value={payrollRates.night} onChange={e=>setPayrollRates({...payrollRates,night:Number(e.target.value)})}/></label><label>Nedjelja <input type="number" value={payrollRates.sunday} onChange={e=>setPayrollRates({...payrollRates,sunday:Number(e.target.value)})}/></label><label>Blagdan <input type="number" value={payrollRates.holiday} onChange={e=>setPayrollRates({...payrollRates,holiday:Number(e.target.value)})}/></label><label>Prekovremeni <input type="number" value={payrollRates.overtime} onChange={e=>setPayrollRates({...payrollRates,overtime:Number(e.target.value)})}/></label></div><div className="permissionNote">SENTRYPRO automatski zbraja evidentirane sate, noćni rad, nedjelje, blagdane i prekovremene sate. Iznosi plaće ostaju simulacija dok tvrtka ne unese vlastite ugovorene i obračunske parametre.</div>
          <section className="simplePanel employeeTableWrap">
            <div className="payrollGrid payrollHead"><span>Djelatnik</span><span>Fond</span><span>Radio</span><span>GO plaćeno</span><span>Za isplatu</span><span>Prekov.</span><span>Noć</span><span>Nedj.</span><span>Blagdan</span><span>GO ostalo</span><span>Simulacija</span><span>Procjena bruto</span><span>Platna lista</span></div>
            {employees.filter(e=>e.active!==false).map(e=>{const s=employeeMonthStats(e);return <div className="payrollGrid payrollRow" key={e.id}>
              <b>{e.name}</b><span>{s.fund.toFixed(1)}</span><span>{s.worked.toFixed(1)}</span><span>{s.goPaid.toFixed(1)}</span><span>{s.paidTotal.toFixed(1)}</span><span>{s.overtime.toFixed(1)}</span><span>{s.night.toFixed(1)}</span><span>{s.sunday.toFixed(1)}</span><span>{s.holiday.toFixed(1)}</span><span>{annualLeaveRemaining(e)} d.</span><span>{s.adjustment.toFixed(2)} €</span><b>{s.grossEstimate.toFixed(2)} €</b><button className="miniBtn" onClick={()=>printPayslip(e)}>PDF</button>
            </div>})}
          </section>
        </SimplePage>}

        {page==="settings" && <SimplePage title="Postavke" sub="Osnovne postavke SENTRYPRO sustava.">
          <div className="privacyPanel"><h3>Privatnost i izolacija objekata</h3><p>Produkcijska verzija mora provoditi izolaciju podataka na poslužitelju, ne samo u sučelju: svaki zapis nosi ID objekta/klijenta, ovlasti se provjeravaju na svakom API zahtjevu, a pristupi osjetljivim podacima ulaze u audit zapis.</p><div className="privacyFlags"><span>✓ minimalni pristup</span><span>✓ audit log</span><span>✓ rokovi čuvanja</span><span>✓ enkripcija u prijenosu</span></div></div>
          <div className="settingsBox"><label>Naziv tvrtke<input defaultValue="AKD ZAŠTITA"/></label><label>Naziv sustava<input defaultValue="SENTRYPRO"/></label><label>Jezik<select defaultValue="Hrvatski"><option>Hrvatski</option></select></label></div>
          <div className="readinessGrid"><div><b>✓ Izolacija objekata</b><span>Rasporedi i izvještaji filtrirani po dodijeljenom objektu.</span></div><div><b>✓ Operativni izvještaji</b><span>Zaštitar i voditelj mogu pisati uz odgovarajuće ovlasti.</span></div><div><b>✓ PDF evidencija</b><span>Izvještaji i hitne situacije spremni za ispis/PDF.</span></div><div><b>✓ Audit trag</b><span>Bilježe se ključne operativne radnje u prototipu.</span></div></div>
          <section className="simplePanel auditPanel"><h3>Audit trag — zadnje radnje</h3>{auditLog.length===0?<p className="muted">Još nema novih zabilježenih radnji u ovoj verziji.</p>:auditLog.slice(0,20).map(a=><div className="auditRow" key={a.id}><b>{a.action}</b><span>{a.detail}</span><small>{a.actor} · {a.date} {a.time}</small></div>)}</section>
        </SimplePage>}
      </main>
    </div>

    {showVisitor && <div className="modalBackdrop" onMouseDown={()=>setShowVisitor(false)}>
      <form className="modal visitorModal compactModal" onSubmit={addVisitor} onMouseDown={e=>e.stopPropagation()}>
        <div className="modalHeader"><div><span>NOVA NAJAVA</span><h2>Najavi posjetitelja</h2></div><button type="button" onClick={()=>setShowVisitor(false)}>×</button></div>
        <div className="formGrid compactForm">
          <label>Ime<input name="firstName" required/></label>
          <label>Prezime<input name="lastName" required/></label>
          <label>Firma iz koje dolazi<input name="company" required/></label>
          <label>Kome ide<input name="visiting" required/></label>
          <label className="wide">Razlog dolaska<input name="reason" required/></label>
          <label>Objekt<select name="site" defaultValue={editingUser?.site || ""}>{sites.map(s=><option key={s.id}>{s.name}</option>)}</select></label>
          <label>Datum<input name="date" type="date" defaultValue={today}/></label>
          <label>Očekivano vrijeme<input name="expected" type="time"/></label>
          <label>Broj dokumenta<input name="documentNumber" placeholder="npr. OI 123456789"/></label>
          <label>Registracija vozila<input name="plate" placeholder="npr. ZG 1234 AB"/></label>
          <label>Broj kartice / ključa<input name="card" placeholder="npr. K-014"/></label>
          <label className="wide">Napomena<textarea name="note" rows="1" placeholder="Dodatna napomena..."/></label>
        </div>
        <div className="modalActions stickyActions"><button type="button" className="ghostBtn" onClick={()=>setShowVisitor(false)}>Odustani</button><button className="goldBtn">Spremi najavu</button></div>
      </form>
    </div>}





    {showSite && <div className="modalBackdrop" onMouseDown={()=>{setEditingSite(null);setShowSite(false)}}>
      <form className="modal userModal" onSubmit={addSite} onMouseDown={e=>e.stopPropagation()}>
        <div className="modalHeader"><div><span>{editingSite ? "UREDI OBJEKT" : "NOVI OBJEKT"}</span><h2>{editingSite ? "Uredi objekt" : "Unos objekta"}</h2></div><button type="button" onClick={()=>{setEditingSite(null);setShowSite(false)}}>×</button></div>
        <div className="formGrid compactForm">
          <label className="wide">Naziv objekta<input name="name" defaultValue={editingSite?.name || ""} required placeholder="npr. Poslovni centar Zapad"/></label>
          <label className="wide">Klijent / tvrtka<input name="client" defaultValue={editingSite?.client || ""} placeholder="Naziv klijenta"/></label>
          <label>Grad<input name="city" defaultValue={editingSite?.city || ""} placeholder="Zagreb"/></label><label>Adresa<input name="address" defaultValue={editingSite?.address || ""} placeholder="Ulica i broj"/></label>
          <label>Kontakt osoba<input name="contact" defaultValue={editingSite?.contact || ""} placeholder="Ime i prezime"/></label><label>Telefon / službeni kontakt<input name="phone" defaultValue={editingSite?.phone || ""} placeholder="091 123 4567"/></label>
          <label>Planirana popunjenost<input name="guards" defaultValue={editingSite?.guards || ""} placeholder="npr. 2/2"/></label>
        </div>
        <div className="modalActions stickyActions"><button type="button" className="ghostBtn" onClick={()=>{setEditingSite(null);setShowSite(false)}}>Odustani</button><button className="goldBtn">{editingSite ? "Spremi promjene" : "Spremi objekt"}</button></div>
      </form>
    </div>}

    {showHours && <div className="modalBackdrop" onMouseDown={()=>setShowHours(false)}>
      <form className="modal userModal" onSubmit={addWorkHours} onMouseDown={e=>e.stopPropagation()}>
        <div className="modalHeader"><div><span>EVIDENCIJA SATI</span><h2>Upis smjene</h2></div><button type="button" onClick={()=>setShowHours(false)}>×</button></div>
        <div className="formGrid compactForm">
          <label className="wide">Djelatnik<select name="employee">{employees.filter(e=>e.active!==false).map(e=><option key={e.id}>{e.name}</option>)}</select></label>
          <label>Datum<input name="date" type="date" required/></label>
          <label>Smjena<select name="shift"><option value="I">I — 07:00–19:00</option><option value="II">II — 19:00–07:00</option><option value="SL">SL — slobodan</option><option value="GO">GO — godišnji</option><option value="BO">BO — bolovanje</option></select></label>
          <label className="wide">Objekt<select name="site">{sites.map(s=><option key={s.id}>{s.name}</option>)}</select></label>
        </div>
        <div className="modalActions stickyActions"><button type="button" className="ghostBtn" onClick={()=>setShowHours(false)}>Odustani</button><button className="goldBtn">Spremi smjenu</button></div>
      </form>
    </div>}

    {showPatrol && <div className="modalBackdrop" onMouseDown={()=>setShowPatrol(false)}>
      <form className="modal userModal" onSubmit={addPatrol} onMouseDown={e=>e.stopPropagation()}>
        <div className="modalHeader"><div><span>NOVI OBILAZAK</span><h2>Evidentiraj obilazak</h2></div><button type="button" onClick={()=>setShowPatrol(false)}>×</button></div>
        <div className="formGrid compactForm">
          <label className="wide">Djelatnik<select name="employee">{employees.filter(e=>e.active!==false).map(e=><option key={e.id}>{e.name} · {e.cardNumber || "bez iskaznice"}</option>)}</select></label>
          <label className="wide">Objekt<select name="site" defaultValue={editingUser?.site || ""}>{sites.map(s=><option key={s.id}>{s.name}</option>)}</select></label>
          <label>Datum<input name="date" type="date" defaultValue={today}/></label>
          <label>Izvor<select name="source"><option>Ručni unos</option><option>Kerber</option></select></label>
          <label>Početak<input name="start" type="time" required/></label>
          <label>Kraj<input name="end" type="time" required/></label>
          <label>Kontrolnih točaka odrađeno<input name="checkpointsDone" type="number" min="0" defaultValue="0"/></label>
          <label>Ukupno kontrolnih točaka<input name="checkpointsTotal" type="number" min="0" defaultValue="0"/></label>
        </div>
        <div className="modalActions stickyActions"><button type="button" className="ghostBtn" onClick={()=>setShowPatrol(false)}>Odustani</button><button className="goldBtn">Spremi obilazak</button></div>
      </form>
    </div>}

    {showUser && <div className="modalBackdrop" onMouseDown={()=>{setEditingUser(null);setShowUser(false)}}>
      <form className="modal userModal" onSubmit={addUser} onMouseDown={e=>e.stopPropagation()}>
        <div className="modalHeader"><div><span>NOVI KORISNIK</span><h2>{editingUser ? "Uredi djelatnika" : "Unos novog djelatnika"}</h2></div><button type="button" onClick={()=>{setEditingUser(null);setShowUser(false)}}>×</button></div>
        <div className="formGrid compactForm">
          <label className="wide">Ime i prezime<input name="name" defaultValue={editingUser?.name || ""} required placeholder="npr. Ivan Horvat"/></label>
          <label>Uloga<select name="role" defaultValue={editingUser?.role || "Zaštitar"}><option>Zaštitar</option><option>Voditelj</option><option>Administrator</option></select></label>
          <label>Objekt<select name="site" defaultValue={editingUser?.site || ""}><option>—</option>{sites.map(s=><option key={s.id}>{s.name}</option>)}</select></label><div className="wide siteChecks"><b>Dodatni objekti na kojima djelatnik smije raditi</b><div>{sites.map(s=><label key={s.id}><input type="checkbox" name="assignedSites" value={s.name} defaultChecked={(editingUser?.assignedSites||[]).includes(s.name)}/>{s.name}</label>)}</div><small>Primarni objekt iznad automatski ostaje dodijeljen. Voditelj može djelatnika rasporediti i na dodatne lokacije.</small></div>
          <label>Smjena<select name="shift" defaultValue={editingUser?.shift || ""}><option>I (07:00–19:00)</option><option>II (19:00–07:00)</option><option>SL</option></select></label>
          <label>Status<select name="status" defaultValue={editingUser?.status || "Slobodan"}><option>Slobodan</option><option>Na smjeni</option><option>Kašnjenje</option><option>Bolovanje</option><option>Godišnji odmor</option></select></label>
          <label>Telefon<input name="phone" defaultValue={editingUser?.phone || ""} placeholder="091 123 4567"/></label>
          <label>Poslovni e-mail<input name="email" defaultValue={editingUser?.email || ""} type="email" placeholder="ime@firma.hr"/></label>
          <label>Broj iskaznice<input name="cardNumber" defaultValue={editingUser?.cardNumber || ""} placeholder="npr. ISK-001"/></label>
          <label>Registracija službenog/odobrenog vozila<input name="vehiclePlate" defaultValue={editingUser?.vehiclePlate || ""} placeholder="ZG 1234 AB"/></label>
          <label className="checkLabel"><input name="vehicleAccess" type="checkbox" defaultChecked={editingUser?.vehicleAccess || false}/> Dozvoljen automatski ulaz vozilom</label>
          <label className="checkLabel replacementCheck"><input name="replacementAvailable" type="checkbox" defaultChecked={editingUser?.replacementAvailable || false}/> Dostupan i voljan raditi zamjene</label>
          <label>Godišnji odmor - ukupno dana<input name="annualLeaveEntitlement" type="number" min="0" defaultValue={editingUser?.annualLeaveEntitlement ?? 20}/></label>
          <label>Godišnji odmor - iskorišteno dana<input name="annualLeaveUsed" type="number" min="0" defaultValue={editingUser?.annualLeaveUsed ?? 0}/></label>
          <label>Ugovorena osnovna bruto plaća (€)<input name="baseGross" type="number" min="0" step="0.01" defaultValue={editingUser?.baseGross ?? 0}/></label>
          <label>Broj licence<input name="license" defaultValue={editingUser?.license || ""} placeholder="npr. Z-10234"/></label>
          <label>Datum zaposlenja<input name="employmentDate" type="date" defaultValue={editingUser?.employmentDate || ""}/></label>
          <label>Vrijedi do<input name="licenseExpiry" defaultValue={editingUser?.licenseExpiry || ""} type="date"/></label>
          <label className="wide">Operativne ovlasti<textarea name="authorities" rows="3" defaultValue={editingUser?.authorities || "Kontrola ulaza/izlaza; ophodnja; evidencija događaja; postupanje prema radnom nalogu"} placeholder="Npr. kontrola ulaza/izlaza; ophodnja; evidencija događaja..."/></label>
        </div>
        <div className="modalActions stickyActions"><button type="button" className="ghostBtn" onClick={()=>{setEditingUser(null);setShowUser(false)}}>Odustani</button><button className="goldBtn">{editingUser ? "Spremi promjene" : "Spremi djelatnika"}</button></div>
      </form>
    </div>}

    {showEvent && <div className="modalBackdrop" onMouseDown={()=>setShowEvent(false)}>
      <form className="modal eventModal" onSubmit={addEvent} onMouseDown={e=>e.stopPropagation()}>
        <div className="modalHeader"><div><span>NOVI DOGAĐAJ</span><h2>Evidentiraj događaj</h2></div><button type="button" onClick={()=>setShowEvent(false)}>×</button></div>
        <div className="formGrid compactForm">
          <label>Datum<input name="date" type="date" defaultValue={today}/></label>
          <label>Vrijeme<input name="time" type="time" defaultValue={new Date().toTimeString().slice(0,5)}/></label>
          <label>Objekt<select name="site" defaultValue={editingUser?.site || ""}>{sites.map(s=><option key={s.id}>{s.name}</option>)}</select></label>
          <label>Vrsta događaja<select name="category"><option>Sigurnosni događaj</option><option>Incident</option><option>Tehnički kvar</option><option>Kašnjenje</option><option>Primopredaja</option><option>Kontrola</option><option>Ostalo</option></select></label>
          <label className="wide">Naziv događaja<input name="title" required placeholder="Kratak naziv događaja"/></label>
          <label className="wide">Detaljan opis<textarea name="description" required rows="3" placeholder="Opiši što se dogodilo i koje su radnje poduzete..."/></label>
          <label>Evidentirao<input name="recordedBy" defaultValue="Administrator" required/></label>
          <label>Razina važnosti<select name="level"><option>Nisko</option><option>Srednje</option><option>Visoko</option><option>Kritično</option></select></label>
          <label className="wide">Naknadna napomena<textarea name="followUp" rows="2" placeholder="Npr. obaviješten voditelj, potreban servis..."/></label>
          <label className="wide">Fotografija / dokument<input name="attachment" type="file" accept="image/*,.pdf,.doc,.docx"/></label>
        </div>
        <div className="attachmentNote">U ovoj razvojnoj verziji sprema se naziv odabrane datoteke. Trajno spremanje samog priloga povezat ćemo s pravom bazom podataka.</div>
        <div className="modalActions stickyActions"><button type="button" className="ghostBtn" onClick={()=>setShowEvent(false)}>Odustani</button><button className="goldBtn">Spremi događaj</button></div>
      </form>
    </div>}
  </div>
}

function Stat({icon,label,value,sub,tone}){return <div className="statCard"><div className={`statIcon ${tone}`}>{icon}</div><div><span>{label}</span><strong>{value}</strong><small>{sub}</small></div></div>}
function Mini({icon,label,value,sub,good}){return <div className="miniCard"><div className="miniIcon">{icon}</div><div><span>{label}</span><b className={good?"goodText":""}>{value}</b><small>{sub}</small></div></div>}
function Status({status}){return <span className={`status ${status==="U OBJEKTU"?"inside":status==="IZAŠAO"?"out":"announced"}`}>{status}</span>}

function VisitorPanel({visitors,query,setQuery,siteFilter,setSiteFilter,sites,setShowVisitor,enterVisitor,exitVisitor,full,readOnly=false}){
  return <section className={`visitorPanel ${full?"full":""}`}>
    <div className="panelTop">
      <div className="panelTitle"><div className="panelBadge">👥</div><div><h3>Najave i posjetitelji</h3><p>Evidencija dolazaka i odlazaka posjetitelja.</p></div></div>
      <div className="panelActions">
        <div className="searchWrap">⌕<input value={query} onChange={e=>setQuery(e.target.value)} placeholder="Pretraži ime, firmu, razlog, registraciju..."/></div>
        {!readOnly&&<select value={siteFilter} onChange={e=>setSiteFilter(e.target.value)}><option>Svi objekti</option>{sites.map(s=><option key={s.id}>{s.name}</option>)}</select>}
        {!readOnly&&<button className="goldBtn" onClick={()=>setShowVisitor(true)}>＋ Nova najava</button>}
      </div>
    </div>
    <div className="visitorListHeader">
      <span>Posjetitelj / firma</span><span>Kome ide / razlog</span><span>Objekt</span><span>Dokument / vozilo</span><span>Vrijeme</span><span>Status</span><span>Akcija</span>
    </div>
    <div className="visitorList">
      {visitors.map((v)=><div className="visitorRow" key={v.id}>
        <div className="vPrimary"><b>{v.firstName} {v.lastName}</b><small>{v.company}</small></div>
        <div className="vDouble"><b>{v.visiting}</b><small>{v.reason}</small></div>
        <div className="vDouble"><b>{v.site}</b><small>{v.date}</small></div>
        <div className="vDouble"><b>{v.documentNumber||"Dokument nije upisan"}</b><small>{v.plate||"Bez vozila"}{v.card?` · Kartica ${v.card}`:""}</small></div>
        <div className="vTimes"><small>Oček. {v.expected||"—"}</small><b>{v.enteredAt||"—"} → {v.exitedAt||"—"}</b></div>
        <div><Status status={v.status}/></div>
        <div>{readOnly?<span className="done">Samo uvid</span>:v.status==="NAJAVLJEN"?<button className="enterBtn" onClick={()=>enterVisitor(v.id)}>ULAZ</button>:
             v.status==="U OBJEKTU"?<button className="exitBtn" onClick={()=>exitVisitor(v.id)}>IZLAZ</button>:
             <span className="done">Završeno</span>}</div>
      </div>)}
    </div>
    <div className="tableFooter"><span>Prikazano {visitors.length} zapisa</span><div className="pager"><button>‹</button><button className="active">1</button><button>›</button></div></div>
  </section>
}

function EventCard({x}){
  const cls=x.level==="Kritično"?"critical":x.level==="Visoko"?"high":x.level==="Srednje"?"medium":"low";
  return <div className="eventCard">
    <div className="eventWhen"><b>{x.time}</b><span>{x.date}</span></div>
    <div className="eventMain"><div className="eventTitle"><b>{x.title}</b><span className={`level ${cls}`}>{x.level}</span></div><p>{x.description}</p>
      <div className="eventMeta"><span>📍 {x.site}</span><span>🏷 {x.category}</span><span>👤 {x.recordedBy}</span>{x.attachment&&<span>📎 {x.attachment}</span>}</div>
      {x.followUp&&<div className="followUp"><b>Naknadna napomena:</b> {x.followUp}</div>}
    </div>
  </div>
}

function SimplePage({title,sub,children}){return <><section className="pageTitle"><h1>{title}</h1><p>{sub}</p></section><section className="simplePanel">{children}</section></>}

createRoot(document.getElementById("root")).render(<App/>);
