Skip to content
Snippets Groups Projects
results-section.js 16.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • // Imports
    
    import * as Auth from "/services/auth/auth.js";
    
    import * as results from "/services/election/calculate-election-generic.js";
    
    import * as PartyModel from "/services/model/party-model.js";
    import * as Scroller from "/services/common/scroller.js";
    
    
    export async function mount(where, round) {
      const resultComponent = new ResultComponent(round);
      await resultComponent.mount(where);
    
      await resultComponent.calculateResults();
    
      resultComponent.displayResults();
    
    }
    
    class ResultComponent {
      constructor(round) {
        this.round = round;
    
        this.PartyModel = PartyModel.getPartyModel();
    
      }
    
      async mount(where) {
    
        this.PartyModel.current_user = await Auth.GetUser();
    
        const mountpoint = where;
        document.getElementById(mountpoint).innerHTML = /* HTML */ `
          <div class="tabs is-boxed is-toggle is-fullwidth">
            <ul>
              <li id="areas" class="is-active">
                <a>
                  <span>Circonscriptions</span>
                </a>
              </li>
              <li id="sections">
                <a>
                  <span>Villes</span>
                </a>
              </li>
            </ul>
          </div>
          <div class="control filter">
            <label class="radio">
    
              <input type="radio" name="filter" value="partial" checked />
    
              Partiel
            </label>
            <label class="radio">
    
              <input type="radio" name="filter" value="completed" />
    
              Complété
            </label>
            <label class="radio">
    
              <input type="radio" name="filter" value="validated" />
    
              Validé
            </label>
          </div>
          <div class="columns">
            <div class="column is-half">
              <div id="map-section" class="card-no-hover">
                <header class="card-header">
                  <p class="card-header-title">
                    Carte
                  </p>
                  <button id="zoom-map" class="button is-success">
                    <span class="icon is-small">
                      <i class="fas fa-search"></i>
                    </span>
                  </button>
                </header>
                <div class="card-content">
                  <div id="round-list" class="content">
                    La carte du tour
                  </div>
                </div>
              </div>
            </div>
            <div class="column">
              <div id="news-flow-section" class="card-no-hover">
                <header class="card-header">
                  <p class="card-header-title">
                    Actualités
                  </p>
                  <button id="zoom-news-flow" class="button is-success">
                    <span class="icon is-small">
                      <i class="fas fa-search"></i>
                    </span>
                  </button>
                </header>
                <div class="card-content">
    
                  <div id="news-flow" class="content">
    
                    Flux d'actualité
                  </div>
                </div>
              </div>
              <div id="results-section" class="card-no-hover" ">
              <header class="card-header">
                <p class="card-header-title">
                  Résultats
                </p>
                <button id="zoom-results" class="button is-success">
                  <span class="icon is-small">
                    <i class="fas fa-search"></i>
                  </span>
                </button>
              </header>
              <div class="card-content">
    
                <div id="detailed-results" class="content">
    
                  <div class="control select">
                    <select id="select-areas" class="input"></select>
                  </div>
                  <div class="control select">
                    <select id="select-sections" class="input"></select>
                  </div>
                  <div id="zone-results"></div>
                  <div id="zone-detaileds-results" style="display:none"></div>
    
                </div>
              </div>
            </div>
          </div>
        `;
    
        this.calculator = await results.mountCalculator(this.round);
    
        this.handleDom();
        document.getElementById("areas").click();
    
      }
    
      resultFlowTemplate(zone) {
        return /* HTML */ `<div class="card-list card-no-hover">
          <div class="card-content">
            <div id="flow-content-${zone.ID}" class="content">
              <h5 class="title is-5">${zone.Name}</h5>
            </div>
          </div>
        </div>`;
      }
    
    
      progressBarTemplate(candidateList, color) {
    
        return /* HTML */ `<div class="progressBar">
          <div
            class="progressBarValue"
    
            style="background-color : ${color}; width : ${candidateList.Percentage}%"
    
          >
            ${candidateList.Name +
            " (" +
    
            (candidateList.VoiceNumber != null
              ? candidateList.VoiceNumber + " votes soit : "
              : "") +
    
            candidateList.Percentage +
            "%)"}
          </div>
        </div>`;
    
      showWarningResults(text) {
        return /* HTML */ `<br />
          <article class="message is-warning">
            <div class="message-header">
              <p>Warning</p>
            </div>
            <div class="message-body">
              ${text}
            </div>
          </article>`;
      }
    
    
      handleDom() {
    
        let resultHandler = this;
    
        document.getElementById("areas").addEventListener("click", function () {
    
          resultHandler.zone = "areas";
          resultHandler.calculateResults();
          resultHandler.displayResults();
    
          document.getElementById("sections").setAttribute("class", "");
          document.getElementById("areas").setAttribute("class", "is-active");
        });
        document.getElementById("sections").addEventListener("click", function () {
    
          resultHandler.zone = "sections";
          resultHandler.calculateResults();
          resultHandler.displayResults();
    
          document.getElementById("areas").setAttribute("class", "");
          document.getElementById("sections").setAttribute("class", "is-active");
        });
    
        document.getElementById("zoom-map").addEventListener("click", function () {
          resultHandler.zoomMap();
        });
        document
          .getElementById("zoom-news-flow")
          .addEventListener("click", function () {
            resultHandler.zoomNewsFlow();
          });
        document
          .getElementById("zoom-results")
          .addEventListener("click", function () {
            resultHandler.zoomResults();
          });
    
    
        let radioButtons = document.getElementsByName("filter");
        for (var i = 0; i < radioButtons.length; i++) {
    
          radioButtons[i].addEventListener("click", async (e) => {
            await this.calculateResults();
            this.displayResults();
    
    
        document.addEventListener(
          "input",
          function __listener(event) {
            if (event.target.id == "select-areas") {
              if (event.target.value != 0) {
                let area = resultHandler.results.areasResults.find(
                  (area) => area.ID == event.target.value
                );
    
                if (resultHandler.zone === "areas")
                  resultHandler.displayZoneResults(area);
                else if (resultHandler.zone === "sections") {
                  resultHandler.refreshSections(area);
                  resultHandler.displayZoneResults(area.Sections[0]);
                }
              }
            } else if (event.target.id == "select-sections") {
              let area = resultHandler.results.areasResults.find(
                (area) => area.ID == document.getElementById("select-areas").value
              );
              let section = area.Sections.find(
                (section) => section.ID == event.target.value
              );
              resultHandler.displayZoneResults(section);
            }
          },
          false
        );
    
      }
    
      zoomMap() {
        let resultHandler = this;
        document.getElementById("map-section").parentElement.className =
          "column is-full";
        document.getElementById("zoom-map").addEventListener("click", function () {
          resultHandler.unZoom();
        });
      }
    
      zoomNewsFlow() {
        let resultHandler = this;
        document.getElementById("news-flow-section").parentElement.className =
          "column is-full";
    
        document.getElementById("news-flow-section").style.height = "70vh";
    
        document.getElementById("map-section").parentElement.className = "column";
        document.getElementById("map-section").parentElement.style.display = "none";
        document.getElementById("results-section").style.display = "none";
        document
          .getElementById("zoom-news-flow")
          .addEventListener("click", function () {
            resultHandler.unZoom();
          });
      }
    
    
        let resultHandler = this;
        document.getElementById("results-section").parentElement.className =
          "column is-full";
    
        document.getElementById("results-section").style.height = "70vh";
    
        document.getElementById("map-section").parentElement.className = "column";
        document.getElementById("map-section").parentElement.style.display = "none";
        document.getElementById("news-flow-section").style.display = "none";
        document
          .getElementById("zoom-results")
          .addEventListener("click", function () {
            resultHandler.unZoom();
          });
    
        document.getElementById("zone-detaileds-results").style.display = "block";
    
      }
    
      unZoom() {
        document.getElementById("map-section").parentElement.className =
          "column is-half";
        document.getElementById("news-flow-section").style.height = "45vh";
    
        document.getElementById("results-section").style.height = "25vh";
    
        document.getElementById("news-flow-section").parentElement.className =
          "column is-half";
        document.getElementById("map-section").parentElement.style.display =
          "block";
        document.getElementById("results-section").style.display = "block";
        document.getElementById("news-flow-section").style.display = "block";
    
        document.getElementById("zone-detaileds-results").style.display = "none";
    
    
        this.handleDom();
      }
    
        this.filter = document.querySelector('input[name="filter"]:checked').value;
        this.results = await this.calculator.calculateResults(this.filter);
      }
    
      displayResults() {
        document.getElementById("news-flow").innerHTML = "";
        if (this.zone === "areas") {
          this.displayFlowAreas();
    
          this.displayAreasResults();
    
        } else if (this.zone === "sections") {
          this.displayFlowSections();
    
          this.displaySectionsResults();
    
        Scroller.scrollInit("news-flow");
    
      }
    
      async displayFlowAreas() {
        this.results.areasResults.sort(function (a, b) {
          return b.DateCompletion - a.DateCompletion;
        });
        for (let j in this.results.areasResults) {
          let area = this.results.areasResults[j];
    
          if (area.status === this.filter) {
    
            document.getElementById(
              "news-flow"
            ).innerHTML += this.resultFlowTemplate(area);
    
            for (let i in area.candidateLists) {
    
              let party = await this.PartyModel.getParty(
                area.candidateLists[i].PartyID
              );
    
    
              document.getElementById(
                "flow-content-" + area.ID
    
              ).innerHTML += await this.progressBarTemplate(
                area.candidateLists[i],
                party.Color
    
              );
            }
          }
        }
      }
    
      async displayFlowSections() {
        let sections = [];
        this.results.areasResults.forEach((area) => {
          sections = sections.concat(area.Sections);
        });
        sections.sort(function (a, b) {
          return b.DateCompletion - a.DateCompletion;
        });
    
        for (let j in sections) {
          let section = sections[j];
    
          if (section.status === this.filter) {
    
            document.getElementById(
              "news-flow"
            ).innerHTML += this.resultFlowTemplate(section);
    
            for (let i in section.candidateLists) {
    
              let party = await this.PartyModel.getParty(
                section.candidateLists[i].PartyID
              );
    
    
              document.getElementById(
                "flow-content-" + section.ID
    
              ).innerHTML += await this.progressBarTemplate(
                section.candidateLists[i],
                party.Color
    
    
      displayRoundResults() {
    
        document.getElementById(
          "detailed-results"
        ).innerHTML = `<h5 class="title is-5">Résultats détaillés du tour</h5>`;
    
        for (let i in this.results.roundResults) {
          document.getElementById(
            "detailed-results"
          ).innerHTML += this.progressBarTemplate(
            this.results.roundResults[i],
            this.results.roundResults[i].Color
          );
        }
      }
    
    
      displayAreasResults() {
        let selectAreas = document.getElementById("select-areas");
        document.getElementById("select-sections").parentNode.style.display =
          "none";
    
        for (let i = selectAreas.options.length - 1; i >= 0; i--) {
          selectAreas.remove(i);
        }
    
        this.results.areasResults.forEach((area) => {
          let el = document.createElement("option");
          el.textContent = area.Name;
          el.value = area.ID;
          selectAreas.appendChild(el);
        });
    
        this.displayZoneResults(this.results.areasResults[0]);
      }
    
      displaySectionsResults() {
        let selectAreas = document.getElementById("select-areas");
        document.getElementById("select-sections").parentNode.style.display =
          "block";
    
        for (let i = selectAreas.options.length - 1; i >= 0; i--) {
          selectAreas.remove(i);
        }
    
        this.results.areasResults.forEach((area) => {
          let el = document.createElement("option");
          el.textContent = area.Name;
          el.value = area.ID;
          selectAreas.appendChild(el);
        });
    
        this.refreshSections(this.results.areasResults[0]);
    
        this.displayZoneResults(this.results.areasResults[0].Sections[0]);
      }
    
      async displayZoneResults(zone) {
        if (zone.status !== this.filter) {
          console.log(zone);
          if (zone.status == "no_results") {
            document.getElementById(
              "zone-results"
            ).innerHTML = this.showWarningResults(
              "Aucun résultats n'ont étaient saisis sur cette zone"
            );
          } else if (zone.status == "incompleted") {
            document.getElementById(
              "zone-results"
            ).innerHTML = this.showWarningResults(
              "Les résultats pour cette zone ne sont pas complets"
            );
          } else if (zone.status == "not validated") {
            document.getElementById(
              "zone-results"
            ).innerHTML = this.showWarningResults(
              "Les résultats pour cette zone n'ont pas étaient validés"
            );
          }
          document.getElementById("zone-detaileds-results").innerHTML = "";
        } else {
          document.getElementById("zone-results").innerHTML =
            '<br/><h5 class="title is-5">Résultats</h5>';
          for (let i in zone.candidateLists) {
            let party = await this.PartyModel.getParty(
              zone.candidateLists[i].PartyID
            );
            document.getElementById(
              "zone-results"
            ).innerHTML += this.progressBarTemplate(
              zone.candidateLists[i],
              party.Color
            );
          }
          this.displayZoneDetailedResults(zone);
        }
      }
    
      displayZoneDetailedResults(zone) {
        document.getElementById("zone-detaileds-results").innerHTML =
          '<br/><h5 class="title is-5">Statistiques</h5>';
    
        if (this.filter === "partial")
          document.getElementById(
            "zone-detaileds-results"
          ).innerHTML += this.progressBarTemplate(
            {
              Name: "Pourcentage de saisie",
              Percentage: zone.stats.PercentageConsiderated,
              VoiceNumber: null,
            },
            "grey"
          );
        document.getElementById(
          "zone-detaileds-results"
        ).innerHTML += this.progressBarTemplate(
          {
            Name: "Abstention",
            Percentage: zone.stats.Abstention,
            VoiceNumber: null,
          },
          "grey"
        );
        document.getElementById(
          "zone-detaileds-results"
        ).innerHTML += this.progressBarTemplate(
          {
            Name: "Votes blancs",
            Percentage: zone.stats.BlankPercentage,
            VoiceNumber: zone.stats.BlankVoiceNumber,
          },
          "grey"
        );
        document.getElementById(
          "zone-detaileds-results"
        ).innerHTML += this.progressBarTemplate(
          {
            Name: "Votes nuls",
            Percentage: zone.stats.NullVotePercentage,
            VoiceNumber: zone.stats.NullVoteVoiceNumber,
          },
          "grey"
        );
      }
    
      refreshSections(area) {
        let selectSections = document.getElementById("select-sections");
        selectSections.parentNode.style.display = "block";
        for (let i = selectSections.options.length - 1; i >= 0; i--) {
          selectSections.remove(i);
        }
        for (let i in area.Sections) {
          let el = document.createElement("option");
          el.textContent = area.Sections[i].Name;
          el.value = area.Sections[i].ID;
          selectSections.appendChild(el);
        }
      }