{"id":7,"date":"2026-10-26T20:58:01","date_gmt":"2026-10-26T20:58:01","guid":{"rendered":"https:\/\/rezultati.ppf.unsa.ba\/?page_id=7"},"modified":"2026-10-26T21:17:07","modified_gmt":"2026-10-26T21:17:07","slug":"predaja-rezultata-ispita","status":"publish","type":"page","link":"https:\/\/rezultati.ppf.unsa.ba\/?page_id=7","title":{"rendered":"Predaja rezultata ispita"},"content":{"rendered":"<p><!DOCTYPE html><br \/>\n<html lang=\"bs\"><br \/>\n<head><br \/>\n<meta charset=\"UTF-8\"><br \/>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><br \/>\n<title>Obrazac za objavu rezultata ispita | PPF UNSA<\/title><\/p>\n<style>\n:root {\n    --green: #285A37;\n    --green-light: #3f7960;\n    --green-soft: #edf4ee;\n    --border: #cbd5ce;\n    --text: #25332a;\n    --muted: #66736a;\n}<\/p>\n<p>* { box-sizing: border-box; }<\/p>\n<p>body {\n    margin: 0;\n    padding: 24px;\n    background: #eef1ee;\n    color: var(--text);\n    font-family: Arial, Helvetica, sans-serif;\n    font-size: 14px;\n}<\/p>\n<p>.page {\n    width: 100%;\n    max-width: 1100px;\n    margin: 0 auto;\n    background: #fff;\n    border: 1px solid #dce3dd;\n    border-radius: 8px;\n    box-shadow: 0 5px 22px rgba(20,45,27,.09);\n    overflow: hidden;\n}<\/p>\n<p>.page-header {\n    padding: 22px 28px;\n    border-bottom: 4px solid var(--green);\n}<\/p>\n<p>.logo-row {\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    gap: 24px;\n    margin-bottom: 20px;\n}<\/p>\n<p>.logo {\n    display: block;\n    max-width: 155px;\n    max-height: 90px;\n    width: auto;\n    height: auto;\n    object-fit: contain;\n}<\/p>\n<p>.logo-unsa { max-width: 125px; }<\/p>\n<p>.header-text {\n    text-align: center;\n    color: var(--green);\n    line-height: 1.55;\n}<\/p>\n<p>.header-text .university {\n    font-weight: 700;\n    font-size: 15px;\n    text-transform: uppercase;\n}<\/p>\n<p>.header-text .faculty {\n    font-weight: 700;\n    font-size: 18px;\n    text-transform: uppercase;\n}<\/p>\n<p>.header-text .document-title {\n    margin-top: 9px;\n    font-size: 16px;\n    font-weight: 700;\n    letter-spacing: .35px;\n}<\/p>\n<p>.content { padding: 24px 28px 28px; }<\/p>\n<p>.section-title {\n    margin: 0 0 15px;\n    padding-bottom: 8px;\n    border-bottom: 1px solid var(--border);\n    color: var(--green);\n    font-size: 15px;\n    font-weight: 700;\n}<\/p>\n<p>.general-grid {\n    display: grid;\n    grid-template-columns: repeat(2,minmax(0,1fr));\n    gap: 14px 20px;\n    margin-bottom: 25px;\n}<\/p>\n<p>.field {\n    display: flex;\n    flex-direction: column;\n    gap: 6px;\n    min-width: 0;\n}<\/p>\n<p>.field label {\n    font-size: 12px;\n    font-weight: 700;\n    color: #4d5b51;\n}<\/p>\n<p>input, select, textarea {\n    width: 100%;\n    min-width: 0;\n    padding: 10px 11px;\n    border: 1px solid #cbd5ce;\n    border-radius: 4px;\n    background: #fff;\n    color: #25332a;\n    font: inherit;\n}<\/p>\n<p>input:focus, select:focus, textarea:focus {\n    outline: 2px solid rgba(63,121,96,.2);\n    border-color: var(--green-light);\n}<\/p>\n<p>input::placeholder, textarea::placeholder { color: #a0aaa2; }<\/p>\n<p>input[readonly] {\n    background: #f7f9f7;\n    color: #4d5b51;\n}<\/p>\n<p>input:invalid:not(:placeholder-shown),\nselect:invalid,\ntextarea:invalid {\n    border-color: #c0392b;\n}<\/p>\n<p>.field.full { grid-column: 1 \/ -1; }<\/p>\n<p>.table-heading {\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    gap: 12px;\n    margin-bottom: 12px;\n}<\/p>\n<p>.table-heading .section-title {\n    flex: 1;\n    margin: 0;\n}<\/p>\n<p>.table-wrap { width: 100%; overflow-x: auto; }<\/p>\n<p>table {\n    width: 100%;\n    border-collapse: collapse;\n    table-layout: fixed;\n}<\/p>\n<p>th, td {\n    border: 1px solid #cbd5ce;\n    padding: 7px;\n    text-align: center;\n    vertical-align: middle;\n}<\/p>\n<p>thead th {\n    background: var(--green);\n    color: #fff;\n    font-size: 12px;\n    font-weight: 700;\n    line-height: 1.35;\n}<\/p>\n<p>tbody tr:nth-child(even) { background: #f7f9f7; }\ntbody td { height: 42px; }<\/p>\n<p>td input {\n    padding: 7px 5px;\n    border-color: #d7ded8;\n    border-radius: 3px;\n    text-align: center;\n}<\/p>\n<p>td.index-cell {\n    color: #657269;\n    font-weight: 700;\n}<\/p>\n<p>td.percent-cell, td.status-cell {\n    font-size: 12px;\n    font-weight: 700;\n}<\/p>\n<p>.status-pass { color: #216b3a; background: #e8f5eb; }\n.status-fail { color: #a52a2a; background: #fbecec; }\n.status-empty { color: #8a938c; }<\/p>\n<p>.col-number { width: 7%; }\n.col-index { width: 25%; }\n.col-points { width: 22%; }\n.col-percent { width: 16%; }\n.col-status { width: 20%; }\n.col-action { width: 10%; }<\/p>\n<p>.row-delete {\n    padding: 5px 7px;\n    border: 1px solid #e1bcbc;\n    border-radius: 4px;\n    background: #fff;\n    color: #9b3333;\n    cursor: pointer;\n    font-size: 12px;\n}<\/p>\n<p>.row-delete:hover { background: #fff0f0; }<\/p>\n<p>.actions {\n    display: flex;\n    flex-wrap: wrap;\n    gap: 10px;\n    margin: 16px 0 26px;\n}<\/p>\n<p>.btn {\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    gap: 7px;\n    padding: 10px 15px;\n    border: 1px solid transparent;\n    border-radius: 4px;\n    font-size: 13px;\n    font-weight: 700;\n    cursor: pointer;\n}<\/p>\n<p>.btn-primary { background: var(--green); color: #fff; }\n.btn-primary:hover { background: #1f472b; }<\/p>\n<p>.btn-secondary {\n    background: #fff;\n    border-color: #b9c8bc;\n    color: var(--green);\n}<\/p>\n<p>.btn-secondary:hover { background: var(--green-soft); }<\/p>\n<p>.btn-danger {\n    background: #fff;\n    border-color: #e1bcbc;\n    color: #9b3333;\n}<\/p>\n<p>.exam-details {\n    display: grid;\n    grid-template-columns: repeat(2,minmax(0,1fr));\n    gap: 14px 20px;\n    margin-top: 24px;\n}<\/p>\n<p>.footer-signatures {\n    display: grid;\n    grid-template-columns: 1fr 1fr;\n    gap: 40px;\n    margin-top: 36px;\n    padding-top: 18px;\n    border-top: 1px solid var(--border);\n}<\/p>\n<p>.signature { text-align: center; line-height: 1.5; }<\/p>\n<p>.signature-line {\n    height: 36px;\n    margin-top: 20px;\n    border-bottom: 1px solid #67736a;\n}<\/p>\n<p>.signature small {\n    display: block;\n    margin-top: 6px;\n    color: var(--muted);\n}<\/p>\n<p>.note {\n    margin-top: 16px;\n    color: var(--muted);\n    font-size: 12px;\n    line-height: 1.5;\n}<\/p>\n<p>.required-note {\n    margin: 0 0 20px;\n    padding: 10px 12px;\n    border-left: 4px solid var(--green);\n    background: var(--green-soft);\n    color: #334b39;\n    font-size: 12px;\n    line-height: 1.5;\n}<\/p>\n<p>.validation-message {\n    display: none;\n    margin: 0 0 16px;\n    padding: 12px;\n    border: 1px solid #e1bcbc;\n    border-radius: 4px;\n    background: #fff0f0;\n    color: #922b21;\n    line-height: 1.5;\n}<\/p>\n<p>.validation-message.visible { display: block; }<\/p>\n<p>@media (max-width: 700px) {\n    body { padding: 8px; }<\/p>\n<p>    .page-header, .content { padding: 16px; }<\/p>\n<p>    .logo {\n        max-width: 95px;\n        max-height: 65px;\n    }<\/p>\n<p>    .logo-unsa { max-width: 80px; }\n    .logo-row { gap: 10px; }<\/p>\n<p>    .header-text .university { font-size: 11px; }\n    .header-text .faculty { font-size: 13px; }\n    .header-text .document-title { font-size: 13px; }<\/p>\n<p>    .general-grid, .exam-details, .footer-signatures {\n        grid-template-columns: 1fr;\n    }<\/p>\n<p>    .field.full { grid-column: auto; }\n    table { min-width: 680px; }\n}<\/p>\n<p>@page {\n    size: A4 portrait;\n    margin: 12mm;\n}<\/p>\n<p>@media print {\n    body {\n        padding: 0;\n        background: #fff;\n        color: #000;\n        font-size: 10pt;\n        -webkit-print-color-adjust: exact;\n        print-color-adjust: exact;\n    }<\/p>\n<p>    .page {\n        max-width: none;\n        border: 0;\n        border-radius: 0;\n        box-shadow: none;\n        overflow: visible;\n    }<\/p>\n<p>    .page-header { padding: 0 0 12px; }\n    .content { padding: 14px 0 0; }<\/p>\n<p>    .actions, .row-delete, .no-print, .table-action-column,\n    .required-note, .validation-message {\n        display: none !important;\n    }<\/p>\n<p>    input, select, textarea {\n        padding: 2px 3px;\n        border: 0;\n        border-radius: 0;\n        color: #000;\n        background: transparent;\n        font-size: 9pt;\n        box-shadow: none;\n        appearance: none;\n    }<\/p>\n<p>    input::placeholder, textarea::placeholder { color: transparent; }<\/p>\n<p>    .general-grid, .exam-details { gap: 8px 14px; }<\/p>\n<p>    th, td {\n        padding: 5px 4px;\n        border: 1px solid #777;\n    }<\/p>\n<p>    thead th {\n        background: #285A37 !important;\n        color: #fff !important;\n    }<\/p>\n<p>    tbody tr { break-inside: avoid; }\n    .footer-signatures { margin-top: 28px; }\n    .signature-line { height: 28px; }\n    .section-title { color: #285A37 !important; }\n}\n<\/style>\n<p><\/head><\/p>\n<p><body><\/p>\n<div class=\"page\">\n<header class=\"page-header\">\n<div class=\"logo-row\">\n        <img decoding=\"async\"\n            class=\"logo logo-unsa\"\n            src=\"https:\/\/www.unsa.ba\/themes\/unsa\/logo.svg\"\n            alt=\"Univerzitet u Sarajevu\"\n        ><\/p>\n<div class=\"header-text\">\n<div class=\"university\">Univerzitet u Sarajevu<\/div>\n<div class=\"faculty\">Poljoprivredno-prehrambeni fakultet<\/div>\n<div class=\"document-title\">REZULTATI PISMENE PROVJERE ZNANJA<\/div>\n<\/p><\/div>\n<p>        <img decoding=\"async\"\n            class=\"logo\"\n            src=\"https:\/\/ppf.unsa.ba\/images\/Aktuelnosti\/ppfznaktransparent.png\"\n            alt=\"Poljoprivredno-prehrambeni fakultet\"\n        >\n    <\/div>\n<\/header>\n<p><main class=\"content\"><\/p>\n<h2 class=\"section-title\">Op\u0107i podaci o ispitu<\/h2>\n<p class=\"required-note\">\n        Sva polja ozna\u010dena zvjezdicom (*) su obavezna.<br \/>\n        Rezultate mo\u017eete \u0161tampati ili sa\u010duvati kao PDF tek kada unesete<br \/>\n        sve obavezne podatke i podatke za svakog studenta.\n    <\/p>\n<div id=\"validationMessage\" class=\"validation-message\"\n         role=\"alert\" aria-live=\"polite\"><\/div>\n<div class=\"general-grid\">\n<div class=\"field\">\n            <label for=\"ciklus\">Ciklus studija *<\/label><br \/>\n            <select id=\"ciklus\" name=\"ciklus\" required><option value=\"\">Odaberite ciklus<\/option><option value=\"I (prvi) ciklus\">I (PRVI) CIKLUS<\/option><option value=\"II (drugi) ciklus\">II (DRUGI) CIKLUS<\/option><option value=\"III (tre\u0107i) ciklus\">III (TRE\u0106I) CIKLUS<\/option><\/select>\n        <\/div>\n<div class=\"field\">\n            <label for=\"odsjek\">Odsjek *<\/label><br \/>\n            <select id=\"odsjek\" name=\"odsjek\" required disabled><option value=\"\">Prvo odaberite ciklus studija<\/option><\/select>\n        <\/div>\n<div class=\"field full\">\n            <label for=\"studijskiProgram\">Studijski program *<\/label><br \/>\n            <select id=\"studijskiProgram\" name=\"studijskiProgram\" required disabled><option value=\"\">Prvo odaberite ciklus i odsjek<\/option><\/select>\n        <\/div>\n<div class=\"field full\">\n            <label for=\"program\">Naziv studijskog programa *<\/label><br \/>\n            <input\n                id=\"program\"\n                name=\"program\"\n                type=\"text\"\n                placeholder=\"Naziv \u0107e se popuniti nakon izbora programa\"\n                readonly\n                required\n            >\n        <\/div>\n<div class=\"field\">\n            <label for=\"akademska_godina\">Akademska godina *<\/label><br \/>\n            <select id=\"akademska_godina\" name=\"akademska_godina\" required><option value=\"\">Odaberite akademsku godinu<\/option><option value=\"2026\/2027\">2026\/2027.<\/option><\/select>\n        <\/div>\n<div class=\"field\">\n            <label for=\"semestar\">Semestar *<\/label><br \/>\n            <select id=\"semestar\" name=\"semestar\" required><option value=\"\">Odaberite semestar<\/option><option value=\"I semestar\">I semestar<\/option><option value=\"II semestar\">II semestar<\/option><option value=\"III semestar\">III semestar<\/option><option value=\"IV semestar\">IV semestar<\/option><option value=\"V semestar\">V semestar<\/option><option value=\"VI semestar\">VI semestar<\/option><\/select>\n        <\/div>\n<div class=\"field full\">\n            <label for=\"predmet\">Naziv predmeta *<\/label><br \/>\n            <input id=\"predmet\" name=\"predmet\" type=\"text\"\n                   placeholder=\"Unesite naziv predmeta\" required>\n        <\/div>\n<div class=\"field\">\n            <label for=\"provjera\">Vrsta provjere znanja *<\/label><br \/>\n            <input id=\"provjera\" name=\"provjera\" type=\"text\"\n                   placeholder=\"Npr. parcijalni ispit\" required>\n        <\/div>\n<div class=\"field\">\n            <label for=\"datum\">Datum provjere *<\/label><br \/>\n            <input id=\"datum\" name=\"datum\" type=\"date\" required>\n        <\/div>\n<div class=\"field\">\n            <label for=\"maxBodova\">Maksimalan broj bodova *<\/label><br \/>\n            <input id=\"maxBodova\" name=\"maxBodova\" type=\"number\"\n                   min=\"0.01\" step=\"0.01\"\n                   placeholder=\"Unesite maksimalan broj bodova\" required>\n        <\/div>\n<div class=\"field\">\n            <label for=\"minBodova\">Minimalan broj prolaznih bodova *<\/label><br \/>\n            <input id=\"minBodova\" name=\"minBodova\" type=\"number\"\n                   min=\"0\" step=\"0.01\"\n                   placeholder=\"Unesite minimum za prolaz\" required>\n        <\/div>\n<div class=\"field full\">\n            <label for=\"uvid\">Termin i mjesto uvida u pisani rad *<\/label><br \/>\n            <input id=\"uvid\" name=\"uvid\" type=\"text\"\n                   placeholder=\"Unesite termin i mjesto uvida\" required>\n        <\/div>\n<div class=\"field full\">\n            <label for=\"nastavnik\">Odgovorni nastavnik *<\/label><br \/>\n            <input id=\"nastavnik\" name=\"nastavnik\" type=\"text\"\n                   placeholder=\"Unesite ime i prezime nastavnika\" required>\n        <\/div>\n<\/p><\/div>\n<div class=\"table-heading\">\n<h2 class=\"section-title\">Tabela rezultata<\/h2>\n<\/p><\/div>\n<div class=\"table-wrap\">\n<table id=\"resultsTable\">\n<colgroup>\n<col class=\"col-number\">\n<col class=\"col-index\">\n<col class=\"col-points\">\n<col class=\"col-percent\">\n<col class=\"col-status\">\n<col class=\"col-action table-action-column\">\n            <\/colgroup>\n<thead>\n<tr>\n<th>R. broj<\/th>\n<th>Broj indeksa *<\/th>\n<th>Osvojeni bodovi *<\/th>\n<th>Ostvareni %<\/th>\n<th>Status<\/th>\n<th class=\"table-action-column no-print\">Ukloni<\/th>\n<\/tr>\n<\/thead>\n<tbody id=\"studentRows\"><\/tbody>\n<\/table><\/div>\n<div class=\"actions no-print\">\n        <button type=\"button\" class=\"btn btn-primary\" id=\"addStudent\"><br \/>\n            + Dodaj studenta<br \/>\n        <\/button><\/p>\n<p>        <button type=\"button\" class=\"btn btn-secondary\" id=\"printPage\"><br \/>\n            \u0160tampaj \/ Sa\u010duvaj kao PDF<br \/>\n        <\/button><\/p>\n<p>        <button type=\"button\" class=\"btn btn-secondary\" id=\"exportCsv\"><br \/>\n            Izvezi tabelu u CSV<br \/>\n        <\/button><\/p>\n<p>        <button type=\"button\" class=\"btn btn-secondary\" id=\"emailResults\"><br \/>\n            Po\u0161alji rezultate na e-mail<br \/>\n        <\/button><\/p>\n<p>        <button type=\"button\" class=\"btn btn-danger\" id=\"clearForm\"><br \/>\n            O\u010disti obrazac<br \/>\n        <\/button>\n    <\/div>\n<div class=\"exam-details\">\n<div class=\"field\">\n            <label for=\"napomena\">Napomena (opcionalno)<\/label><br \/>\n            <textarea id=\"napomena\" name=\"napomena\" rows=\"2\"\n                      placeholder=\"Unesite napomenu ako je potrebna\"><\/textarea>\n        <\/div>\n<div class=\"field\">\n            <label for=\"mjestoDatum\">Mjesto i datum objave (opcionalno)<\/label><br \/>\n            <input id=\"mjestoDatum\" name=\"mjestoDatum\" type=\"text\"\n                   placeholder=\"Npr. Sarajevo, datum objave\">\n        <\/div>\n<\/p><\/div>\n<div class=\"footer-signatures\">\n<div class=\"signature\">\n            <strong>M. P.<\/strong><\/p>\n<div class=\"signature-line\"><\/div>\n<p>            <small>Mjesto za pe\u010dat<\/small>\n        <\/div>\n<div class=\"signature\">\n            <strong id=\"signatureTeacherName\">Odgovorni nastavnik<\/strong><\/p>\n<div class=\"signature-line\"><\/div>\n<p>            <small>Potpis nastavnika<\/small>\n        <\/div>\n<\/p><\/div>\n<p class=\"note\">\n        Procenat se ra\u010duna prema unesenom maksimalnom broju bodova.<br \/>\n        Status prolaznosti prikazuje se kada su uneseni bodovi i minimalan<br \/>\n        broj bodova za prolaz. Obrazac ne pohranjuje podatke na server. Dugme za e-mail otvara novu poruku s pripremljenim rezultatima; poruku je potrebno poslati iz va\u0161eg e-mail programa.\n    <\/p>\n<p><\/main>\n<\/div>\n<p><script>\n(function () {\n    \"use strict\";<\/p>\n<p>    const tbody = document.getElementById(\"studentRows\");\n    const maxInput = document.getElementById(\"maxBodova\");\n    const minInput = document.getElementById(\"minBodova\");<\/p>\n<p>    const ciklusSelect = document.getElementById(\"ciklus\");\n    const odsjekSelect = document.getElementById(\"odsjek\");\n    const studijskiProgramSelect = document.getElementById(\"studijskiProgram\");\n    const programInput = document.getElementById(\"program\");<\/p>\n<p>    const validationMessage = document.getElementById(\"validationMessage\");\n    const nastavnikInput = document.getElementById(\"nastavnik\");\n    const signatureTeacherName = document.getElementById(\"signatureTeacherName\");<\/p>\n<p>    \/\/ Ime nastavnika na potpisu prati unos u polju \"Odgovorni nastavnik\".\n    function updateTeacherSignature() {\n        const name = nastavnikInput.value.trim();\n        signatureTeacherName.textContent = name || \"Odgovorni nastavnik\";\n    }<\/p>\n<p>    nastavnikInput.addEventListener(\"input\", updateTeacherSignature);<\/p>\n<p>    \/*\n     * \u010cetiri odsjeka postoje na oba ciklusa.\n     * Svaki program je povezan s odgovaraju\u0107im odsjekom.\n     *\/\n    const odsjeci = [\n        \"BILJNA PROIZVODNJA\",\n        \"ZOOTEHNIKA\",\n        \"PREHRAMBENE TEHNOLOGIJE\",\n        \"EKONOMIKA POLJOPRIVREDE I PREHRAMBENE INDUSTRIJE\"\n    ];<\/p>\n<p>    const studijskiProgrami = {\n\"I (prvi) ciklus\": {\n    \"BILJNA PROIZVODNJA\": [\n        \"RATARSTVO \/ POVRTLARSTVO\",\n        \"VO\u0106ARSTVO \/ VINOGRADARSTVO\"\n    ],<\/p>\n<p>    \"ZOOTEHNIKA\": [\n        \"ANIMALNA PROIZVODNJA\",\n        \"AKVAKULTURA\"\n    ],<\/p>\n<p>    \"PREHRAMBENE TEHNOLOGIJE\": [\n        \"PREHRAMBENE TEHNOLOGIJE\",\n        \"NUTRICIONIZAM\"\n    ],<\/p>\n<p>    \"EKONOMIKA POLJOPRIVREDE I PREHRAMBENE INDUSTRIJE\": [\n        \"EKONOMIKA AGROINDUSTRIJE\"\n    ]\n},<\/p>\n<p>        \"II (drugi) ciklus\": {\n            \"BILJNA PROIZVODNJA\": [\n                \"STUDIJSKI PROGRAM: RATARSTVO\",\n                \"STUDIJSKI PROGRAM: POVRTLARSTVO\",\n                \"STUDIJSKI PROGRAM: VO\u0106ARSTVO\",\n                \"STUDIJSKI PROGRAM: VINOGRADARSTVO I VINARSTVO\",\n                \"STUDIJSKI PROGRAM: FLORISTIKA I PEJSA\u017dNO OBLIKOVANJE\",\n                \"STUDIJSKI PROGRAM: FITOMEDICINA\",\n                \"STUDIJSKI PROGRAM: ODR\u017dIVO UPRAVLJANJE ZEMLJI\u0160TEM I RURALNIM PROSTOROM\",\n                \"STUDIJSKI PROGRAM: URBANA POLJOPRIVREDA\"\n            ],<\/p>\n<p>            \"ZOOTEHNIKA\": [\n                \"STUDIJSKI PROGRAM: ANIMALNA PROIZVODNJA\",\n                \"STUDIJSKI PROGRAM: AKVAKULTURA\",\n                \"STUDIJSKI PROGRAM: HRANA I ISHRANA \u017dIVOTINJA\"\n            ],<\/p>\n<p>            \"PREHRAMBENE TEHNOLOGIJE\": [\n                \"STUDIJSKI PROGRAM: PREHRAMBENE TEHNOLOGIJE - TEHNOLOGIJA PROIZVODA BILJNOG PORIJEKLA\",\n                \"STUDIJSKI PROGRAM: TEHNOLOGIJA PROIZVODA ANIMALNOG PORIJEKLA\",\n                \"STUDIJSKI PROGRAM: KONTROLA KVALITETA HRANE I PI\u0106A\",\n                \"STUDIJSKI PROGRAM: ODR\u017dIVI SISTEMI PROIZVODNJE HRANE\"\n            ],<\/p>\n<p>            \"EKONOMIKA POLJOPRIVREDE I PREHRAMBENE INDUSTRIJE\": [\n                \"STUDIJSKI PROGRAM: EKONOMIKA AGROINDUSTRIJE\"\n            ]\n        }\n    };<\/p>\n<p>    function addPlaceholder(select, text) {\n        const option = document.createElement(\"option\");\n        option.value = \"\";\n        option.textContent = text;\n        select.appendChild(option);\n    }<\/p>\n<p>    function updateDepartments() {\n        const selectedCycle = ciklusSelect.value;<\/p>\n<p>        odsjekSelect.innerHTML = \"\";\n        studijskiProgramSelect.innerHTML = \"\";\n        programInput.value = \"\";<\/p>\n<p>        addPlaceholder(\n            odsjekSelect,\n            selectedCycle\n                ? \"Odaberite odsjek\"\n                : \"Prvo odaberite ciklus studija\"\n        );<\/p>\n<p>        addPlaceholder(\n            studijskiProgramSelect,\n            \"Prvo odaberite odsjek\"\n        );<\/p>\n<p>        const cycleDepartments = studijskiProgrami[selectedCycle];<\/p>\n<p>        if (!cycleDepartments) {\n            odsjekSelect.disabled = true;\n            studijskiProgramSelect.disabled = true;<\/p>\n<p>            if (selectedCycle === \"III (tre\u0107i) ciklus\") {\n                odsjekSelect.options[0].textContent =\n                    \"Programi III ciklusa nisu uneseni\";\n            }<\/p>\n<p>            return;\n        }<\/p>\n<p>        odsjeci.forEach(function (odsjek) {\n            const option = document.createElement(\"option\");\n            option.value = odsjek;\n            option.textContent = odsjek;\n            odsjekSelect.appendChild(option);\n        });<\/p>\n<p>        odsjekSelect.disabled = false;\n        studijskiProgramSelect.disabled = true;\n    }<\/p>\n<p>    function updatePrograms() {\n        const selectedCycle = ciklusSelect.value;\n        const selectedDepartment = odsjekSelect.value;<\/p>\n<p>        studijskiProgramSelect.innerHTML = \"\";\n        programInput.value = \"\";<\/p>\n<p>        const cycleDepartments = studijskiProgrami[selectedCycle];\n        const programs = cycleDepartments && selectedDepartment\n            ? cycleDepartments[selectedDepartment] || []\n            : [];<\/p>\n<p>        addPlaceholder(\n            studijskiProgramSelect,\n            programs.length\n                ? \"Odaberite studijski program\"\n                : \"Prvo odaberite odsjek\"\n        );<\/p>\n<p>        programs.forEach(function (program) {\n            const option = document.createElement(\"option\");\n            option.value = program;\n            option.textContent = program;\n            studijskiProgramSelect.appendChild(option);\n        });<\/p>\n<p>        studijskiProgramSelect.disabled = programs.length === 0;\n    }<\/p>\n<p>    function updateProgramName() {\n        programInput.value = studijskiProgramSelect.value;\n        clearValidationMessage();\n    }<\/p>\n<p>    ciklusSelect.addEventListener(\"change\", function () {\n        updateDepartments();\n        clearValidationMessage();\n    });<\/p>\n<p>    odsjekSelect.addEventListener(\"change\", function () {\n        updatePrograms();\n        clearValidationMessage();\n    });<\/p>\n<p>    studijskiProgramSelect.addEventListener(\"change\", updateProgramName);<\/p>\n<p>    function parseNumber(value) {\n        if (value === null || value === undefined) return NaN;<\/p>\n<p>        const normalized = String(value).trim().replace(\",\", \".\");\n        if (normalized === \"\") return NaN;<\/p>\n<p>        return Number(normalized);\n    }<\/p>\n<p>    function formatNumber(value, decimals) {\n        return value.toLocaleString(\"bs-BA\", {\n            minimumFractionDigits: 0,\n            maximumFractionDigits: decimals\n        });\n    }<\/p>\n<p>    function updateRow(row) {\n        const pointsInput = row.querySelector(\".points-input\");\n        const percentCell = row.querySelector(\".percent-cell\");\n        const statusCell = row.querySelector(\".status-cell\");<\/p>\n<p>        const points = parseNumber(pointsInput.value);\n        const max = parseNumber(maxInput.value);\n        const min = parseNumber(minInput.value);<\/p>\n<p>        percentCell.textContent = \"\";\n        statusCell.textContent = \"\";\n        statusCell.className = \"status-cell status-empty\";<\/p>\n<p>        pointsInput.setCustomValidity(\"\");<\/p>\n<p>        if (pointsInput.value.trim() === \"\") return;<\/p>\n<p>        if (!Number.isFinite(points) || points < 0) {\n            pointsInput.setCustomValidity(\"Unesite ispravan broj bodova.\");\n            statusCell.textContent = \"Provjerite bodove\";\n            return;\n        }\n\n        if (Number.isFinite(max) &#038;&#038; max > 0) {\n            if (points > max) {\n                pointsInput.setCustomValidity(\n                    \"Osvojeni bodovi ne mogu biti ve\u0107i od maksimuma.\"\n                );\n                statusCell.textContent = \"Iznad maksimuma\";\n                return;\n            }<\/p>\n<p>            percentCell.textContent =\n                formatNumber((points \/ max) * 100, 1) + \"%\";\n        }<\/p>\n<p>        if (Number.isFinite(min) && min >= 0) {\n            if (Number.isFinite(max) && min > max) {\n                statusCell.textContent = \"Provjerite minimum\";\n                return;\n            }<\/p>\n<p>            if (points >= min) {\n                statusCell.textContent = \"Polo\u017eio\/la\";\n                statusCell.className = \"status-cell status-pass\";\n            } else {\n                statusCell.textContent = \"Nije polo\u017eio\/la\";\n                statusCell.className = \"status-cell status-fail\";\n            }\n        }\n    }<\/p>\n<p>    function renumberRows() {\n        Array.from(tbody.rows).forEach(function (row, index) {\n            row.querySelector(\".row-number\").textContent = index + 1;\n        });\n    }<\/p>\n<p>    function addStudent() {\n        const row = document.createElement(\"tr\");<\/p>\n<p>        row.innerHTML = `<\/p>\n<td class=\"index-cell row-number\"><\/td>\n<td>\n                <input type=\"text\" class=\"index-input\"\n                       aria-label=\"Broj indeksa\"\n                       placeholder=\"Broj indeksa\" required>\n            <\/td>\n<td>\n                <input type=\"number\" class=\"points-input\"\n                       aria-label=\"Osvojeni bodovi\"\n                       min=\"0\" step=\"0.01\"\n                       placeholder=\"Bodovi\" required>\n            <\/td>\n<td class=\"percent-cell\"><\/td>\n<td class=\"status-cell status-empty\"><\/td>\n<td class=\"table-action-column no-print\">\n                <button type=\"button\" class=\"row-delete\"\n                        aria-label=\"Ukloni studenta\">Ukloni<\/button>\n            <\/td>\n<p>        `;<\/p>\n<p>        row.querySelector(\".points-input\").addEventListener(\"input\", function () {\n            updateRow(row);\n            clearValidationMessage();\n        });<\/p>\n<p>        row.querySelector(\".index-input\").addEventListener(\"input\", function () {\n            clearValidationMessage();\n        });<\/p>\n<p>        row.querySelector(\".row-delete\").addEventListener(\"click\", function () {\n            row.remove();\n            renumberRows();\n            clearValidationMessage();\n        });<\/p>\n<p>        tbody.appendChild(row);\n        renumberRows();\n    }<\/p>\n<p>    function updateAllRows() {\n        Array.from(tbody.rows).forEach(updateRow);\n    }<\/p>\n<p>    function clearValidationMessage() {\n        validationMessage.textContent = \"\";\n        validationMessage.classList.remove(\"visible\");\n    }<\/p>\n<p>    function showValidationError(message, field) {\n        validationMessage.textContent = message;\n        validationMessage.classList.add(\"visible\");<\/p>\n<p>        if (field) {\n            field.focus();<\/p>\n<p>            field.scrollIntoView({\n                behavior: \"smooth\",\n                block: \"center\"\n            });\n        } else {\n            validationMessage.scrollIntoView({\n                behavior: \"smooth\",\n                block: \"center\"\n            });\n        }\n    }<\/p>\n<p>    function validateForm() {\n        clearValidationMessage();\n        updateAllRows();<\/p>\n<p>        const requiredFields = [\n            ciklusSelect,\n            odsjekSelect,\n            studijskiProgramSelect,\n            programInput,\n            document.getElementById(\"akademska_godina\"),\n            document.getElementById(\"semestar\"),\n            document.getElementById(\"predmet\"),\n            document.getElementById(\"provjera\"),\n            document.getElementById(\"datum\"),\n            maxInput,\n            minInput,\n            document.getElementById(\"uvid\"),\n            document.getElementById(\"nastavnik\")\n        ];<\/p>\n<p>        for (const field of requiredFields) {\n            if (!field.value || !field.value.trim()) {\n                const label = document.querySelector(\n                    'label[for=\"' + field.id + '\"]'\n                );<\/p>\n<p>                const fieldName = label\n                    ? label.textContent.replace(\"*\", \"\").trim()\n                    : \"Obavezno polje\";<\/p>\n<p>                showValidationError(\n                    'Niste popunili obavezno polje: \"' + fieldName + '\".',\n                    field\n                );<\/p>\n<p>                return false;\n            }<\/p>\n<p>            if (!field.checkValidity()) {\n                const label = document.querySelector(\n                    'label[for=\"' + field.id + '\"]'\n                );<\/p>\n<p>                showValidationError(\n                    \"Provjerite unesenu vrijednost u polju: \" +\n                    (label ? label.textContent.replace(\"*\", \"\").trim() : field.id),\n                    field\n                );<\/p>\n<p>                return false;\n            }\n        }<\/p>\n<p>        const cycleDepartments = studijskiProgrami[ciklusSelect.value];<\/p>\n<p>        if (!cycleDepartments) {\n            showValidationError(\n                \"Za odabrani ciklus nije unesena lista studijskih programa. \" +\n                \"Odaberite I ili II ciklus studija.\",\n                ciklusSelect\n            );<\/p>\n<p>            return false;\n        }<\/p>\n<p>        const validPrograms = cycleDepartments[odsjekSelect.value] || [];<\/p>\n<p>        if (!validPrograms.includes(studijskiProgramSelect.value)) {\n            showValidationError(\n                \"Odabrani studijski program ne pripada izabranom ciklusu i odsjeku.\",\n                studijskiProgramSelect\n            );<\/p>\n<p>            return false;\n        }<\/p>\n<p>        if (programInput.value !== studijskiProgramSelect.value) {\n            showValidationError(\n                \"Naziv studijskog programa nije ispravan. Ponovo odaberite program.\",\n                studijskiProgramSelect\n            );<\/p>\n<p>            return false;\n        }<\/p>\n<p>        const max = parseNumber(maxInput.value);\n        const min = parseNumber(minInput.value);<\/p>\n<p>        if (!Number.isFinite(max) || max <= 0) {\n            showValidationError(\n                \"Maksimalan broj bodova mora biti ve\u0107i od nule.\",\n                maxInput\n            );\n            return false;\n        }\n\n        if (!Number.isFinite(min) || min < 0) {\n            showValidationError(\n                \"Minimalan broj prolaznih bodova ne mo\u017ee biti negativan.\",\n                minInput\n            );\n            return false;\n        }\n\n        if (min > max) {\n            showValidationError(\n                \"Minimalan broj prolaznih bodova ne mo\u017ee biti ve\u0107i \" +\n                \"od maksimalnog broja bodova.\",\n                minInput\n            );\n            return false;\n        }<\/p>\n<p>        if (tbody.rows.length === 0) {\n            showValidationError(\n                \"Morate unijeti najmanje jednog studenta. \" +\n                \"Kliknite na dugme \u201eDodaj studenta\u201c.\",\n                document.getElementById(\"addStudent\")\n            );\n            return false;\n        }<\/p>\n<p>        for (let i = 0; i < tbody.rows.length; i++) {\n            const row = tbody.rows[i];\n            const indexInput = row.querySelector(\".index-input\");\n            const pointsInput = row.querySelector(\".points-input\");\n\n            if (!indexInput.value.trim()) {\n                showValidationError(\n                    \"Nedostaje broj indeksa za studenta pod rednim brojem \" +\n                    (i + 1) + \".\",\n                    indexInput\n                );\n                return false;\n            }\n\n            if (pointsInput.value.trim() === \"\") {\n                showValidationError(\n                    \"Niste unijeli osvojene bodove za studenta pod rednim \" +\n                    \"brojem \" + (i + 1) + \".\",\n                    pointsInput\n                );\n                return false;\n            }\n\n            const points = parseNumber(pointsInput.value);\n\n            if (!Number.isFinite(points) || points < 0) {\n                showValidationError(\n                    \"Osvojeni bodovi za studenta pod rednim brojem \" +\n                    (i + 1) + \" nisu ispravni.\",\n                    pointsInput\n                );\n                return false;\n            }\n\n            if (points > max) {\n                showValidationError(\n                    \"Osvojeni bodovi studenta pod rednim brojem \" +\n                    (i + 1) + \" ne mogu biti ve\u0107i od maksimalnog broja bodova.\",\n                    pointsInput\n                );\n                return false;\n            }\n        }<\/p>\n<p>        return true;\n    }<\/p>\n<p>    maxInput.addEventListener(\"input\", function () {\n        updateAllRows();\n        clearValidationMessage();\n    });<\/p>\n<p>    minInput.addEventListener(\"input\", function () {\n        updateAllRows();\n        clearValidationMessage();\n    });<\/p>\n<p>    document.querySelectorAll(\n        \".general-grid input, .general-grid select\"\n    ).forEach(function (field) {\n        field.addEventListener(\"input\", clearValidationMessage);\n        field.addEventListener(\"change\", clearValidationMessage);\n    });<\/p>\n<p>    document.getElementById(\"addStudent\").addEventListener(\"click\", function () {\n        addStudent();\n        clearValidationMessage();<\/p>\n<p>        const rows = tbody.querySelectorAll(\".index-input\");\n        rows[rows.length - 1].focus();\n    });<\/p>\n<p>    document.getElementById(\"printPage\").addEventListener(\"click\", function () {\n        if (!validateForm()) return;<\/p>\n<p>        window.print();\n    });<\/p>\n<p>    document.getElementById(\"exportCsv\").addEventListener(\"click\", function () {\n        if (!validateForm()) return;<\/p>\n<p>        const lines = [\n            [\n                \"R. broj\",\n                \"Broj indeksa\",\n                \"Osvojeni bodovi\",\n                \"Ostvareni %\",\n                \"Status\"\n            ]\n        ];<\/p>\n<p>        Array.from(tbody.rows).forEach(function (row, index) {\n            lines.push([\n                index + 1,\n                row.querySelector(\".index-input\").value,\n                row.querySelector(\".points-input\").value,\n                row.querySelector(\".percent-cell\").textContent,\n                row.querySelector(\".status-cell\").textContent\n            ]);\n        });<\/p>\n<p>        const csv = \"\\uFEFF\" + lines.map(function (line) {\n            return line.map(function (cell) {\n                return '\"' + String(cell).replace(\/\"\/g, '\"\"') + '\"';\n            }).join(\";\");\n        }).join(\"\\r\\n\");<\/p>\n<p>        const blob = new Blob([csv], {\n            type: \"text\/csv;charset=utf-8;\"\n        });<\/p>\n<p>        const url = URL.createObjectURL(blob);\n        const link = document.createElement(\"a\");<\/p>\n<p>        link.href = url;\n        link.download = \"rezultati_ispita.csv\";<\/p>\n<p>        document.body.appendChild(link);\n        link.click();\n        link.remove();<\/p>\n<p>        setTimeout(function () {\n            URL.revokeObjectURL(url);\n        }, 1000);\n    });<\/p>\n<p>    document.getElementById(\"emailResults\").addEventListener(\"click\", function () {\n        if (!validateForm()) return;<\/p>\n<p>        const value = function (id) {\n            const field = document.getElementById(id);\n            return field ? field.value.trim() : \"\";\n        };<\/p>\n<p>        const lines = [\n            \"REZULTATI PISMENE PROVJERE ZNANJA\",\n            \"\",\n            \"Ciklus studija: \" + value(\"ciklus\"),\n            \"Odsjek: \" + value(\"odsjek\"),\n            \"Studijski program: \" + value(\"program\"),\n            \"Akademska godina: \" + value(\"akademska_godina\"),\n            \"Semestar: \" + value(\"semestar\"),\n            \"Predmet: \" + value(\"predmet\"),\n            \"Vrsta provjere znanja: \" + value(\"provjera\"),\n            \"Datum provjere: \" + value(\"datum\"),\n            \"Maksimalan broj bodova: \" + value(\"maxBodova\"),\n            \"Minimalan broj prolaznih bodova: \" + value(\"minBodova\"),\n            \"Termin i mjesto uvida: \" + value(\"uvid\"),\n            \"Odgovorni nastavnik: \" + value(\"nastavnik\"),\n            \"\",\n            \"REZULTATI STUDENATA\",\n            \"R. broj | Broj indeksa | Osvojeni bodovi | Ostvareni % | Status\"\n        ];<\/p>\n<p>        Array.from(tbody.rows).forEach(function (row, index) {\n            lines.push([\n                index + 1,\n                row.querySelector(\".index-input\").value.trim(),\n                row.querySelector(\".points-input\").value.trim(),\n                row.querySelector(\".percent-cell\").textContent.trim(),\n                row.querySelector(\".status-cell\").textContent.trim()\n            ].join(\" | \"));\n        });<\/p>\n<p>        if (value(\"napomena\")) {\n            lines.push(\"\", \"Napomena: \" + value(\"napomena\"));\n        }\n        if (value(\"mjestoDatum\")) {\n            lines.push(\"Mjesto i datum objave: \" + value(\"mjestoDatum\"));\n        }<\/p>\n<p>        lines.push(\"\", \"Poruka je pripremljena putem obrasca za rezultate ispita PPF UNSA.\");<\/p>\n<p>        const subject = \"Rezultati ispita \u2013 \" + value(\"predmet\");\n        const mailto = \"mailto:a.salihovic@ppf.unsa.ba\"\n            + \"?subject=\" + encodeURIComponent(subject)\n            + \"&body=\" + encodeURIComponent(lines.join(\"\\r\\n\"));<\/p>\n<p>        \/\/ Otvara podrazumijevani e-mail program s popunjenim primaocem i sadr\u017eajem.\n        window.location.href = mailto;\n    });<\/p>\n<p>    document.getElementById(\"clearForm\").addEventListener(\"click\", function () {\n        if (!confirm(\n            \"\u017delite li o\u010distiti sva polja i ukloniti sve redove?\"\n        )) {\n            return;\n        }<\/p>\n<p>        document.querySelectorAll(\n            \".general-grid input, .general-grid select, \" +\n            \".exam-details input, .exam-details textarea\"\n        ).forEach(function (field) {\n            field.value = \"\";\n        });<\/p>\n<p>        updateTeacherSignature();<\/p>\n<p>        ciklusSelect.value = \"\";\n        updateDepartments();<\/p>\n<p>        tbody.innerHTML = \"\";<\/p>\n<p>        addStudent();\n        addStudent();\n        addStudent();<\/p>\n<p>        clearValidationMessage();<\/p>\n<p>        window.scrollTo({\n            top: 0,\n            behavior: \"smooth\"\n        });\n    });<\/p>\n<p>    \/\/ Po\u010detno stanje: tri prazna reda i neodabrani ciklus\/odsjek\/program.\n    updateDepartments();<\/p>\n<p>    addStudent();\n    addStudent();\n    addStudent();<\/p>\n<p>})();\n<\/script><\/p>\n<p><!-- Direktna objava rezultata --><\/p>\n<div id=\"predajaRezultata\" class=\"no-print\" style=\"margin:25px 0;padding:16px;border:1px solid #285A37;border-radius:8px;\">\n    <button type=\"button\" id=\"posaljiNaOdobrenje\" style=\"display:block;background:#285A37;color:white;border:0;padding:12px 20px;border-radius:5px;cursor:pointer;font-weight:bold;\"><br \/>\n        Objavi rezultate<br \/>\n    <\/button><\/p>\n<p id=\"porukaPredaje\" role=\"status\" aria-live=\"polite\" style=\"font-weight:bold; margin-top:10px;\">\n<\/div>\n<p><script>\ndocument.addEventListener('DOMContentLoaded', function () {\n    const dugme = document.getElementById('posaljiNaOdobrenje');\n    const poruka = document.getElementById('porukaPredaje');<\/p>\n<p>    if (!dugme || !poruka) {\n        console.error('Nedostaje dugme za objavu ili element za poruku.');\n        return;\n    }<\/p>\n<p>    const uzmi = function (id) {\n        const element = document.getElementById(id);\n        return element ? element.value.trim() : '';\n    };<\/p>\n<p>    dugme.addEventListener('click', async function (event) {\n        event.preventDefault();<\/p>\n<p>        \/\/ 1. Provjera obaveznih polja\n        const obaveznaPolja = [\n            ['ciklus', 'Ciklus studija'],\n            ['odsjek', 'Odsjek'],\n            ['studijskiProgram', 'Studijski program'],\n            ['program', 'Naziv studijskog programa'],\n            ['akademska_godina', 'Akademska godina'],\n            ['semestar', 'Semestar'],\n            ['predmet', 'Naziv predmeta'],\n            ['provjera', 'Vrsta provjere znanja'],\n            ['datum', 'Datum provjere'],\n            ['maxBodova', 'Maksimalan broj bodova'],\n            ['minBodova', 'Minimalan broj prolaznih bodova'],\n            ['uvid', 'Termin i mjesto uvida'],\n            ['nastavnik', 'Odgovorni nastavnik']\n        ];<\/p>\n<p>        for (const [id, naziv] of obaveznaPolja) {\n            if (!uzmi(id)) {\n                poruka.style.color = '#c0392b';\n                poruka.textContent =\n                    'Popunite obavezno polje: ' + naziv + '.';<\/p>\n<p>                const polje = document.getElementById(id);\n                if (polje) polje.focus();<\/p>\n<p>                return;\n            }\n        }<\/p>\n<p>        \/\/ 2. Provjera bodova\n        const maxBodova = Number(uzmi('maxBodova'));\n        const minBodova = Number(uzmi('minBodova'));<\/p>\n<p>        if (\n            !Number.isFinite(maxBodova) ||\n            !Number.isFinite(minBodova) ||\n            maxBodova <= 0 ||\n            minBodova < 0 ||\n            minBodova > maxBodova\n        ) {\n            poruka.style.color = '#c0392b';\n            poruka.textContent =\n                'Provjerite maksimalan broj bodova i minimalan broj prolaznih bodova.';\n            return;\n        }<\/p>\n<p>        \/\/ 3. Prikupljanje podataka o studentima\n        const redovi = Array.from(\n            document.querySelectorAll('#studentRows tr')\n        );<\/p>\n<p>        const studenti = redovi.map(function (red) {\n            const indeksPolje = red.querySelector('.index-input');\n            const bodoviPolje = red.querySelector('.points-input');<\/p>\n<p>            return {\n                indeks: indeksPolje ? indeksPolje.value.trim() : '',\n                bodovi: bodoviPolje ? bodoviPolje.value.trim() : '',\n                procenat: (\n                    red.querySelector('.percent-cell')?.textContent || ''\n                ).trim(),\n                status: (\n                    red.querySelector('.status-cell')?.textContent || ''\n                ).trim()\n            };\n        });<\/p>\n<p>        if (\n            studenti.length === 0 ||\n            studenti.some(function (student) {\n                return (\n                    !student.indeks ||\n                    student.bodovi === '' ||\n                    !Number.isFinite(Number(student.bodovi)) ||\n                    Number(student.bodovi) < 0 ||\n                    Number(student.bodovi) > maxBodova\n                );\n            })\n        ) {\n            poruka.style.color = '#c0392b';\n            poruka.textContent =\n                'Unesite ispravan broj indeksa i osvojene bodove za svakog studenta.';\n            return;\n        }<\/p>\n<p>        \/\/ 4. Priprema podataka za WordPress\n        const podaci = {\n            ciklus: uzmi('ciklus'),\n            odsjek: uzmi('odsjek'),\n            studijskiProgram: uzmi('studijskiProgram'),\n            program: uzmi('program'),\n            akademska_godina: uzmi('akademska_godina'),\n            semestar: uzmi('semestar'),\n            predmet: uzmi('predmet'),\n            provjera: uzmi('provjera'),\n            datum: uzmi('datum'),\n            maxBodova: maxBodova,\n            minBodova: minBodova,\n            uvid: uzmi('uvid'),\n            nastavnik: uzmi('nastavnik'),\n            napomena: uzmi('napomena'),\n            mjestoDatum: uzmi('mjestoDatum'),\n            studenti: studenti\n        };<\/p>\n<p>        \/\/ 5. Slanje podataka\n        dugme.disabled = true;\n        poruka.style.color = '#285A37';\n        poruka.textContent = '\u0160aljem rezultate na server...';<\/p>\n<p>        try {\n            const wpApiUrl =\n                window.location.origin +\n                '\/index.php?rest_route=\/ppf\/v1\/objavi-rezultate';<\/p>\n<p>            const odgovor = await fetch(wpApiUrl, {\n                method: 'POST',\n                credentials: 'same-origin',\n                headers: {\n                    'Content-Type': 'application\/json',\n                    'Accept': 'application\/json'\n                },\n                body: JSON.stringify(podaci)\n            });<\/p>\n<p>            let rezultat;<\/p>\n<p>            try {\n                rezultat = await odgovor.json();\n            } catch (e) {\n                throw new Error(\n                    'Server nije vratio ispravan JSON odgovor.'\n                );\n            }<\/p>\n<p>            if (!odgovor.ok) {\n                throw new Error(\n                    rezultat.poruka ||\n                    rezultat.message ||\n                    'Gre\u0161ka servera (HTTP ' + odgovor.status + ').'\n                );\n            }<\/p>\n<p>            if (rezultat.status === 'uspjeh') {\n                poruka.style.color = '#216b3a';\n                poruka.textContent =\n                    'Rezultati su uspje\u0161no sa\u010duvani na serveru.';<\/p>\n<p>                alert('Rezultati ispita su uspje\u0161no sa\u010duvani.');\n            } else {\n                throw new Error(\n                    rezultat.poruka ||\n                    rezultat.message ||\n                    'Server nije potvrdio uspje\u0161an upis rezultata.'\n                );\n            }\n        } catch (greska) {\n            poruka.style.color = '#c0392b';\n            poruka.textContent =\n                'Gre\u0161ka pri objavi: ' + greska.message;\n        } finally {\n            dugme.disabled = false;\n        }\n    });\n});\n<\/script><br \/>\n<!-- SKRIPTA ZA SLANJE U WORDPRESS BAZU (DODATI NA SAM KRAJ) --><br \/>\n<script>\n\/\/ \u010cekamo da se stranica potpuno u\u010dita\ndocument.addEventListener('DOMContentLoaded', function() {\n    \/\/ Pronalazimo gumb na dnu prema tekstu na njemu\n    const dugmad = Array.from(document.querySelectorAll('button'));\n    const dugmeObjavi = dugmad.find(d => d.textContent.includes('Objavi rezultate'));<\/p>\n<p>    if (dugmeObjavi) {\n        \/\/ Kreiramo element za ispis poruke odmah ispod gumba\n        const poruka = document.createElement('p');\n        poruka.id = 'porukaPredaje';\n        poruka.style.fontWeight = 'bold';\n        poruka.style.marginTop = '10px';\n        poruka.style.fontSize = '14px';\n        dugmeObjavi.parentNode.appendChild(poruka);<\/p>\n<p>        dugmeObjavi.addEventListener('click', async function (e) {\n            e.preventDefault();<\/p>\n<p>            const uzmi = id => {\n                const element = document.getElementById(id);\n                return element ? element.value.trim() : '';\n            };<\/p>\n<p>            \/\/ 1. Kontrola obaveznih polja\n            const obaveznaPolja = [\n                ['ciklus', 'Ciklus studija'],\n                ['odsjek', 'Odsjek'],\n                ['studijskiProgram', 'Studijski program'],\n                ['program', 'Naziv studijskog programa'],\n                ['akademska_godina', 'Akademska godina'],\n                ['semestar', 'Semestar'],\n                ['predmet', 'Naziv predmeta'],\n                ['provjera', 'Vrsta provjere znanja'],\n                ['datum', 'Datum provjere'],\n                ['maxBodova', 'Maksimalan broj bodova'],\n                ['minBodova', 'Minimalan broj prolaznih bodova'],\n                ['uvid', 'Termin i mjesto uvida'],\n                ['nastavnik', 'Odgovorni nastavnik']\n            ];<\/p>\n<p>            for (const [id, naziv] of obaveznaPolja) {\n                \/\/ Poku\u0161aj prona\u0107i po ID-u ili po name\/klasi ako ID ne postoji\n                let el = document.getElementById(id) || document.querySelector(`[name=\"${id}\"]`) || document.querySelector(`.${id}`);\n                if (el && !el.value.trim()) {\n                    poruka.style.color = '#c0392b';\n                    poruka.textContent = 'Popunite obavezno polje: ' + naziv + '.';\n                    el.focus();\n                    return;\n                }\n            }<\/p>\n<p>            \/\/ 2. Prikupljanje studenata iz tabele\n            \/\/ Pokrivamo i #studentRows i #tabela_rezultata jer ne znamo ta\u010dan ID iz va\u0161eg koda\n            const redovi = Array.from(document.querySelectorAll('#studentRows tr, #tabela_rezultata tbody tr, table tbody tr'));\n            const studenti = redovi.map(red => {\n                const indeksInput = red.querySelector('.index-input, .broj-indeksa, input[type=\"text\"]');\n                const bodoviInput = red.querySelector('.points-input, .osvojeni-bodovi, input[type=\"number\"]');\n                return {\n                    indeks: indeksInput ? indeksInput.value.trim() : '',\n                    bodovi: bodoviInput ? bodoviInput.value.trim() : '',\n                    procenat: red.querySelector('.percent-cell, td:nth-child(4)')?.textContent.trim() || '',\n                    status: red.querySelector('.status-cell, td:nth-child(5)')?.textContent.trim() || ''\n                };\n            }).filter(s => s.indeks !== ''); \/\/ Preska\u010demo prazne redove<\/p>\n<p>            if (studenti.length === 0) {\n                poruka.style.color = '#c0392b';\n                poruka.textContent = 'Molimo unesite broj indeksa i bodove za barem jednog studenta.';\n                return;\n            }<\/p>\n<p>            \/\/ 3. Pakovanje svih podataka za slanje\n            const podaci = {\n                ciklus: uzmi('ciklus') || document.querySelector('select')?.value || '',\n                odsjek: uzmi('odsjek'),\n                studijskiProgram: uzmi('studijskiProgram'),\n                program: uzmi('program'),\n                akademska_godina: uzmi('akademska_godina'),\n                semestar: uzmi('semestar'),\n                predmet: uzmi('predmet'),\n                provjera: uzmi('provjera'),\n                datum: uzmi('datum'),\n                maxBodova: uzmi('maxBodova'),\n                minBodova: uzmi('minBodova'),\n                uvid: uzmi('uvid'),\n                nastavnik: uzmi('nastavnik'),\n                napomena: uzmi('napomena'),\n                mjestoDatum: uzmi('mjestoDatum'),\n                studenti: studenti\n            };<\/p>\n<p>            dugmeObjavi.disabled = true;\n            poruka.style.color = '#285A37';\n            poruka.textContent = 'Slanje rezultata direktno u WordPress bazu podataka...';<\/p>\n<p>            try {\n                \/\/ Apsolutna putanja koja radi unutar WordPressa\n                const wpApiUrl = window.location.origin + '\/index.php?rest_route=\/ppf\/v1\/objavi-rezultate';<\/p>\n<p>                const odgovor = await fetch(wpApiUrl, {\n                    method: 'POST',\n                    headers: { 'Content-Type': 'application\/json' },\n                    body: JSON.stringify(podaci)\n                });<\/p>\n<p>                if (!odgovor.ok) {\n                    throw new Error('Server javlja gre\u0161ku (Status: ' + odgovor.status + ')');\n                }<\/p>\n<p>                const rezultat = await odgovor.json();<\/p>\n<p>                if (rezultat.status === 'uspjeh') {\n                    poruka.style.color = '#216b3a';\n                    poruka.textContent = '\ud83c\udf89 Rezultati su uspje\u0161no objavljeni i trajno upisani u bazu podataka!';\n                    alert('Uspje\u0161no! Rezultati ispita su sa\u010duvani.');\n                    dugmeObjavi.disabled = false;\n                } else {\n                    throw new Error(rezultat.poruka || 'Gre\u0161ka pri upisu.');\n                }<\/p>\n<p>            } catch (gre\u0161ka) {\n                poruka.style.color = '#c0392b';\n                poruka.textContent = 'Gre\u0161ka pri objavi: ' + gre\u0161ka.message;\n                dugmeObjavi.disabled = false;\n            }\n        });\n    }\n});\n<\/script><\/p>\n<p><\/body><br \/>\n<\/html><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Obrazac za objavu rezultata ispita | PPF UNSA Univerzitet u Sarajevu Poljoprivredno-prehrambeni fakultet REZULTATI PISMENE PROVJERE ZNANJA Op\u0107i podaci o ispitu Sva polja ozna\u010dena zvjezdicom (*) su obavezna. Rezultate mo\u017eete \u0161tampati ili sa\u010duvati kao PDF tek kada unesete sve obavezne podatke i podatke za svakog studenta. Ciklus studija * Odaberite ciklusI (PRVI) CIKLUSII (DRUGI) CIKLUSIII [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-7","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/rezultati.ppf.unsa.ba\/index.php?rest_route=\/wp\/v2\/pages\/7","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rezultati.ppf.unsa.ba\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/rezultati.ppf.unsa.ba\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/rezultati.ppf.unsa.ba\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rezultati.ppf.unsa.ba\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7"}],"version-history":[{"count":4,"href":"https:\/\/rezultati.ppf.unsa.ba\/index.php?rest_route=\/wp\/v2\/pages\/7\/revisions"}],"predecessor-version":[{"id":12,"href":"https:\/\/rezultati.ppf.unsa.ba\/index.php?rest_route=\/wp\/v2\/pages\/7\/revisions\/12"}],"wp:attachment":[{"href":"https:\/\/rezultati.ppf.unsa.ba\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}