{"id":5962,"date":"2026-08-02T17:17:24","date_gmt":"2026-08-02T15:17:24","guid":{"rendered":"https:\/\/omissmartcity.com\/?page_id=5962"},"modified":"2026-08-02T17:17:26","modified_gmt":"2026-08-02T15:17:26","slug":"staff-validator","status":"publish","type":"page","link":"https:\/\/omissmartcity.com\/hr\/staff-validator\/","title":{"rendered":"Staff Validator"},"content":{"rendered":"<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><script>var OSC_I18N_JS = {\"get_informed\":\"Get informed. Experience the best.\",\"powered_by\":\"Pokre\\u0107e\",\"smart_offer_id\":\"ID posebne ponude\",\"active\":\"Aktivan\",\"redeemed\":\"Iskori\\u0161ten\",\"expired\":\"Istekao\",\"cancelled\":\"Otkazan\",\"already_redeemed_on\":\"Ve\\u0107 iskori\\u0161ten\",\"no_longer_valid\":\"Ovaj vau\\u010der vi\\u0161e nije valjan.\",\"present_voucher\":\"Poka\\u017eite ovaj vau\\u010der prije pla\\u0107anja.\",\"staff_will_scan\":\"Osoblje \\u0107e skenirati QR kod kako bi iskoristili ponudu.\",\"share_btn\":\"Spremi ili podijeli ovaj vau\\u010der\",\"share_link_copied\":\"Link kopiran! Zalijepi ga bilo gdje da spremi\\u0161.\",\"share_bookmark\":\"Spremi ovu stranicu u favorite da sa\\u010duva\\u0161 vau\\u010der.\",\"exclusive_badge\":\"Omi\\u0161SmartCity Ekskluzivno\",\"experience_badge\":\"Omi\\u0161SmartCity Do\\u017eivljaj\",\"special_offer_heading\":\"Posebna ponuda\",\"get_your_offer\":\"Preuzmi Ponudu\",\"valid_until\":\"Vrijedi do\",\"time_left\":\"Preostalo\",\"claimed\":\"Preuzeto\",\"days_left_suffix\":\"dana preostalo\",\"day_left_suffix\":\"dan preostao\",\"claimed_suffix\":\"preuzeto\",\"claim_note\":\"Preuzmite ponudu na omissmartcity.com i poka\\u017eite kod osoblju.\",\"smart_offers_title\":\"Posebne ponude\",\"partner_access\":\"Pristup za partnere\",\"enter_staff_pin\":\"Unesite PIN osoblja\",\"unlock\":\"Otklju\\u010daj\",\"incorrect_pin\":\"Neto\\u010dan PIN\",\"enter_6_digits\":\"Unesite 6 znamenki\",\"something_wrong\":\"Ne\\u0161to je po\\u0161lo po zlu. Poku\\u0161ajte ponovno.\",\"partner_account\":\"Partnerski ra\\u010dun\",\"scan_qr_code\":\"Skeniraj QR kod\",\"scan_helper\":\"Usmjerite kameru na QR kod gosta kako biste provjerili i iskoristili ponudu.\",\"cant_scan\":\"Ne mo\\u017eete skenirati?\",\"enter_code_manually\":\"Unesite kod ru\\u010dno\",\"logged_in_as\":\"Prijavljeni kao\",\"switch_partner\":\"Promijeni partnera\",\"check_voucher\":\"Provjeri vau\\u010der\",\"paste_token\":\"Zalijepi token ili skenirani URL\",\"tab_scan\":\"Skeniraj\",\"tab_vouchers\":\"Moji vau\\u010deri\",\"total_redeemed\":\"Ukupno iskori\\u0161teno\",\"total_issued\":\"Ukupno izdano\",\"no_vouchers_yet\":\"Jo\\u0161 nema izdanih vau\\u010dera.\",\"active_label\":\"Aktivan\",\"valid\":\"ISPRAVAN\",\"valid_msg\":\"Ova posebna ponuda je valjana i mo\\u017ee se iskoristiti.\",\"redeemed_title\":\"ISKORI\\u0160TEN\",\"redeemed_msg\":\"Ponuda uspje\\u0161no iskori\\u0161tena.\",\"redeem_offer_btn\":\"Iskoristi ponudu\",\"scan_next_offer\":\"Skeniraj sljede\\u0107u ponudu\",\"scan_another_qr\":\"Skeniraj drugi QR\",\"redeemed_label\":\"Iskori\\u0161teno\",\"redeemed_by_label\":\"Iskoristio\\\/la\",\"already_used_title\":\"VE\\u0106 ISKORI\\u0160TEN\",\"wrong_location_title\":\"POGRE\\u0160NA LOKACIJA\",\"expired_title\":\"ISTEKAO\",\"invalid_title\":\"NEISPRAVAN\",\"msg_expired\":\"Ova ponuda je istekla i vi\\u0161e nije valjana.\",\"msg_already_used\":\"Ova ponuda je ve\\u0107 iskori\\u0161tena i ne mo\\u017ee se ponovno iskoristiti.\",\"msg_wrong_partner\":\"Ovaj vau\\u010der nije valjan za va\\u0161 ra\\u010dun.\",\"msg_invalid\":\"Ovaj QR kod ne odgovara nijednoj ponudi u na\\u0161em sustavu.\",\"details_label\":\"DETALJI\",\"offer_id_label\":\"ID ponude\",\"date_label\":\"Datum\",\"status_label\":\"Status\",\"scan_again_btn\":\"Skeniraj ponovno\",\"enter_code_manually_btn\":\"Unesi kod ru\\u010dno\",\"back_to_previous\":\"Natrag na prethodni ekran\",\"qr_not_read_title\":\"QR KOD<br>NIJE PRO\\u010cITAN\",\"qr_not_read_msg\":\"Nismo uspjeli pro\\u010ditati ovaj QR kod. Poku\\u0161ajte ponovno.\",\"tips_label\":\"SAVJETI\",\"tips_qr\":\"Provjerite je li QR kod jasan, dobro osvijetljen i neo\\u0161te\\u0107en.\",\"connection_error_title\":\"GRE\\u0160KA<br>VEZE\",\"connection_error_msg\":\"Nismo uspjeli provjeriti ovaj kod. Provjerite internetsku vezu.\",\"tips_network\":\"Provjerite WiFi ili mobilni signal, zatim poku\\u0161ajte ponovno skenirati.\",\"redeem_failed_title\":\"POTVRDA<br>NIJE USPJELA\",\"redeem_failed_msg\":\"Nismo uspjeli obraditi potvrdu. Ponuda jo\\u0161 nije iskori\\u0161tena.\",\"tips_redeem_failed\":\"Provjerite vezu, zatim poku\\u0161ajte ponovno. Ni\\u0161ta nije izgubljeno.\",\"try_again\":\"Poku\\u0161aj ponovno\"};<\/script>        <link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\n        <link href=\"https:\/\/fonts.googleapis.com\/css2?family=Poppins:wght@600;700;800&display=swap\" rel=\"stylesheet\">\n        <style>\n            #osc-v-root, #osc-v-root *{ box-sizing:border-box; }\n            #osc-v-root{\n                --green:#16A34A; --green-dark:#0F5C2E; --red:#C23616;\n                --cream:#FAF9F5; --ink:#1C2620; --muted:#6b6659; --line:#E5E5E5;\n                font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;\n                max-width:420px; margin:0 auto; color:var(--ink); background:#fff;\n            }\n            #osc-v-root .topbar{ background:var(--green-dark); padding:12px 20px; text-align:center; }\n            #osc-v-root .topbar-logo{ font-family:'Poppins',sans-serif; font-size:19px; font-weight:800; }\n            #osc-v-root .topbar-logo .g{ color:var(--green); }\n            #osc-v-root .topbar-logo .w{ color:#fff; }\n            #osc-v-root .topbar-tag{ color:rgba(255,255,255,.85); font-size:11px; margin-top:1px; }\n\n            #osc-v-root .osc-panel{ padding:18px 24px 16px; text-align:center; }\n            #osc-v-root .nika-top-logo{ height:52px; margin:0 auto 4px; display:block; }\n\n            #osc-v-root h2{ font-family:'Poppins',sans-serif; font-size:23px; font-weight:800; color:var(--green-dark); margin:10px 0 2px; }\n            #osc-v-root .sub{ color:var(--muted); font-size:13px; margin-bottom:14px; }\n            #osc-v-root .osc-divider{ height:1px; background:var(--line); margin:0 0 16px; }\n\n            #osc-v-root .lock-circle{\n                width:42px; height:42px; border-radius:50%; background:#EAF3EC; color:var(--green-dark);\n                display:flex; align-items:center; justify-content:center; margin:0 auto 10px;\n            }\n            #osc-v-root .lock-circle svg{ width:19px; height:19px; }\n            #osc-v-root .pin-label{ font-weight:700; font-size:14px; margin-bottom:10px; }\n\n            #osc-v-root input[type=password]{\n                width:100%; padding:13px; font-size:23px; letter-spacing:.6em; text-align:center;\n                border:1px solid #cfe8d8; border-radius:10px; font-family:inherit; color:var(--ink);\n            }\n            #osc-v-root input[type=password]:focus{ outline:none; border-color:var(--green); box-shadow:0 0 0 3px #EAF3EC; }\n            #osc-v-root button{ font-family:inherit; cursor:pointer; border:none; }\n            #osc-v-root .btn-primary{\n                width:100%; margin-top:12px; padding:13px; font-size:15px; font-weight:700;\n                background:var(--green-dark); color:#fff; border-radius:10px;\n                display:flex; align-items:center; justify-content:center; gap:8px;\n            }\n            #osc-v-root .btn-primary svg{ width:17px; height:17px; }\n            #osc-v-root .btn-primary:active{ background:var(--green); }\n            #osc-v-root .err{ color:var(--red); text-align:center; margin-top:8px; font-size:12.5px; min-height:14px; }\n\n            #osc-v-root .bottom-links{\n                border-top:1px solid var(--line); padding:12px 20px; display:flex; align-items:center;\n                justify-content:center; gap:9px; flex-wrap:wrap; font-size:11.5px; color:var(--muted); margin-top:16px;\n            }\n            #osc-v-root .bottom-links a{ color:var(--muted); text-decoration:none; }\n            #osc-v-root .bottom-links .sep{ color:#ccc; }\n            #osc-v-root .bottom-links svg{ width:12px; height:12px; vertical-align:-2px; margin-right:3px; }\n\n            \/* ---- Validator Home (scan ekran) ---- *\/\n            #osc-v-root .home-header{ text-align:center; padding:22px 24px 4px; }\n            #osc-v-root .home-title{ font-family:'Poppins',sans-serif; font-size:26px; font-weight:800; color:var(--green-dark); margin:0; }\n            #osc-v-root .home-underline{ width:44px; height:3px; background:var(--green); border-radius:2px; margin:10px auto 18px; }\n            #osc-v-root .shop-icon{ width:56px; height:56px; color:var(--green-dark); margin:0 auto 10px; }\n            #osc-v-root .home-partner-name{ font-family:'Poppins',sans-serif; font-size:22px; font-weight:800; color:var(--ink); margin:0; }\n            #osc-v-root .home-partner-sub{ color:var(--muted); font-size:13px; margin-top:2px; margin-bottom:20px; }\n\n            #osc-v-root .scan-cta{\n                width:calc(100% - 48px); margin:0 24px; padding:18px; font-size:16.5px; font-weight:800; letter-spacing:.03em; color:#fff;\n                background:var(--green-dark); border-radius:14px; display:flex; align-items:center; justify-content:center; gap:12px;\n                text-transform:uppercase;\n            }\n            #osc-v-root .scan-cta svg{ width:24px; height:24px; }\n            #osc-v-root .scan-helper{ text-align:center; color:var(--muted); font-size:12.5px; line-height:1.5; margin:12px 24px 18px; }\n\n            #osc-v-root #osc-qr-reader{ margin:0 24px 16px; border-radius:14px; overflow:hidden; }\n\n            #osc-v-root .manual-toggle-wrap{ text-align:center; padding:16px 24px 18px; border-top:1px solid var(--line); }\n            #osc-v-root .kbd-circle{\n                width:44px; height:44px; border-radius:50%; background:#EAF3EC; color:var(--green-dark);\n                display:flex; align-items:center; justify-content:center; margin:0 auto 10px;\n            }\n            #osc-v-root .kbd-circle svg{ width:20px; height:20px; }\n            #osc-v-root .cant-scan{ font-weight:700; font-size:14.5px; color:var(--ink); margin-bottom:2px; }\n            #osc-v-root .manual-toggle-link{\n                display:inline-flex; align-items:center; gap:3px; color:var(--green); font-weight:600; font-size:14px;\n                background:none; border:none; cursor:pointer; padding:0;\n            }\n            #osc-v-root .manual-toggle-link svg{ width:14px; height:14px; }\n            #osc-v-root .manual-area{ display:none; margin-top:14px; }\n            #osc-v-root .manual-input{\n                width:100%; padding:12px 14px; font-size:14px; border:1px solid var(--line); border-radius:10px; margin-bottom:8px;\n            }\n            #osc-v-root .btn-secondary{\n                width:100%; padding:12px; font-size:14px; font-weight:700;\n                background:#f1efe9; color:var(--ink); border-radius:10px;\n            }\n\n            #osc-v-root .home-footer{\n                background:#F4F2EC; padding:14px 20px; display:flex; align-items:center; justify-content:space-between;\n            }\n            #osc-v-root .home-footer .who{ display:flex; align-items:center; gap:10px; }\n            #osc-v-root .who-circle{\n                width:34px; height:34px; border-radius:50%; background:#EAF3EC; color:var(--green-dark);\n                display:flex; align-items:center; justify-content:center; flex-shrink:0;\n            }\n            #osc-v-root .who-circle svg{ width:16px; height:16px; }\n            #osc-v-root .who-label{ font-size:11px; color:var(--muted); }\n            #osc-v-root .who-name{ font-size:13px; font-weight:700; color:var(--ink); }\n            #osc-v-root .switch-partner{\n                display:flex; align-items:center; gap:6px; color:var(--green-dark); font-weight:700; font-size:12.5px;\n                background:none; border:none; cursor:pointer; padding-left:14px; border-left:1px solid var(--line);\n            }\n            #osc-v-root .switch-partner svg{ width:15px; height:15px; }\n\n            \/* ---- Tab bar (Scan \/ My Vouchers) ---- *\/\n            #osc-v-root .tab-bar{ display:flex; gap:8px; padding:0 20px 16px; }\n            #osc-v-root .tab-btn{\n                flex:1; display:flex; align-items:center; justify-content:center; gap:6px;\n                padding:10px; border-radius:10px; border:1.5px solid var(--line); background:#fff;\n                color:var(--muted); font-size:12.5px; font-weight:700; cursor:pointer;\n            }\n            #osc-v-root .tab-btn svg{ width:15px; height:15px; }\n            #osc-v-root .tab-btn.active{ background:var(--green-dark); border-color:var(--green-dark); color:#fff; }\n\n            #osc-v-root .vouchers-stats-row{ display:flex; gap:10px; margin:0 20px 14px; }\n            #osc-v-root .vouchers-total-box{\n                flex:1; padding:14px; background:#F1EFE9; border-radius:12px; text-align:center;\n            }\n            #osc-v-root .vouchers-total-box.redeemed-box{ background:#EAF3EC; }\n            #osc-v-root .vouchers-total-label{ font-size:10px; letter-spacing:.05em; text-transform:uppercase; color:var(--muted); margin-bottom:2px; }\n            #osc-v-root .redeemed-box .vouchers-total-label{ color:var(--green-dark); }\n            #osc-v-root .vouchers-total-count{ font-family:'Poppins',sans-serif; font-size:26px; font-weight:800; color:var(--ink); }\n            #osc-v-root .redeemed-box .vouchers-total-count{ color:var(--green-dark); }\n\n            #osc-v-root .vouchers-list{ padding:0 20px; max-height:340px; overflow-y:auto; }\n            #osc-v-root .voucher-row{\n                display:flex; justify-content:space-between; align-items:center;\n                padding:11px 0; border-bottom:1px solid var(--line); font-size:12.5px;\n            }\n            #osc-v-root .voucher-row:last-child{ border-bottom:none; }\n            #osc-v-root .voucher-row.is-redeemed{ background:#F3FAF5; margin:0 -10px; padding:11px 10px; border-radius:8px; border-bottom-color:transparent; }\n            #osc-v-root .voucher-row .vr-offer{ font-weight:700; color:var(--ink); }\n            #osc-v-root .voucher-row .vr-code{ font-family:'SFMono-Regular',Consolas,monospace; font-size:10.5px; color:var(--muted); }\n            #osc-v-root .voucher-row .vr-right{ text-align:right; }\n            #osc-v-root .voucher-row .vr-date{ color:var(--muted); font-size:11px; }\n            #osc-v-root .vr-status{\n                display:inline-block; font-size:9.5px; font-weight:800; letter-spacing:.04em; text-transform:uppercase;\n                padding:3px 8px; border-radius:10px; margin-bottom:3px;\n            }\n            #osc-v-root .vr-status.redeemed{ background:var(--green); color:#fff; }\n            #osc-v-root .vr-status.active{ background:#EAF3EC; color:var(--green-dark); }\n            #osc-v-root .vr-status.expired,\n            #osc-v-root .vr-status.cancelled{ background:#f1efe9; color:var(--muted); }\n            #osc-v-root .vouchers-empty{ text-align:center; color:var(--muted); font-size:13px; padding:30px 20px; }\n            \/* ---- Rezultat ekran (nakon skeniranja) ---- *\/\n            #osc-v-root .result-view{ display:none; }\n            #osc-v-root .result-partner{ text-align:center; padding:20px 24px 4px; }\n            #osc-v-root .result-partner-name{ font-family:Georgia,'Times New Roman',serif; font-size:21px; margin:0; }\n            #osc-v-root .result-partner-loc{ font-family:Georgia,serif; font-size:9.5px; letter-spacing:.2em; color:var(--muted); text-transform:uppercase; margin-top:2px; }\n\n            #osc-v-root .status-card{\n                margin:16px 20px; padding:22px; border-radius:16px; display:flex; align-items:center; gap:16px;\n            }\n            #osc-v-root .status-card.redeemed{\n                flex-direction:column; text-align:center; gap:10px; padding:26px 22px;\n            }\n            #osc-v-root .status-card.ok{ background:var(--green-dark); }\n            #osc-v-root .status-card.redeemed{ background:var(--green); }\n            #osc-v-root .status-card.bad{ background:var(--red); }\n            #osc-v-root .status-icon-circle{\n                width:64px; height:64px; min-width:64px; border-radius:50%; background:#fff;\n                display:flex; align-items:center; justify-content:center;\n            }\n            #osc-v-root .status-card.ok .status-icon-circle svg, #osc-v-root .status-card.redeemed .status-icon-circle svg{ color:var(--green-dark); width:32px; height:32px; }\n            #osc-v-root .status-card.bad .status-icon-circle svg{ color:var(--red); width:32px; height:32px; }\n            #osc-v-root .status-title{ font-family:'Poppins',sans-serif; font-size:32px; font-weight:800; color:#fff; line-height:1; margin-bottom:6px; }\n            #osc-v-root .status-msg{ color:rgba(255,255,255,.9); font-size:13px; line-height:1.4; }\n\n            #osc-v-root .result-offer{ text-align:center; padding:8px 24px 14px; }\n            #osc-v-root .result-offer-value{ font-family:'Poppins',sans-serif; font-size:32px; font-weight:800; color:var(--green); margin:0 0 3px; }\n            #osc-v-root .result-offer-sub{ font-size:14px; color:#333; }\n\n            #osc-v-root .id-row{ display:flex; align-items:center; gap:12px; padding:14px 24px; }\n            #osc-v-root .ticket-circle{\n                width:38px; height:38px; min-width:38px; border-radius:50%; background:#EAF3EC; color:var(--green-dark);\n                display:flex; align-items:center; justify-content:center;\n            }\n            #osc-v-root .ticket-circle svg{ width:18px; height:18px; }\n            #osc-v-root .id-label{ font-size:11px; color:var(--muted); }\n            #osc-v-root .id-value{ font-family:'SFMono-Regular',Consolas,monospace; font-size:15px; font-weight:700; color:var(--green-dark); }\n\n            #osc-v-root .redeem-btn{\n                width:calc(100% - 48px); margin:6px 24px 0; padding:16px; font-size:15.5px; font-weight:800; letter-spacing:.02em;\n                text-transform:uppercase; color:#fff; background:var(--green-dark); border-radius:12px;\n                display:flex; align-items:center; justify-content:center; gap:10px;\n            }\n            #osc-v-root .redeem-btn svg{ width:19px; height:19px; }\n            #osc-v-root .msg-row{ display:flex; align-items:flex-start; gap:12px; padding:6px 22px 20px; }\n            #osc-v-root .msg-icon-circle{\n                width:32px; height:32px; min-width:32px; border-radius:50%; background:#fff; color:var(--red);\n                display:flex; align-items:center; justify-content:center; margin-top:1px;\n            }\n            #osc-v-root .msg-icon-circle svg{ width:16px; height:16px; }\n            #osc-v-root .msg-label{ font-size:13.5px; font-weight:800; color:#fff; margin-bottom:2px; }\n            #osc-v-root .msg-text{ font-size:13px; color:rgba(255,255,255,.92); line-height:1.4; }\n            #osc-v-root .card-inner-divider{ height:1px; background:rgba(255,255,255,.25); margin:0 22px 14px; }\n\n            #osc-v-root .details-box{\n                margin:16px 20px; padding:18px 20px; border-radius:12px; background:#FBEAE7;\n            }\n            #osc-v-root .details-head{ display:flex; align-items:center; gap:8px; margin-bottom:10px; }\n            #osc-v-root .details-head svg{ width:16px; height:16px; color:var(--red); }\n            #osc-v-root .details-head span{ font-size:12px; font-weight:800; color:var(--red); letter-spacing:.05em; }\n            #osc-v-root .details-line{ font-size:13.5px; color:var(--ink); margin-bottom:5px; }\n            #osc-v-root .details-line b{ font-weight:700; }\n            #osc-v-root .details-line .status-val{ color:var(--red); font-weight:800; }\n\n            #osc-v-root .tips-row{ display:flex; align-items:flex-start; gap:12px; padding:16px 24px; }\n            #osc-v-root .tips-icon-circle{\n                width:38px; height:38px; min-width:38px; border-radius:50%; background:#FBE7E3; color:var(--red);\n                display:flex; align-items:center; justify-content:center; margin-top:2px;\n            }\n            #osc-v-root .tips-icon-circle svg{ width:18px; height:18px; }\n            #osc-v-root .tips-label{ font-size:12px; font-weight:800; color:var(--red); letter-spacing:.05em; margin-bottom:3px; }\n            #osc-v-root .tips-text{ font-size:13.5px; color:#333; line-height:1.4; }\n\n            #osc-v-root .btn-red-solid{\n                width:calc(100% - 48px); margin:0 24px 10px; padding:15px; font-size:15px; font-weight:800; letter-spacing:.02em;\n                text-transform:uppercase; color:#fff; background:var(--red); border-radius:12px;\n                display:flex; align-items:center; justify-content:center; gap:10px;\n            }\n            #osc-v-root .btn-red-solid svg{ width:18px; height:18px; }\n            #osc-v-root .btn-red-outline{\n                width:calc(100% - 48px); margin:0 24px 10px; padding:14px; font-size:14px; font-weight:800; letter-spacing:.02em;\n                text-transform:uppercase; color:var(--red); background:#fff; border:1.5px solid var(--red); border-radius:12px;\n                display:flex; align-items:center; justify-content:center; gap:10px;\n            }\n            #osc-v-root .btn-red-outline svg{ width:16px; height:16px; }\n            #osc-v-root .scan-again-link{\n                display:flex; align-items:center; justify-content:center; gap:8px; width:100%; padding:18px;\n                color:var(--green-dark); font-weight:700; font-size:14.5px; background:none; border:none; cursor:pointer;\n            }\n            #osc-v-root .scan-again-link svg{ width:16px; height:16px; }\n        <\/style>\n\n        <div id=\"osc-v-root\">\n\n            <div class=\"topbar\">\n                <div class=\"topbar-logo\"><span class=\"g\">omis<\/span><span class=\"w\">smartcity<\/span>.<span class=\"g\">com<\/span><\/div>\n                <div class=\"topbar-tag\">Get informed. Experience the best.<\/div>\n            <\/div>\n\n            <!-- PIN ekran -->\n            <div id=\"osc-pin-view\">\n                <div class=\"osc-panel\">\n                    <img decoding=\"async\" class=\"nika-top-logo\" src=\"https:\/\/omissmartcity.com\/wp-content\/uploads\/2024\/12\/nika-display-logo.png\" alt=\"NIKA Smart City Solutions\">\n                    <h2>Posebne ponude<\/h2>\n                    <div class=\"sub\">Pristup za partnere<\/div>\n                <\/div>\n                <div class=\"osc-divider\"><\/div>\n                <div class=\"osc-panel\" style=\"padding-top:0;\">\n                    <div class=\"lock-circle\">\n                        <svg viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"5\" y=\"11\" width=\"14\" height=\"9\" rx=\"2\"\/><path d=\"M8 11V7a4 4 0 0 1 8 0v4\"\/><\/svg>\n                    <\/div>\n                    <div class=\"pin-label\">Unesite PIN osoblja<\/div>\n                    <input type=\"password\" id=\"osc-pin-input\" maxlength=\"6\" inputmode=\"numeric\" pattern=\"[0-9]*\" placeholder=\"\">\n                    <button id=\"osc-pin-submit\" class=\"btn-primary\">\n                        <svg viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"5\" y=\"11\" width=\"14\" height=\"9\" rx=\"2\"\/><path d=\"M8 11V7a4 4 0 0 1 8 0v4\"\/><\/svg>\n                        Otklju\u010daj                    <\/button>\n                    <div id=\"osc-pin-error\" class=\"err\"><\/div>\n                <\/div>\n\n                <div class=\"bottom-links\">\n                    <span><svg viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\"\/><path d=\"M3 7l9 6 9-6\"\/><\/svg>info@omissmartcity.com<\/span>\n                    <span class=\"sep\">|<\/span>\n                    <a href=\"#\">Pravila o privatnosti<\/a>\n                    <span class=\"sep\">|<\/span>\n                    <a href=\"#\">Uvjeti i odredbe<\/a>\n                <\/div>\n            <\/div>\n\n            <!-- Scan ekran (Validator Home) -->\n            <div id=\"osc-scan-view\" style=\"display:none;\">\n                <div class=\"home-header\">\n                    <p class=\"home-title\">Posebne ponude<\/p>\n                    <div class=\"home-underline\"><\/div>\n                    <svg class=\"shop-icon\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\"><path d=\"M3 9l1.5-5h15L21 9\"\/><path d=\"M3 9a2 2 0 0 0 4 0 2 2 0 0 0 4 0 2 2 0 0 0 4 0 2 2 0 0 0 4 0\"\/><path d=\"M5 9v10h14V9\"\/><path d=\"M9 19v-6h6v6\"\/><\/svg>\n                    <p class=\"home-partner-name\" id=\"osc-partner-name\"><\/p>\n                    <div class=\"home-partner-sub\">Partnerski ra\u010dun<\/div>\n                <\/div>\n\n                <div class=\"tab-bar\" id=\"osc-tab-bar\" style=\"display:none;\">\n                    <button id=\"osc-tab-scan\" class=\"tab-btn active\">\n                        <svg viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z\"\/><circle cx=\"12\" cy=\"13\" r=\"4\"\/><\/svg>\n                        Skeniraj                    <\/button>\n                    <button id=\"osc-tab-vouchers\" class=\"tab-btn\">\n                        <svg viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\"><path d=\"M3 7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v2a2 2 0 0 0 0 6v2a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-2a2 2 0 0 0 0-6V7z\"\/><\/svg>\n                        Moji vau\u010deri                    <\/button>\n                <\/div>\n\n                <div id=\"osc-scan-tab-content\">\n                <button id=\"osc-start-scan\" class=\"scan-cta\">\n                    <svg viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M3 7V5a2 2 0 0 1 2-2h2M17 3h2a2 2 0 0 1 2 2v2M21 17v2a2 2 0 0 1-2 2h-2M7 21H5a2 2 0 0 1-2-2v-2\"\/><rect x=\"9\" y=\"9\" width=\"6\" height=\"6\"\/><\/svg>\n                    Skeniraj QR kod                <\/button>\n                <p class=\"scan-helper\">Usmjerite kameru na QR kod gosta kako biste provjerili i iskoristili ponudu.<\/p>\n                <div id=\"osc-qr-reader\"><\/div>\n\n                <div class=\"manual-toggle-wrap\">\n                    <div class=\"kbd-circle\">\n                        <svg viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\"><rect x=\"2\" y=\"6\" width=\"20\" height=\"12\" rx=\"2\"\/><path d=\"M6 10h.01M10 10h.01M14 10h.01M18 10h.01M6 14h12\" stroke-linecap=\"round\"\/><\/svg>\n                    <\/div>\n                    <div class=\"cant-scan\">Ne mo\u017eete skenirati?<\/div>\n                    <button id=\"osc-manual-toggle\" class=\"manual-toggle-link\">\n                        Unesite kod ru\u010dno                        <svg viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"><path d=\"M9 6l6 6-6 6\"\/><\/svg>\n                    <\/button>\n\n                    <div class=\"manual-area\" id=\"osc-manual-area\">\n                        <input type=\"text\" id=\"osc-manual-token\" class=\"manual-input\" placeholder=\"Zalijepi token ili skenirani URL\">\n                        <button id=\"osc-manual-check\" class=\"btn-secondary\">Provjeri vau\u010der<\/button>\n                    <\/div>\n                <\/div>\n                <\/div>\n\n                <div id=\"osc-vouchers-tab-content\" style=\"display:none;\">\n                    <div class=\"vouchers-stats-row\">\n                        <div class=\"vouchers-total-box\">\n                            <div class=\"vouchers-total-label\">Ukupno izdano<\/div>\n                            <div class=\"vouchers-total-count\" id=\"osc-vouchers-total-issued\">\u2014<\/div>\n                        <\/div>\n                        <div class=\"vouchers-total-box redeemed-box\">\n                            <div class=\"vouchers-total-label\">Ukupno iskori\u0161teno<\/div>\n                            <div class=\"vouchers-total-count\" id=\"osc-vouchers-total-redeemed\">\u2014<\/div>\n                        <\/div>\n                    <\/div>\n                    <div id=\"osc-vouchers-list\" class=\"vouchers-list\"><\/div>\n                <\/div>\n\n                <div class=\"home-footer\">\n                    <div class=\"who\">\n                        <div class=\"who-circle\">\n                            <svg viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><circle cx=\"12\" cy=\"8\" r=\"4\"\/><path d=\"M4 20c0-4 4-6 8-6s8 2 8 6\"\/><\/svg>\n                        <\/div>\n                        <div>\n                            <div class=\"who-label\">Prijavljeni kao<\/div>\n                            <div class=\"who-name\" id=\"osc-who-name\"><\/div>\n                        <\/div>\n                    <\/div>\n                    <button id=\"osc-logout\" class=\"switch-partner\">\n                        <svg viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M17 2l4 4-4 4\"\/><path d=\"M3 11V9a4 4 0 0 1 4-4h14\"\/><path d=\"M7 22l-4-4 4-4\"\/><path d=\"M21 13v2a4 4 0 0 1-4 4H3\"\/><\/svg>\n                        Promijeni partnera                    <\/button>\n                <\/div>\n            <\/div>\n\n            <!-- Rezultat skeniranja -->\n            <div id=\"osc-result-view\" class=\"result-view\">\n                <div class=\"result-partner\">\n                    <p class=\"result-partner-name\" id=\"osc-result-partner-name\"><\/p>\n                    <div class=\"result-partner-loc\">\u2022 Omi\u0161 \u2022<\/div>\n                <\/div>\n                <div id=\"osc-result-body\"><\/div>\n            <\/div>\n        <\/div>\n\n        <script>\n        (function () {\n            var T = OSC_I18N_JS;\n            var restBase = 'https:\/\/omissmartcity.com\/hr\/wp-json\/osc\/v1\/';\n            var pinView = document.getElementById('osc-pin-view');\n            var scanView = document.getElementById('osc-scan-view');\n            var resultView = document.getElementById('osc-result-view');\n            var resultBody = document.getElementById('osc-result-body');\n            var currentToken = null;\n            var qrReader = null;\n\n            \/**\n             * Stranica je uvijek servirana s neutralnim (PIN) pocetnim stanjem u HTML-u,\n             * kako bi bila potpuno cache-safe (Kinsta i sl. full-page cache ne mogu\n             * servirati \"tudi\" ulogiran prikaz). Stvarno stanje (ulogiran\/nije) se\n             * provjerava ovdje, na klijentu, pri svakom ucitavanju stranice.\n             *\/\n            function checkSession() {\n                \/\/ ?logout=1 u URL-u uvijek prisiljava PIN ekran - koristan bookmark\/link za\n                \/\/ slucajeve kad \"Promijeni partnera\" gumb ne odradi posao u nekim preglednicima\n                var forceLogout = \/[?&]logout=1\\b\/.test(window.location.search);\n                if (forceLogout) {\n                    document.cookie = 'osc_validator_session=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=\/;';\n                    fetch(restBase + 'validator\/logout', { method: 'POST' }).catch(function () {});\n                    pinView.style.display = 'block';\n                    scanView.style.display = 'none';\n                    return;\n                }\n\n                fetch(restBase + 'validator\/session')\n                    .then(function (r) { return r.json(); })\n                    .then(function (data) {\n                        if (data.logged_in) {\n                            document.getElementById('osc-partner-name').textContent = data.partner_name;\n                            document.getElementById('osc-who-name').textContent = data.partner_name;\n                            var resultNameEl = document.getElementById('osc-result-partner-name');\n                            if (resultNameEl) resultNameEl.textContent = data.partner_name;\n                            var tabBar = document.getElementById('osc-tab-bar');\n                            if (tabBar) tabBar.style.display = (data.role === 'owner') ? 'flex' : 'none';\n                            pinView.style.display = 'none';\n                            scanView.style.display = 'block';\n                        } else {\n                            pinView.style.display = 'block';\n                            scanView.style.display = 'none';\n                        }\n                    })\n                    .catch(function () { \/* ostaje na PIN ekranu ako provjera ne uspije *\/ });\n            }\n            checkSession();\n\n            var ICONS = {\n                ok: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\"><path d=\"M5 13l4 4L19 7\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg>',\n                bad: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\"><path d=\"M6 6l12 12M18 6L6 18\" stroke-linecap=\"round\"\/><\/svg>',\n                clock: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\"><circle cx=\"12\" cy=\"12\" r=\"9\"\/><path d=\"M12 7v5l3 2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg>',\n                warn: '<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" stroke=\"none\"><path d=\"M12 2L1 21h22L12 2z\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linejoin=\"round\"\/><path d=\"M12 9v5\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\"\/><circle cx=\"12\" cy=\"17\" r=\"1.1\"\/><\/svg>'\n            };\n\n            function showResult(status, data) {\n                scanView.style.display = 'none';\n                resultView.style.display = 'block';\n                data = data || {};\n\n                if (status === 'VALID' || status === 'REDEEM_SUCCESS') {\n                    renderPositive(status, data);\n                } else if (status === 'SCAN_TIMEOUT' || status === 'NETWORK_ERROR') {\n                    renderScanFailed(status);\n                } else if (status === 'REDEEM_FAILED') {\n                    renderRedeemFailed();\n                } else {\n                    renderProblem(status, data);\n                }\n            }\n\n            function renderPositive(status, data) {\n                var isRedeemSuccess = status === 'REDEEM_SUCCESS';\n                var cardClass = isRedeemSuccess ? 'redeemed' : 'ok';\n                var title = isRedeemSuccess ? T.redeemed_title : T.valid;\n                var msg = isRedeemSuccess ? T.redeemed_msg : T.valid_msg;\n\n                var html = '<div class=\"status-card ' + cardClass + '\">'\n                          + '<div class=\"status-icon-circle\">' + ICONS.ok + '<\/div>'\n                          + '<div><div class=\"status-title\">' + title + '<\/div><div class=\"status-msg\">' + msg + '<\/div><\/div>'\n                          + '<\/div>'\n                          + '<div class=\"result-offer\">'\n                          + '<div class=\"result-offer-value\">' + (data.offer_title || '') + '<\/div>'\n                          + (data.offer_value ? '<div class=\"result-offer-sub\">' + data.offer_value + '<\/div>' : (data.offer_subtitle ? '<div class=\"result-offer-sub\">' + data.offer_subtitle + '<\/div>' : ''))\n                          + '<\/div>'\n                          + '<div class=\"osc-divider\" style=\"margin:0 20px;\"><\/div>'\n                          + '<div class=\"id-row\">'\n                          + '<div class=\"ticket-circle\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\"><path d=\"M3 7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v2a2 2 0 0 0 0 6v2a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-2a2 2 0 0 0 0-6V7z\"\/><path d=\"M12 6v2M12 11v2M12 16v2\" stroke-linecap=\"round\"\/><\/svg><\/div>'\n                          + '<div><div class=\"id-label\">' + T.smart_offer_id + '<\/div><div class=\"id-value\">' + (data.voucher_code || '') + '<\/div><\/div>'\n                          + '<\/div>';\n\n                if (isRedeemSuccess) {\n                    html += '<div class=\"osc-divider\" style=\"margin:0 20px;\"><\/div>'\n                          + '<div class=\"id-row\">'\n                          + '<div class=\"ticket-circle\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\"><rect x=\"3\" y=\"4\" width=\"18\" height=\"17\" rx=\"2\"\/><path d=\"M3 9h18M8 2v4M16 2v4\" stroke-linecap=\"round\"\/><\/svg><\/div>'\n                          + '<div><div class=\"id-label\">' + T.redeemed_label + '<\/div><div class=\"id-value\" style=\"color:var(--ink);font-family:inherit;font-weight:700;font-size:14px;\">' + (data.redeemed_at || '') + '<\/div><\/div>'\n                          + '<\/div>'\n                          + '<div class=\"osc-divider\" style=\"margin:0 20px;\"><\/div>'\n                          + '<div class=\"id-row\">'\n                          + '<div class=\"ticket-circle\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\"><circle cx=\"12\" cy=\"8\" r=\"4\"\/><path d=\"M4 20c0-4 4-6 8-6s8 2 8 6\"\/><\/svg><\/div>'\n                          + '<div><div class=\"id-label\">' + T.redeemed_by_label + '<\/div><div class=\"id-value\" style=\"color:var(--ink);font-family:inherit;font-weight:700;font-size:14px;\">' + (data.redeemed_by || '') + '<\/div><\/div>'\n                          + '<\/div>'\n                          + '<div class=\"osc-divider\" style=\"margin:0 20px;\"><\/div>'\n                          + '<button id=\"osc-scan-next\" class=\"redeem-btn\">'\n                          + '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z\"\/><circle cx=\"12\" cy=\"13\" r=\"4\"\/><\/svg>'\n                          + T.scan_next_offer + '<\/button>';\n                } else {\n                    html += '<div class=\"osc-divider\" style=\"margin:0 20px;\"><\/div>'\n                          + '<button id=\"osc-redeem-btn\" class=\"redeem-btn\">'\n                          + '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"3\" y=\"8\" width=\"18\" height=\"4\"\/><path d=\"M12 8v13M19 12v7a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-7\"\/><path d=\"M7.5 8a2.5 2.5 0 0 1 0-5C11 3 12 8 12 8s1-5 4.5-5a2.5 2.5 0 0 1 0 5\"\/><\/svg>'\n                          + T.redeem_offer_btn + '<\/button>';\n                }\n                html += '<button id=\"osc-scan-again\" class=\"scan-again-link\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"><path d=\"M19 12H5M11 18l-6-6 6-6\"\/><\/svg>' + T.scan_another_qr + '<\/button>';\n                resultBody.innerHTML = html;\n            }\n\n            \/**\n             * Zajedni\u010dki prikaz za sve statuse koje je BACKEND potvrdio kao nevaljane\n             * (istekao, iskori\u0161ten, ne postoji, pogre\u0161an partner) - dinami\u010dka poruka\n             * + Details box (Offer ID \/ Date \/ Status) prema stvarnim podacima iz baze.\n             *\/\n            function renderProblem(status, data) {\n                var titleMap = {\n                    EXPIRED: T.expired_title,\n                    ALREADY_USED: T.already_used_title,\n                    REDEEMED: T.already_used_title,\n                    WRONG_PARTNER: T.wrong_location_title,\n                    INVALID: T.invalid_title,\n                    not_found: T.invalid_title\n                };\n                var messageMap = {\n                    EXPIRED: T.msg_expired,\n                    ALREADY_USED: T.msg_already_used,\n                    REDEEMED: T.msg_already_used,\n                    WRONG_PARTNER: T.msg_wrong_partner,\n                    INVALID: T.msg_invalid\n                };\n                var title = titleMap[status] || T.invalid_title;\n                var message = messageMap[status] || messageMap.INVALID;\n                var now = new Date();\n                var dateStr = now.toLocaleDateString('en-GB', { day:'2-digit', month:'short', year:'numeric' }) + ', ' + now.toLocaleTimeString('en-GB', { hour:'2-digit', minute:'2-digit' });\n\n                var html = '<div class=\"status-card bad\">'\n                          + '<div class=\"status-icon-circle\">' + ICONS.warn + '<\/div>'\n                          + '<div><div class=\"status-title\">' + title + '<\/div><div class=\"status-msg\">' + message + '<\/div><\/div>'\n                          + '<\/div>';\n\n                html += '<div class=\"details-box\">'\n                      + '<div class=\"details-head\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><circle cx=\"12\" cy=\"12\" r=\"10\"\/><path d=\"M12 16v-4M12 8h.01\"\/><\/svg><span>' + T.details_label + '<\/span><\/div>'\n                      + (data.voucher_code ? '<div class=\"details-line\"><b>' + T.offer_id_label + ':<\/b> ' + data.voucher_code + '<\/div>' : '')\n                      + '<div class=\"details-line\"><b>' + T.date_label + ':<\/b> ' + (data.redeemed_at || dateStr) + '<\/div>'\n                      + '<div class=\"details-line\"><b>' + T.status_label + ':<\/b> <span class=\"status-val\">' + title + '<\/span><\/div>'\n                      + '<\/div>';\n\n                html += '<button id=\"osc-scan-next\" class=\"btn-red-solid\" style=\"margin-top:6px;\">'\n                      + '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M3 7V5a2 2 0 0 1 2-2h2M17 3h2a2 2 0 0 1 2 2v2M21 17v2a2 2 0 0 1-2 2h-2M7 21H5a2 2 0 0 1-2-2v-2\"\/><rect x=\"9\" y=\"9\" width=\"6\" height=\"6\"\/><\/svg>'\n                      + T.scan_again_btn + '<\/button>'\n                      + '<button id=\"osc-manual-enter\" class=\"btn-red-outline\">'\n                      + '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\"><rect x=\"2\" y=\"6\" width=\"20\" height=\"12\" rx=\"2\"\/><path d=\"M6 10h.01M10 10h.01M14 10h.01M18 10h.01M6 14h12\" stroke-linecap=\"round\"\/><\/svg>'\n                      + T.enter_code_manually_btn + '<\/button>'\n                      + '<button id=\"osc-scan-again\" class=\"scan-again-link\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"><path d=\"M19 12H5M11 18l-6-6 6-6\"\/><\/svg>' + T.back_to_previous + '<\/button>';\n\n                resultBody.innerHTML = html;\n            }\n\n            \/** Gre\u0161ka prilikom REDEEM koraka (ne scan\/validate) - nudi ponovni poku\u0161aj s istim tokenom, ne novo skeniranje *\/\n            function renderRedeemFailed() {\n                var html = '<div class=\"status-card bad\">'\n                          + '<div class=\"status-icon-circle\">' + ICONS.warn + '<\/div>'\n                          + '<div><div class=\"status-title\">' + T.redeem_failed_title + '<\/div><div class=\"status-msg\">' + T.redeem_failed_msg + '<\/div><\/div>'\n                          + '<\/div>'\n                          + '<div class=\"osc-divider\" style=\"margin:0 20px;\"><\/div>'\n                          + '<div class=\"tips-row\">'\n                          + '<div class=\"tips-icon-circle\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\"><path d=\"M9 18h6M10 22h4M12 2a6 6 0 0 0-4 10.5c.6.6 1 1.4 1 2.5h6c0-1.1.4-1.9 1-2.5A6 6 0 0 0 12 2z\"\/><\/svg><\/div>'\n                          + '<div><div class=\"tips-label\">' + T.tips_label + '<\/div><div class=\"tips-text\">' + T.tips_redeem_failed + '<\/div><\/div>'\n                          + '<\/div>'\n                          + '<div class=\"osc-divider\" style=\"margin:0 20px;\"><\/div>'\n                          + '<button id=\"osc-retry-redeem\" class=\"btn-red-solid\" style=\"margin-top:16px;\">'\n                          + '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M23 4v6h-6M1 20v-6h6\"\/><path d=\"M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15\"\/><\/svg>'\n                          + T.try_again + '<\/button>'\n                          + '<button id=\"osc-scan-again\" class=\"scan-again-link\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"><path d=\"M19 12H5M11 18l-6-6 6-6\"\/><\/svg>' + T.scan_another_qr + '<\/button>';\n                resultBody.innerHTML = html;\n            }\n            function renderScanFailed(reason) {\n                var isNetwork = reason === 'NETWORK_ERROR';\n                var title = isNetwork ? T.connection_error_title : T.qr_not_read_title;\n                var msg = isNetwork\n                    ? T.connection_error_msg\n                    : T.qr_not_read_msg;\n                var tipsText = isNetwork\n                    ? T.tips_network\n                    : T.tips_qr;\n\n                var html = '<div class=\"status-card bad\">'\n                          + '<div class=\"status-icon-circle\">' + ICONS.warn + '<\/div>'\n                          + '<div><div class=\"status-title\">' + title + '<\/div><div class=\"status-msg\">' + msg + '<\/div><\/div>'\n                          + '<\/div>'\n                          + '<div class=\"osc-divider\" style=\"margin:0 20px;\"><\/div>'\n                          + '<div class=\"tips-row\">'\n                          + '<div class=\"tips-icon-circle\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\"><path d=\"M9 18h6M10 22h4M12 2a6 6 0 0 0-4 10.5c.6.6 1 1.4 1 2.5h6c0-1.1.4-1.9 1-2.5A6 6 0 0 0 12 2z\"\/><\/svg><\/div>'\n                          + '<div><div class=\"tips-label\">' + T.tips_label + '<\/div><div class=\"tips-text\">' + tipsText + '<\/div><\/div>'\n                          + '<\/div>'\n                          + '<div class=\"osc-divider\" style=\"margin:0 20px;\"><\/div>'\n                          + '<button id=\"osc-scan-next\" class=\"btn-red-solid\" style=\"margin-top:16px;\">'\n                          + '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M3 7V5a2 2 0 0 1 2-2h2M17 3h2a2 2 0 0 1 2 2v2M21 17v2a2 2 0 0 1-2 2h-2M7 21H5a2 2 0 0 1-2-2v-2\"\/><rect x=\"9\" y=\"9\" width=\"6\" height=\"6\"\/><\/svg>'\n                          + T.scan_again_btn + '<\/button>'\n                          + '<button id=\"osc-manual-enter\" class=\"btn-red-outline\">'\n                          + '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\"><rect x=\"2\" y=\"6\" width=\"20\" height=\"12\" rx=\"2\"\/><path d=\"M6 10h.01M10 10h.01M14 10h.01M18 10h.01M6 14h12\" stroke-linecap=\"round\"\/><\/svg>'\n                          + T.enter_code_manually_btn + '<\/button>'\n                          + '<button id=\"osc-scan-again\" class=\"scan-again-link\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"><path d=\"M19 12H5M11 18l-6-6 6-6\"\/><\/svg>' + T.scan_another_qr + '<\/button>';\n                resultBody.innerHTML = html;\n            }\n\n            document.getElementById('osc-pin-submit').addEventListener('click', submitPin);\n            document.getElementById('osc-pin-input').addEventListener('keydown', function (e) {\n                if (e.key === 'Enter') submitPin();\n            });\n\n            function submitPin() {\n                var pin = document.getElementById('osc-pin-input').value.trim();\n                var errEl = document.getElementById('osc-pin-error');\n                errEl.textContent = '';\n                if (!\/^\\d{6}$\/.test(pin)) { errEl.textContent = T.enter_6_digits; return; }\n                fetch(restBase + 'validator\/login', {\n                    method: 'POST',\n                    headers: { 'Content-Type': 'application\/json' },\n                    body: JSON.stringify({ pin: pin })\n                })\n                .then(function (r) { return r.json().then(function (d) { return { ok: r.ok, data: d }; }); })\n                .then(function (res) {\n                    if (!res.ok) { errEl.textContent = T.incorrect_pin; return; }\n                    document.getElementById('osc-partner-name').textContent = res.data.partner_name;\n                    var tabBar = document.getElementById('osc-tab-bar');\n                    if (tabBar) tabBar.style.display = (res.data.role === 'owner') ? 'flex' : 'none';\n                    pinView.style.display = 'none';\n                    scanView.style.display = 'block';\n                })\n                .catch(function () { errEl.textContent = T.something_wrong; });\n            }\n\n            var manualToggle = document.getElementById('osc-manual-toggle');\n            if (manualToggle) {\n                manualToggle.addEventListener('click', function () {\n                    var area = document.getElementById('osc-manual-area');\n                    area.style.display = area.style.display === 'block' ? 'none' : 'block';\n                });\n            }\n\n            \/\/ ---- Tab bar: Scan \/ My Vouchers ----\n            var tabScan = document.getElementById('osc-tab-scan');\n            var tabVouchers = document.getElementById('osc-tab-vouchers');\n            var scanTabContent = document.getElementById('osc-scan-tab-content');\n            var vouchersTabContent = document.getElementById('osc-vouchers-tab-content');\n            var vouchersLoaded = false;\n\n            if (tabScan && tabVouchers) {\n                tabScan.addEventListener('click', function () {\n                    tabScan.classList.add('active');\n                    tabVouchers.classList.remove('active');\n                    scanTabContent.style.display = 'block';\n                    vouchersTabContent.style.display = 'none';\n                });\n                tabVouchers.addEventListener('click', function () {\n                    tabVouchers.classList.add('active');\n                    tabScan.classList.remove('active');\n                    scanTabContent.style.display = 'none';\n                    vouchersTabContent.style.display = 'block';\n                    stopActiveScan(); \/\/ prekida kameru\/timeout ako je skeniranje bilo u tijeku\n                    if (!vouchersLoaded) loadVouchers();\n                });\n            }\n\n            function loadVouchers() {\n                var listEl = document.getElementById('osc-vouchers-list');\n                var issuedEl = document.getElementById('osc-vouchers-total-issued');\n                var redeemedEl = document.getElementById('osc-vouchers-total-redeemed');\n                listEl.innerHTML = '<div class=\"vouchers-empty\">\u2026<\/div>';\n                fetch(restBase + 'partner\/redemptions', { credentials: 'same-origin' })\n                    .then(function (r) {\n                        return r.json().then(function (data) { return { ok: r.ok, status: r.status, data: data }; });\n                    })\n                    .then(function (res) {\n                        vouchersLoaded = true;\n                        if (!res.ok) {\n                            var errMsg = (res.data && res.data.message) ? res.data.message : ('HTTP ' + res.status);\n                            listEl.innerHTML = '<div class=\"vouchers-empty\">' + T.something_wrong + '<br><small style=\"opacity:.6;\">(' + errMsg + ')<\/small><\/div>';\n                            return;\n                        }\n                        var data = res.data;\n                        issuedEl.textContent = data.total_issued || 0;\n                        redeemedEl.textContent = data.total_redeemed || 0;\n                        if (!data.items || !data.items.length) {\n                            listEl.innerHTML = '<div class=\"vouchers-empty\">' + T.no_vouchers_yet + '<\/div>';\n                            return;\n                        }\n                        var statusLabels = {\n                            redeemed: T.redeemed_label || 'Iskori\u0161ten',\n                            active: T.active_label || 'Aktivan',\n                            expired: T.expired_title || 'Istekao',\n                            cancelled: T.cancelled || 'Otkazan'\n                        };\n                        var html = '';\n                        data.items.forEach(function (v) {\n                            var isRedeemed = v.status === 'redeemed';\n                            var statusText = statusLabels[v.status] || v.status;\n                            html += '<div class=\"voucher-row' + (isRedeemed ? ' is-redeemed' : '') + '\">'\n                                  + '<div><div class=\"vr-offer\">' + v.offer_title + '<\/div><div class=\"vr-code\">' + v.voucher_code + '<\/div><\/div>'\n                                  + '<div class=\"vr-right\"><span class=\"vr-status ' + v.status + '\">' + statusText + '<\/span><div class=\"vr-date\">' + v.date + '<\/div><\/div>'\n                                  + '<\/div>';\n                        });\n                        listEl.innerHTML = html;\n                    })\n                    .catch(function () {\n                        listEl.innerHTML = '<div class=\"vouchers-empty\">' + T.something_wrong + '<\/div>';\n                    });\n            }\n\n            document.getElementById('osc-logout').addEventListener('click', function () {\n                \/\/ Client-side brisanje cookieja - pouzdano, ne ovisi o server-side setcookie() headers timingu\n                document.cookie = 'osc_validator_session=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=\/;';\n                fetch(restBase + 'validator\/logout', { method: 'POST' })\n                    .then(function () { window.location.href = window.location.href.split('?')[0]; })\n                    .catch(function () { window.location.href = window.location.href.split('?')[0]; });\n            });\n\n            function extractToken(raw) {\n                var match = raw.match(\/voucher\\\/([a-zA-Z0-9\\-_]+)\\\/validate\/);\n                return match ? match[1] : raw.trim();\n            }\n\n            function checkToken(raw) {\n                currentToken = extractToken(raw);\n                fetch(restBase + 'voucher\/' + encodeURIComponent(currentToken) + '\/validate')\n                    .then(function (r) { return r.json(); })\n                    .then(function (data) { showResult(data.status, data); })\n                    .catch(function () { showResult('NETWORK_ERROR', {}); });\n            }\n\n            document.getElementById('osc-manual-check').addEventListener('click', function () {\n                var val = document.getElementById('osc-manual-token').value.trim();\n                if (val) checkToken(val);\n            });\n\n            var scanTimeoutId = null;\n\n            \/** Prekida aktivnu kameru i timeout - poziva se pri prelasku na drugi tab da se izbjegne \"SCAN_TIMEOUT\" gre\u0161ka u pozadini *\/\n            function stopActiveScan() {\n                clearTimeout(scanTimeoutId);\n                scanTimeoutId = null;\n                if (qrReader) {\n                    try {\n                        qrReader.stop().catch(function () {});\n                    } catch (e) {}\n                    qrReader = null;\n                }\n                var startBtn = document.getElementById('osc-start-scan');\n                if (startBtn) startBtn.style.display = 'flex';\n                var readerDiv = document.getElementById('osc-qr-reader');\n                if (readerDiv) readerDiv.innerHTML = '';\n            }\n\n            function startCamera() {\n                var btn = document.getElementById('osc-start-scan');\n                btn.style.display = 'none';\n                var readerDiv = document.getElementById('osc-qr-reader');\n                qrReader = new Html5Qrcode('osc-qr-reader');\n\n                clearTimeout(scanTimeoutId);\n                scanTimeoutId = setTimeout(function () {\n                    if (qrReader) {\n                        qrReader.stop().then(function () {\n                            showResult('SCAN_TIMEOUT', {});\n                        }).catch(function () {});\n                    }\n                }, 25000); \/\/ 25s bez uspjeha -> QR CODE NOT READ ekran\n\n                qrReader.start(\n                    { facingMode: 'environment' },\n                    { fps: 10, qrbox: 250 },\n                    function (decodedText) {\n                        clearTimeout(scanTimeoutId);\n                        qrReader.stop().then(function () { checkToken(decodedText); });\n                    }\n                ).catch(function () {\n                    clearTimeout(scanTimeoutId);\n                    readerDiv.innerHTML = '<p style=\"color:#C23616;text-align:center;\">Camera not available. Use manual entry below.<\/p>';\n                    btn.style.display = 'flex';\n                });\n            }\n\n            document.getElementById('osc-start-scan').addEventListener('click', startCamera);\n\n            function resetToScanView() {\n                stopActiveScan();\n                resultView.style.display = 'none';\n                scanView.style.display = 'block';\n                document.getElementById('osc-manual-token').value = '';\n            }\n\n            function attemptRedeem() {\n                fetch(restBase + 'voucher\/' + encodeURIComponent(currentToken) + '\/redeem', { method: 'POST' })\n                    .then(function (r) { return r.json(); })\n                    .then(function (data) { showResult(data.status, data); })\n                    .catch(function () { showResult('REDEEM_FAILED', {}); });\n            }\n\n            document.addEventListener('click', function (e) {\n                if (e.target.closest('#osc-redeem-btn')) {\n                    attemptRedeem();\n                }\n                if (e.target.closest('#osc-retry-redeem')) {\n                    attemptRedeem();\n                }\n                if (e.target.closest('#osc-scan-next')) {\n                    resetToScanView();\n                    startCamera(); \/\/ odmah otvara kameru, bez dodatnog klika\n                }\n                if (e.target.closest('#osc-scan-again')) {\n                    resetToScanView(); \/\/ samo vra\u0107a na home ekran, kamera se ne pokre\u0107e automatski\n                }\n                if (e.target.closest('#osc-manual-enter')) {\n                    resetToScanView();\n                    var area = document.getElementById('osc-manual-area');\n                    area.style.display = 'block';\n                    document.getElementById('osc-manual-token').focus();\n                }\n            });\n        })();\n        <\/script>\n        <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"_monsterinsights_skip_tracking":false,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"class_list":["post-5962","page","type-page","status-publish","hentry"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/omissmartcity.com\/hr\/wp-json\/wp\/v2\/pages\/5962","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/omissmartcity.com\/hr\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/omissmartcity.com\/hr\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/omissmartcity.com\/hr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/omissmartcity.com\/hr\/wp-json\/wp\/v2\/comments?post=5962"}],"version-history":[{"count":0,"href":"https:\/\/omissmartcity.com\/hr\/wp-json\/wp\/v2\/pages\/5962\/revisions"}],"wp:attachment":[{"href":"https:\/\/omissmartcity.com\/hr\/wp-json\/wp\/v2\/media?parent=5962"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}