Skip to content
Snippets Groups Projects
candidate-lists.js 23.3 KiB
Newer Older
  • Learn to ignore specific revisions
  • // Imports
    import * as Auth from "/services/auth/auth.js";
    
    import * as Common from "/services/common/common.js";
    import * as Messages from "/services/messages/messages.js";
    
    import * as AreaModel from "/services/model/area-model.js";
    
    import * as PartyModel from "/services/model/party-model.js";
    import * as CandidateListModel from "/services/model/candidateList-model.js";
    
    import * as CandidateModel from "/services/model/candidate-model.js";
    
    import * as ElectionModel from "/services/model/election-model.js";
    import * as RoundModel from "/services/model/round-model.js";
    
    import { Delete } from "/services/common/delete.js";
    
    
    // DOM elements
    
    export async function mount(where, parent) {
      const candidateListComponent = new CandidateList(parent);
      await candidateListComponent.mount(where);
      return candidateListComponent;
    }
    
    class CandidateList {
      constructor(parent) {
        this.method = null;
        this.parent = parent;
    
        this.AreaModel = AreaModel.getAreaModel();
    
        this.PartyModel = PartyModel.getPartyModel();
        this.CandidateListModel = CandidateListModel.getCandidateListModel();
    
        this.CandidateModel = CandidateModel.getCandidateModel();
    
        this.ElectionModel = ElectionModel.getElectionModel();
        this.RoundModel = RoundModel.getRoundModel();
    
      }
    
      async mount(where) {
    
        this.AreaModel.current_user = await Auth.GetUser();
    
        this.PartyModel.current_user = await Auth.GetUser();
        this.CandidateListModel.current_user = await Auth.GetUser();
    
        this.CandidateModel.current_user = await Auth.GetUser();
    
        this.ElectionModel.current_user = await Auth.GetUser();
        this.RoundModel.current_user = await Auth.GetUser();
    
        const mountpoint = where;
        document.getElementById(mountpoint).innerHTML = /* HTML */ `
    
          <header id="dropdown-candidate-lists" class="card-header clickable">
    
            <p id="candidate-list-title" class="card-header-title">
    
              Liste des candidats par circonscription
    
            <a>
              <span class="icon is-large">
    
                <i class="fas fa-2x fa-caret-down"></i>
    
          <div id="candidate-lists-dropdown-content" class="columns card-content">
    
            <div class="column">
              <div id="areas-round"></div>
    
            <div class="column">
              <div id="candidate-lists-list"></div>
            </div>
    
            <div class="column is-two-thirds">
    
              <div id="candidate-list" class="card-no-hover"></div>
    
            </div>
          </div>
    
        this.mountModal("candidateList-modal");
    
        this.mountModalClone("candidateList-clone-modal");
    
        this.handleDom();
    
    
      areaTemplate(area) {
        return /* HTML */ `<div class="card card-list">
    
          <div id="areas-area-${area.ID}" class="card-content clickable">
    
            <div class="content">
              <nav class="level">
                <div class="level-left">
                  ${area.Name} (Nombre de siège : ${area.SeatNumber})
                </div>
              </nav>
            </div>
          </div>
        </div>`;
      }
    
    
      candidateListTemplate(candidateList) {
        return /* HTML */ `<div class="card card-list">
          <div
            id="candidateLists-candidateList-${candidateList.ID}"
    
            class="card-content clickable"
    
          >
            <div class="content">
              <nav class="level">
                <div
                  id="candidateLists-candidateList-desc-${candidateList.ID}"
                  class="level-left"
                >
                  ${candidateList.Name}
                </div>
                <div class="level-right">
                  <a
                    id="candidateLists-candidateList-edit-${candidateList.ID}"
                    class="button is-link is-small"
                    title="Modifier"
                  >
                    <span class="icon is-small">
                      <i class="fas fa-pen"></i>
                    </span>
                  </a>
                  <a
                    id="candidateLists-candidateList-delete-${candidateList.ID}"
                    class="button is-danger is-small"
                    title="Supprimer"
                  >
                    <span class="icon is-small">
    
                      <i class="fas fa-trash"></i>
    
                    </span>
                  </a>
                </div>
              </nav>
            </div>
          </div>
        </div>`;
      }
    
    
      candidateListToCloneTemplate(candidateList) {
        return /* HTML */ `<div class="card card-list">
          <div
            id="candidateLists-candidateListToClone-${candidateList.ID}"
            class="card-content clickable"
          >
            <div class="content">
              <nav class="level">
                <div
                  id="candidateLists-candidateList-desc-${candidateList.ID}"
                  class="level-left"
                >
                  ${candidateList.Name}
                </div>
              </nav>
            </div>
          </div>
        </div>`;
      }
    
    
      mountModal(where) {
        const mountpoint = where;
        document.getElementById(mountpoint).innerHTML = /* HTML */ `
          <div class="modal-background"></div>
          <div class="modal-card" id="candidateList-modal-card">
            <header class="modal-card-head">
    
              <p class="modal-card-title">Ajout/modification d'une liste</p>
    
              <button
                class="delete"
                aria-label="close"
                id="candidateList-modal-close"
              ></button>
            </header>
            <section class="modal-card-body">
              <div class="field">
                <div class="control">
                  <input
                    class="input"
    
                    type="hidden"
    
                    id="candidateList-modal-id"
                    disabled
                  />
                </div>
              </div>
              <div class="field">
                <label>Name</label>
                <div class="control">
                  <input class="input" type="text" id="candidateList-modal-name" />
                </div>
              </div>
              <div class="field">
                <label>Parti</label><br />
                <div class="control select">
    
                  <select name="party" id="candidateList-modal-party"></select>
    
                </div>
              </div>
            </section>
            <footer class="modal-card-foot">
              <button id="candidateList-modal-save" class="button is-success">
                Sauvegarder
              </button>
              <button id="candidateList-modal-cancel" class="button">
                Annuler
              </button>
            </footer>
          </div>
        `;
      }
    
    
      mountModalClone(where) {
        const mountpoint = where;
        document.getElementById(mountpoint).innerHTML = /* HTML */ `
          <div class="modal-background"></div>
          <div class="modal-card" id="candidateList-clone-modal-card">
            <header class="modal-card-head">
              <p class="modal-card-title">Importer une liste</p>
              <button
                class="delete"
                aria-label="close"
                id="candidateList-clone-modal-close"
              ></button>
            </header>
            <section id="candidateLists-toclone" class="modal-card-body"></section>
          </div>
        `;
      }
    
    
      async displayCandidates() {
        document.getElementById("candidate-list").innerHTML = /* HTML */ `<div
          class="table-container"
        >
    
          <table class="table is-bordered is-narrow is-fullwidth">
    
            <thead>
              <tr class="is-selected">
                <th hidden>Id</th>
                <th>Nom complet</th>
                <th>Rang</th>
                <th>Conseiller communautaire</th>
                <th>Date de naissance</th>
                <th>Incompatibilité potentielle</th>
                <th>Refusé</th>
                <th>Supprimé</th>
                <th>Actions</th>
              </tr>
            </thead>
            <tbody id="candidates"></tbody>
          </table>
        </div> `;
    
        let candidates = await this.updateCandidates();
    
    Alexis POYEN's avatar
    Alexis POYEN committed
        candidates.sort(function (a, b) {
          return a.Rank > b.Rank;
        });
    
        const markup = candidates
          .map((candidate) => this.candidateTemplate(candidate))
          .join("");
        document.getElementById("candidates").innerHTML = markup;
    
    
    Alexis POYEN's avatar
    Alexis POYEN committed
        let newRank = 1;
        candidates.forEach((candidate) => {
          if (candidate.Rank >= newRank) newRank = candidate.Rank + 1;
        });
    
    
        let newCandidate = {
    
          ID: 0,
          FullName: "",
    
    Alexis POYEN's avatar
    Alexis POYEN committed
          Rank: newRank,
    
          CommunityCounseller: false,
          Birthdate: "2000-01-01",
          PotentialIncompatibility: false,
          Refused: false,
          Removed: false,
        };
        document.getElementById("candidates").innerHTML += this.candidateTemplate(
    
          newCandidate
    
        );
        document
          .getElementById(`candidates-candidate-edit-0`)
          .addEventListener("click", function () {
            candidateListHandler.method = "POST";
    
            candidateListHandler.saveCandidate(newCandidate.ID);
    
          });
        document.getElementById(`candidates-candidate-delete-0`).remove();
    
        let candidateListHandler = this;
        candidates.map((candidate) => {
          document
            .getElementById(`candidates-candidate-edit-${candidate.ID}`)
            .addEventListener("click", function () {
              candidateListHandler.method = "PUT";
              candidateListHandler.saveCandidate(candidate.ID);
            });
          document
            .getElementById(`candidates-candidate-delete-${candidate.ID}`)
            .addEventListener("click", function () {
              new Delete(() => {
                candidateListHandler.deleteCandidate(candidate);
              });
            });
        });
      }
    
      candidateTemplate(candidate) {
        return /* HTML */ `
          <tr id="candidates-candidate-${candidate.ID}">
            <td hidden>
              <input
                class="input"
                type="number"
                id="${candidate.ID}-candidate-id"
                value="${candidate.ID}"
                disabled
              />
            </td>
            <td>
              <input
                class="input"
                type="text"
                id="${candidate.ID}-candidate-fullname"
                value="${candidate.FullName}"
              />
            </td>
            <td>
              <input
                class="input"
                type="number"
                id="${candidate.ID}-candidate-rank"
                value="${candidate.Rank}"
              />
            </td>
            <td>
              <input
                type="checkbox"
                id="${candidate.ID}-candidate-community-counseller"
                ${candidate.CommunityCounseller ? "checked" : ""}
              />
            </td>
            <td>
              <input
                class="input"
                type="date"
                id="${candidate.ID}-candidate-birthdate"
                value="${candidate.Birthdate}"
              />
            </td>
            <td>
              <input
                type="checkbox"
                id="${candidate.ID}-candidate-potential-incompatibility"
                ${candidate.PotentialIncompatibility ? "checked" : ""}
              />
            </td>
            <td>
              <input
                type="checkbox"
                id="${candidate.ID}-candidate-refused"
                ${candidate.Refused ? "checked" : ""}
              />
            </td>
            <td>
              <input
                type="checkbox"
                id="${candidate.ID}-candidate-removed"
                ${candidate.Removed ? "checked" : ""}
              />
            </td>
            <td>
              <a
                id="candidates-candidate-edit-${candidate.ID}"
                class="button is-success is-small"
    
                title="Valider"
    
              >
                <span class="icon is-small">
                  <i class="fas fa-check"></i>
                </span>
              </a>
              <a
                id="candidates-candidate-delete-${candidate.ID}"
                class="button is-danger is-small"
    
                title="Supprimer"
    
              >
                <span class="icon is-small">
    
                  <i class="fas fa-trash"></i>
    
      handleDom() {
        let candidateListHandler = this;
    
        document
          .getElementById(`candidateList-modal-close`)
          .addEventListener("click", function () {
            Common.toggleModal("candidateList-modal", "candidateList-modal-card");
          });
        document
          .getElementById(`candidateList-modal-cancel`)
          .addEventListener("click", function () {
            Common.toggleModal("candidateList-modal", "candidateList-modal-card");
          });
    
        document
          .getElementById(`candidateList-clone-modal-close`)
          .addEventListener("click", function () {
            Common.toggleModal(
              "candidateList-clone-modal",
              "candidateList-clone-modal-card"
            );
          });
    
        document
          .getElementById(`candidateList-modal-save`)
          .addEventListener("click", async function () {
            if (
              document.getElementById("candidateList-modal-party").value === "0"
            ) {
              Messages.Show("is-danger", "Veuillez sélectionner un parti.");
              return;
            }
            await candidateListHandler.saveCandidateList();
          });
      }
    
    
      async displayAreas() {
    
        document.getElementById("areas-round").innerHTML = /* HTML */ `<h5
          class="title is-5"
        >
          Circonscriptions
        </h5>`;
    
        let candidateListHandler = this;
        let areas = await this.updateAreas();
        const markup = areas.map((area) => this.areaTemplate(area)).join("");
    
        document.getElementById("areas-round").innerHTML += markup;
    
    
        areas.map((area) => {
          document
            .getElementById(`areas-area-${area.ID}`)
            .addEventListener("click", async function () {
    
              candidateListHandler.emptyCandidateList();
    
              await candidateListHandler.activateArea(area);
              await candidateListHandler.displayCandidateLists();
            });
        });
    
    
        this.emptyCandidateList();
    
      }
    
      async updateAreas() {
        let candidateListHandler = this;
        let areas = await this.AreaModel.getAreas();
        return areas.filter(function (area) {
          return area.ElectionID == candidateListHandler.round.ElectionID;
        });
      }
    
    
      async activateArea(areaToActivate) {
        this.area = areaToActivate;
        let areas = await this.updateAreas();
        areas.forEach((area) => {
          document
            .getElementById(`areas-area-${area.ID}`)
            .classList.remove("active-card");
        });
        document
          .getElementById(`areas-area-${areaToActivate.ID}`)
          .classList.add("active-card");
      }
    
    
      async activateCandidateList(candidateListToActivate) {
        this.candidateList = candidateListToActivate;
        let candidateLists = await this.updateCandidateLists();
        candidateLists.forEach((candidateList) => {
          document
            .getElementById(`candidateLists-candidateList-${candidateList.ID}`)
            .classList.remove("active-card");
        });
        document
    
          .getElementById(
            `candidateLists-candidateList-${candidateListToActivate.ID}`
          )
    
          .classList.add("active-card");
    
        this.displayCandidates();
    
    
      async displayCandidateLists() {
        let candidateListHandler = this;
        let candidateLists = await this.updateCandidateLists();
    
        document.getElementById("candidate-lists-list").innerHTML = /* HTML */ `<h5
            class="title is-5"
          >
            Listes
          </h5>
    
          <button
            id="candidate-list-new"
            class="button large-button is-success"
            title="Ajouter une liste"
          >
    
            <span class="icon is-small">
              <i class="fas fa-plus"></i>
            </span>
    
          </button>
          <button
            id="candidate-list-clone"
            class="button large-button is-primary"
            title="Importer une liste"
          >
            <span class="icon is-small">
              <i class="fas fa-download"></i>
            </span>
    
          </button>`;
    
        const markup = candidateLists
          .map((candidateList) => this.candidateListTemplate(candidateList))
          .join("");
    
    Alexis POYEN's avatar
    Alexis POYEN committed
        document.getElementById("candidate-lists-list").innerHTML += markup;
    
        candidateLists.map(async (candidateList) => {
          let party = await this.PartyModel.getParty(candidateList.PartyID);
          document.getElementById(
            `candidateLists-candidateList-desc-${candidateList.ID}`
          ).innerHTML += "(" + party.Name + ")";
          document
            .getElementById(`candidateLists-candidateList-edit-${candidateList.ID}`)
            .addEventListener("click", function () {
              candidateListHandler.editCandidateList(candidateList);
            });
          document
            .getElementById(
              `candidateLists-candidateList-delete-${candidateList.ID}`
            )
            .addEventListener("click", function () {
              new Delete(() => {
                candidateListHandler.deleteCandidateList(candidateList);
              });
            });
    
          document
            .getElementById(`candidateLists-candidateList-${candidateList.ID}`)
            .addEventListener("click", async function () {
              await candidateListHandler.activateCandidateList(candidateList);
              await candidateListHandler.displayCandidates();
            });
    
    Alexis POYEN's avatar
    Alexis POYEN committed
    
        document
          .getElementById(`candidate-list-new`)
          .addEventListener("click", function () {
            candidateListHandler.newCandidateList();
          });
    
    
        document
          .getElementById(`candidate-list-clone`)
          .addEventListener("click", function () {
            candidateListHandler.cloneCandidateListModal();
          });
    
      }
    
      async updateCandidateLists() {
        let candidateListHandler = this;
        let candidateLists = await this.CandidateListModel.getCandidateLists();
        return candidateLists.filter(function (candidateList) {
    
          return (
            candidateList.AreaID == candidateListHandler.area.ID &&
            candidateList.RoundID == candidateListHandler.round.ID
          );
    
      async updateCandidates() {
        let candidateListHandler = this;
        let candidates = await this.CandidateModel.getCandidates();
        return candidates.filter(function (candidate) {
          return candidate.CandidateListID == candidateListHandler.candidateList.ID;
        });
      }
    
    
      async newCandidateList() {
        this.method = "POST";
        await this.refreshParties();
        document.getElementById("candidateList-modal-id").value = null;
        document.getElementById("candidateList-modal-party").value = null;
        document.getElementById("candidateList-modal-name").value = null;
        Common.toggleModal("candidateList-modal", "candidateList-modal-card");
    
      async cloneCandidateListModal() {
        let election = await this.ElectionModel.getElection(this.area.ID);
        let rounds = await this.RoundModel.getRounds();
        rounds = rounds.filter((round) => round.ElectionID == election.ID);
        let roundsID = [];
        rounds.forEach((round) => {
          if (this.round.ID !== round.ID) roundsID.push(round.ID);
        });
        let candidateLists = await this.CandidateListModel.getCandidateLists();
        candidateLists = candidateLists.filter(
          (candidateList) =>
            candidateList.AreaID == this.area.ID &&
            roundsID.includes(candidateList.RoundID)
        );
        Common.toggleModal(
          "candidateList-clone-modal",
          "candidateList-clone-modal-card"
        );
    
        const markup = candidateLists
          .map((candidateList) => this.candidateListToCloneTemplate(candidateList))
          .join("");
        document.getElementById("candidateLists-toclone").innerHTML = markup;
    
        candidateLists.map((candidateList) => {
          document
            .getElementById(
              `candidateLists-candidateListToClone-${candidateList.ID}`
            )
            .addEventListener("click", async () => {
              this.cloneCandidateList(candidateList);
              Common.toggleModal(
                "candidateList-clone-modal",
                "candidateList-clone-modal-card"
              );
            });
        });
      }
    
    
      async editCandidateList(candidateList) {
        this.method = "PUT";
        await this.refreshParties();
        document.getElementById("candidateList-modal-id").value = candidateList.ID;
        document.getElementById("candidateList-modal-party").value =
          candidateList.PartyID;
        document.getElementById("candidateList-modal-name").value =
          candidateList.Name;
        Common.toggleModal("candidateList-modal", "candidateList-modal-card");
      }
    
      async refreshParties() {
        let selectParties = document.getElementById("candidateList-modal-party");
        let parties = await this.PartyModel.getParties();
        for (let i = selectParties.options.length - 1; i >= 0; i--) {
          selectParties.remove(i);
        }
    
        let el = document.createElement("option");
        el.textContent = "Veuillez sélectionner un parti";
        el.value = 0;
        selectParties.appendChild(el);
        parties.forEach((party) => {
          el = document.createElement("option");
          el.textContent = party.Name;
          el.value = party.ID;
          selectParties.appendChild(el);
        });
      }
    
      async saveCandidateList() {
        if (this.method == "POST")
          document.getElementById("candidateList-modal-id").value = null;
    
    
        if (
          this.CandidateListModel.checkInputs(
            this.method,
            parseInt(document.getElementById("candidateList-modal-id").value),
            document.getElementById("candidateList-modal-name").value,
            parseInt(document.getElementById("candidateList-modal-party").value)
          )
        ) {
          let candidateList = await this.CandidateListModel.saveCandidateList(
            this.method,
            parseInt(document.getElementById("candidateList-modal-id").value),
            document.getElementById("candidateList-modal-name").value,
            parseInt(document.getElementById("candidateList-modal-party").value),
            this.round.ID,
            this.area.ID
          );
          await this.displayCandidateLists();
          Common.toggleModal("candidateList-modal", "candidateList-modal-card");
          this.activateCandidateList(candidateList);
          return candidateList;
        }
    
      async deleteCandidateList(candidateList) {
        await this.CandidateListModel.deleteCandidateList(candidateList.ID);
        await this.displayCandidateLists();
    
        this.emptyCandidate();
        this.displayCandidateLists();
    
      }
    
      async saveCandidate(candidateID) {
        let candidate = await this.CandidateModel.saveCandidate(
          this.method,
          candidateID,
          this.candidateList.ID,
          document.getElementById(candidateID + "-candidate-fullname").value,
          parseInt(document.getElementById(candidateID + "-candidate-rank").value),
          document.getElementById(candidateID + "-candidate-community-counseller")
            .checked,
          document.getElementById(candidateID + "-candidate-birthdate").value,
          document.getElementById(
            candidateID + "-candidate-potential-incompatibility"
          ).checked,
          document.getElementById(candidateID + "-candidate-refused").checked,
          document.getElementById(candidateID + "-candidate-removed").checked
        );
        await this.displayCandidates();
        return candidate;
      }
    
      async deleteCandidate(candidate) {
        await this.CandidateModel.deleteCandidate(candidate.ID);
        await this.displayCandidates();
    
      async cloneCandidateList(candidateList) {
        console.log(candidateList);
    
        let candidateListCloned = await this.CandidateListModel.saveCandidateList(
          "POST",
          null,
          candidateList.Name,
          candidateList.PartyID,
          this.round.ID,
          this.area.ID
        );
    
        for (let i in candidateList.Candidates) {
          await this.CandidateModel.saveCandidate(
            "POST",
            null,
            candidateListCloned.ID,
            candidateList.Candidates[i].FullName,
            candidateList.Candidates[i].Rank,
            candidateList.Candidates[i].CommunityCounseller,
            candidateList.Candidates[i].Birthdate,
            candidateList.Candidates[i].PotentialIncompatibility,
            candidateList.Candidates[i].Refused,
            candidateList.Candidates[i].Removed
          );
        }
        await this.displayCandidateLists();
        this.activateCandidateList(candidateListCloned);
        return candidateListCloned;
      }
    
    
      emptyCandidateList() {
        this.area = null;
        document.getElementById("candidate-lists-list").innerHTML = "";
    
        this.emptyCandidate();
    
      emptyCandidate() {
    
        this.candidateList = null;
        document.getElementById("candidate-list").innerHTML = "";
      }