summaryrefslogblamecommitdiffstats
path: root/js/grades.js
blob: 5c544fb92a3dee99d3a7c77cd191a70a6a9017a4 (plain) (tree)
1
2
3
4
5


                                                         

                           





































































































































































                                                                                     

                                                                               



































                                                                                                                             
                               
                  
                      











































                                                                                                             






                                                        

       


                                                    







                                                               
const API_ENDPOINT = "https://gimb.tk/test.php";
// const API_ENDPOINT = "http://localhost:5000/test.php";

let checkbox_state = false;

async function checkLogin() {
    localforage.getItem("logged_in").then((value) => {
        // This code runs once the value has been loaded
        // from the offline store.
        if (value !== true) {
            window.location.replace("/index.html");
        }
    }).catch((err) => {
        // This code runs if there were any errors
        console.log(err);
    });
}

// Set loading bar visibility
function setLoading(state) {
    if (state) {
        $("#loading-bar").removeClass("hidden");
    } else {
        $("#loading-bar").addClass("hidden");
    }
}

async function loadGrades(force_refresh = false) {
    setLoading(true);

    let promises_to_run = [
        localforage.getItem("username").then((value) => {
            username = value;
        }),
        localforage.getItem("password").then((value) => {
            password = value;
        }),
        localforage.getItem("grades").then((value) => {
            grades = value;
        })
    ];

    await Promise.all(promises_to_run);

    // If we don't have a list of grades, fetch it
    if (grades === null || grades === [] || force_refresh) {

        $.ajax({
            url: API_ENDPOINT,
            crossDomain: true,

            data: {
                "u": username,
                "p": password,
                "m": "fetchocene"
            },
            dataType: "json",

            cache: false,
            type: "GET",

            success: (data) => {
                // If data is null, the request failed
                if (data === null) {
                    M.toast({ html: "Request failed!" });
                    setLoading(false);
                } else {
                    // Save grades & populate view
                    localforage.setItem("grades", data).then((value) => {
                        grades = value;
                        displayGrades();
                        setLoading(false);
                    });
                }
            },

            error: () => {
                M.toast({ html: "No internet connection!" });
                setLoading(false);
            }

        });

    } else {
        displayGrades();
        setLoading(false);
    }
}

function displayGrades() {
    let grades_by_subject = {};
    grades.forEach((grade, index) => {
        if (!(grade["predmet"] in grades_by_subject)) {
            grades_by_subject[grade["predmet"]] = [];
        }
        let grade_object = {
            date: grade["datum"],
            teacher: grade["profesor"],
            subject: grade["predmet"],
            title: grade["naslov"],
            type: grade["vrsta"],
            term: grade["rok"],
            grade: grade["ocena"],
            temporary: grade["zacasna"],
            index: index
        }
        grades_by_subject[grade["predmet"]].push(grade_object);
    });

    let root_element = document.getElementById("grades-collapsible");

    Object.keys(grades_by_subject).forEach((subject) => {
        // Create root element for a subject entry
        let subject_entry = document.createElement("li");
        // Create subject collapsible header
        let subject_header = document.createElement("div");
        subject_header.classList.add("collapsible-header");
        subject_header.classList.add("collapsible-header-root");
        // Create header text element
        let subject_header_text = document.createElement("span");
        subject_header_text.innerText = subject;

        // Create collection for displaying individuals grades
        let subject_body = document.createElement("div");
        subject_body.className = "collapsible-body";
        let subject_body_root = document.createElement("ul");
        subject_body_root.className = "collection";

        // Setup variables for calculating average
        let grade_sum = 0;
        let grade_tot = 0;

        grades_by_subject[subject].forEach((grade) => {
            // Create element for individual grade
            let grade_node = document.createElement("li");
            grade_node.className = "collection-item";
            grade_node.classList.add("collection-item")
            grade_node.classList.add("grade-node");
            grade_node.dataset["index"] = grade["index"];
            let grade_node_div = document.createElement("div");

            // Node for date and subject text
            let grade_text = document.createElement("span");
            // Node for the actual number
            let grade_number = document.createElement("div");
            grade_number.className = "secondary-content";

            // Apply different style, if the grade is temporary
            if (grade["temporary"]) {
                // Styling for text
                let grade_text_italic = document.createElement("i");
                grade_text_italic.innerText = grade["date"] + " - " + grade["title"];
                grade_text.appendChild(grade_text_italic);

                // Styling for number
                let grade_number_italic = document.createElement("i");
                grade_number_italic.innerText = grade["grade"].toString();
                grade_number.appendChild(grade_number_italic);
            } else {
                // Text
                grade_text.innerText = grade["date"] + " - " + grade["title"];
                // Number
                grade_number.innerText = grade["grade"].toString();
            }

            grade_node_div.appendChild(grade_text);
            grade_node_div.appendChild(grade_number);

            grade_node.appendChild(grade_node_div);


            // Count the grade only if it's not temporary or explicitly enabled
            if (!grade["temporary"] || !checkbox_state) {
                grade_sum += grade["grade"];
                grade_tot += 1;
            }

            subject_body_root.appendChild(grade_node);

        });

        let grade_average = (grade_tot === 0) ? "N/A" : (Math.round(((grade_sum / grade_tot) + Number.EPSILON) * 100) / 100);
        let subject_header_average = document.createElement("div");
        subject_header_average.className = "collapsible-header-right";
        subject_header_average.innerText = grade_average.toString();

        subject_header.appendChild(subject_header_text);
        subject_header.appendChild(subject_header_average);

        subject_body.append(subject_body_root);

        subject_entry.append(subject_header);
        subject_entry.append(subject_body);

        root_element.append(subject_entry);
    });

    $("#grades-collapsible").append(root_element);

    refreshClickHandlers();
}

function clearGrades() {
    const table = document.getElementById("grades-collapsible");
    while (table.firstChild) {
        table.removeChild(table.firstChild);
    }
}

function refreshGrades(force) {
    clearGrades();
    loadGrades(force);
}

function refreshClickHandlers() {
    $("#grades-collapsible").find(".collection-item.grade-node").click(function () {
        let grade_obj = grades[parseInt(this.dataset["index"])];
        document.getElementById("grade-header").innerText = grade_obj["predmet"] + ": " + grade_obj["ocena"];
        document.getElementById("grade-date").innerText = grade_obj["datum"];
        document.getElementById("grade-title").innerText = grade_obj["naslov"];
        document.getElementById("grade-type").innerText = "Type: " + grade_obj["vrsta"];

        let term_element = document.getElementById("grade-term");
        if (grade_obj["rok"] !== "") {
            term_element.innerText = "Term: " + grade_obj["rok"];
            term_element.style["display"] = "";
        } else {
            term_element.style["display"] = "none";
        }

        document.getElementById("grade-teacher").innerText = "Teacher: " + grade_obj["profesor"];

        let temporary_object = document.getElementById("grade-temporary");
        let temporary_object_root = document.getElementById("grade-temporary-root");
        if (grade_obj["zacasna"]) {
            temporary_object.innerText = "(zacasna)";
            temporary_object_root.style["display"] = "";
        } else {
            temporary_object_root.style["display"] = "none";
        }

        const modal = document.querySelectorAll('.side-modal')[0];
        M.Sidenav.getInstance(modal).open();
    });
}

// Initialization code
document.addEventListener("DOMContentLoaded", async () => {
    checkLogin();
    await loadGrades();

    let coll_elem = document.querySelectorAll('.collapsible');
    let coll_instance = M.Collapsible.init(coll_elem, {});

    // Setup refresh handler
    $("#refresh-icon").click(function () {
        refreshGrades(true);
    });

    // Setup checkbox handler
    $("#permanent-grades-checkbox").change(function () {
        checkbox_state = this.checked;
        refreshGrades(false);
    });

    let elems = document.querySelectorAll('.modal');
    let instances = M.Modal.init(elems, {});

    // Setup side menu
    const menus = document.querySelectorAll('.side-menu');
    M.Sidenav.init(menus, { edge: 'right', draggable: true });

    // Setup side modal
    const modals = document.querySelectorAll('.side-modal');
    M.Sidenav.init(modals, { edge: 'left', draggable: false });
});