diff --git a/data/test.db b/data/test.db
index 7be481e590a39fba8ed2fbafb68d5dce01950b3c..f0fc7e7d6d6501152a1221e211ccefa82a4ddc90 100644
Binary files a/data/test.db and b/data/test.db differ
diff --git a/web/components/management/area.js b/web/components/management/area.js
new file mode 100644
index 0000000000000000000000000000000000000000..f13e766db58fb963e0b0160fe75f420f1c5ae9f7
--- /dev/null
+++ b/web/components/management/area.js
@@ -0,0 +1,332 @@
+// 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 { Delete } from "/services/common/delete.js";
+
+// DOM elements
+
+// local variables
+let current_user;
+
+export async function mount(where, parent) {
+  const areaComponent = new Area(parent);
+  await areaComponent.mount(where);
+  return areaComponent;
+}
+
+class Area {
+  constructor(parent) {
+    this.parent = parent;
+  }
+
+  async mount(where) {
+    const mountpoint = where;
+    document.getElementById(mountpoint).innerHTML = /* HTML */ `
+      <header class="card-header">
+        <p class="card-header-title" id="area-title">
+          Circonscriptions
+        </p>
+        <button id="area-new" class="button is-success" disabled>
+          <span class="icon is-small">
+            <i class="fas fa-plus"></i>
+          </span>
+        </button>
+      </header>
+      <div class="card-content">
+        <div id="area-list" class="content">
+          Sélectionner une élection.
+        </div>
+      </div>
+    `;
+    current_user = await Auth.GetUser();
+    this.mountModal("area-modal");
+    this.handleDom();
+  }
+
+  handleDom() {
+    let areaHandler = this;
+    document.getElementById(`area-new`).addEventListener("click", function () {
+      areaHandler.newArea(areaHandler.election);
+    });
+
+    document
+      .getElementById(`area-modal-close`)
+      .addEventListener("click", function () {
+        Common.toggleModal("area-modal", "area-modal-card");
+      });
+    document
+      .getElementById(`area-modal-cancel`)
+      .addEventListener("click", function () {
+        Common.toggleModal("area-modal", "area-modal-card");
+      });
+    document
+      .getElementById(`area-modal-save`)
+      .addEventListener("click", async function () {
+        await areaHandler.saveArea();
+      });
+    document
+      .getElementById(`area-modal-save-area`)
+      .addEventListener("click", async function () {
+        await areaHandler.saveArea();
+        await new Promise((r) => setTimeout(r, 800));
+        areaHandler.newArea(areaHandler.election);
+      });
+    document
+      .getElementById(`area-modal-save-section`)
+      .addEventListener("click", async function () {
+        let area = await areaHandler.saveArea();
+        await new Promise((r) => setTimeout(r, 800));
+        areaHandler.parent.sectionHandler.newSection(area);
+      });
+  }
+
+  mountModal(where) {
+    const mountpoint = where;
+    document.getElementById(mountpoint).innerHTML = /* HTML */ `
+      <div class="modal-background"></div>
+      <div class="modal-card" id="area-modal-card">
+        <header class="modal-card-head">
+          <p class="modal-card-title">
+            Ajout/modification d'une circonscription
+          </p>
+          <button
+            class="delete"
+            aria-label="close"
+            id="area-modal-close"
+          ></button>
+        </header>
+        <section class="modal-card-body">
+          <div class="field">
+            <label>Id</label>
+            <div class="control">
+              <input class="input" type="number" id="area-modal-id" disabled />
+            </div>
+          </div>
+          <div class="field">
+            <label>Nom</label>
+            <div class="control">
+              <input class="input" type="text" id="area-modal-name" />
+            </div>
+          </div>
+          <div class="field">
+            <label>Nombre de siège</label>
+            <div class="control">
+              <input class="input" type="number" id="area-modal-seat-number" />
+            </div>
+          </div>
+        </section>
+        <footer class="modal-card-foot">
+          <button id="area-modal-save" class="button is-success">
+            Sauvegarder
+          </button>
+          <button id="area-modal-save-area" class="button is-success">
+            Sauvegarder <br />
+            (ajouter circonscription)
+          </button>
+          <button id="area-modal-save-section" class="button is-success">
+            Sauvegarder <br />(ajouter ville)
+          </button>
+          <button id="area-modal-cancel" class="button">Annuler</button>
+        </footer>
+      </div>
+    `;
+  }
+
+  async displayAreas() {
+    let areaHandler = this;
+    let areas = await this.updateAreas();
+    const markup = areas.map((area) => this.areaTemplate(area)).join("");
+    document.getElementById("area-list").innerHTML = markup;
+    document.getElementById("area-new").removeAttribute("disabled");
+    document.getElementById("area-title").innerHTML =
+      "Circonscriptions de&nbsp;<em> " + this.election.Name + "</em>";
+
+    areas.map((area) => {
+      document
+        .getElementById(`areas-area-edit-${area.ID}`)
+        .addEventListener("click", function () {
+          areaHandler.editArea(area);
+        });
+      document
+        .getElementById(`areas-area-delete-${area.ID}`)
+        .addEventListener("click", function () {
+          new Delete(() => {
+            areaHandler.deleteArea(area);
+          });
+        });
+      document
+        .getElementById(`areas-area-${area.ID}`)
+        .addEventListener("click", function () {
+          areaHandler.activateArea(area);
+          areaHandler.parent.sectionHandler.area = area;
+          areaHandler.parent.sectionHandler.displaySections();
+          document.getElementById("desk-new").setAttribute("disabled", "true");
+          document
+            .getElementById("section-new")
+            .setAttribute("disabled", "true");
+        });
+    });
+  }
+
+  emptyAreas() {
+    this.election = null;
+    document.getElementById("area-title").innerHTML = "Circonscriptions";
+    document.getElementById("area-list").innerHTML =
+      "Veuillez sélectionner une élection";
+  }
+
+  areaTemplate(area) {
+    return /* HTML */ `<div class="card card-list">
+      <div id="areas-area-${area.ID}" class="card-content">
+        <div class="content">
+          <nav class="level">
+            <div class="level-left">
+              ${area.Name} (Nombre de siège : ${area.SeatNumber})
+            </div>
+            <div class="level-right">
+              <a
+                id="areas-area-edit-${area.ID}"
+                class="button is-link is-small"
+                title="Modifier"
+              >
+                <span class="icon is-small">
+                  <i class="fas fa-pen"></i>
+                </span>
+              </a>
+              <a
+                id="areas-area-delete-${area.ID}"
+                class="button is-danger is-small"
+                title="Supprimer"
+              >
+                <span class="icon is-small">
+                  <i class="fas fa-times"></i>
+                </span>
+              </a>
+            </div>
+          </nav>
+        </div>
+      </div>
+    </div>`;
+  }
+
+  async activateArea(area) {
+    this.parent.sectionHandler.emptySections();
+    this.parent.deskHandler.emptyDesks();
+    let areas = await this.updateAreas();
+    areas.forEach((area) => {
+      document
+        .getElementById(`areas-area-${area.ID}`)
+        .classList.remove("active-card");
+    });
+    document
+      .getElementById(`areas-area-${area.ID}`)
+      .classList.add("active-card");
+  }
+
+  newArea(election) {
+    this.method = "POST";
+    this.election = election;
+    document.getElementById("area-modal-id").value = null;
+    document.getElementById("area-modal-name").value = election.Name;
+    document.getElementById("area-modal-seat-number").value = null;
+    Common.toggleModal("area-modal", "area-modal-card");
+  }
+
+  editArea(area) {
+    this.method = "PUT";
+    document.getElementById("area-modal-id").value = area.ID;
+    document.getElementById("area-modal-name").value = area.Name;
+    document.getElementById("area-modal-seat-number").value = area.SeatNumber;
+    Common.toggleModal("area-modal", "area-modal-card");
+  }
+
+  async saveArea() {
+    let area;
+    if (this.method == "POST")
+      document.getElementById("area-modal-id").value = null;
+
+    try {
+      const response = await fetch(
+        "/api/Area/" + document.getElementById("area-modal-id").value,
+        {
+          method: this.method,
+          headers: new Headers({
+            "XSRF-Token": current_user.xsrftoken,
+          }),
+          body: JSON.stringify({
+            ID: parseInt(document.getElementById("area-modal-id").value),
+            ElectionID: this.election.ID,
+            Name: document.getElementById("area-modal-name").value,
+            SeatNumber: parseInt(
+              document.getElementById("area-modal-seat-number").value
+            ),
+          }),
+        }
+      );
+      if (response.status !== 200) {
+        throw new Error(
+          `Area could not be updated or created (status ${response.status})`
+        );
+      }
+      area = await response.json();
+      await this.displayAreas();
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+    Common.toggleModal("area-modal", "area-modal-card");
+    this.activateArea(area);
+    this.parent.sectionHandler.area = area;
+    this.parent.sectionHandler.displaySections();
+    return area;
+  }
+
+  async updateAreas() {
+    let areaHandler = this;
+    try {
+      const response = await fetch("/api/Area/", {
+        method: "GET",
+        headers: new Headers({
+          "XSRF-Token": current_user.xsrftoken,
+        }),
+      });
+      if (response.status !== 200) {
+        throw new Error(
+          `Areas could not be fetched (status ${response.status})`
+        );
+      }
+      let areas = await response.json();
+      return areas.filter(function (area) {
+        return area.ElectionID == areaHandler.election.ID;
+      });
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+  }
+
+  async deleteArea(area) {
+    try {
+      const response = await fetch("/api/Area/" + area.ID, {
+        method: "delete",
+        headers: new Headers({
+          "XSRF-Token": current_user.xsrftoken,
+        }),
+      });
+      if (response.status !== 200) {
+        throw new Error(
+          `Area could not be deleted (status ${response.status})`
+        );
+      }
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+    this.displayAreas();
+    this.parent.sectionHandler.emptySections();
+    this.parent.deskHandler.emptyDesks();
+    document.getElementById("desk-new").setAttribute("disabled", "true");
+    document.getElementById("section-new").setAttribute("disabled", "true");
+  }
+}
diff --git a/web/components/management/desk.js b/web/components/management/desk.js
new file mode 100644
index 0000000000000000000000000000000000000000..c009bde58e089e7c4b0d95dff20c2526ae9b4145
--- /dev/null
+++ b/web/components/management/desk.js
@@ -0,0 +1,297 @@
+// 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 { Delete } from "/services/common/delete.js";
+
+// DOM elements
+
+// local variables
+let current_user;
+
+export async function mount(where) {
+  const deskComponent = new Desk();
+  await deskComponent.mount(where);
+  return deskComponent;
+}
+
+class Desk {
+  constructor() {}
+
+  async mount(where) {
+    const mountpoint = where;
+    document.getElementById(mountpoint).innerHTML = /* HTML */ `
+      <header class="card-header">
+        <p class="card-header-title" id="desk-title">
+          Bureaux
+        </p>
+        <button id="desk-new" class="button is-success" disabled>
+          <span class="icon is-small">
+            <i class="fas fa-plus"></i>
+          </span>
+        </button>
+      </header>
+      <div class="card-content">
+        <div id="desk-list" class="content">
+          Sélectionner une section.
+        </div>
+      </div>
+    `;
+    current_user = await Auth.GetUser();
+    this.mountModal("desk-modal");
+    this.handleDom();
+  }
+
+  handleDom() {
+    let deskHandler = this;
+    document.getElementById(`desk-new`).addEventListener("click", function () {
+      deskHandler.newDesk(deskHandler.section)
+    });
+
+    document
+      .getElementById(`desk-modal-close`)
+      .addEventListener("click", function () {
+        Common.toggleModal("desk-modal", "desk-modal-card");
+      });
+    document
+      .getElementById(`desk-modal-cancel`)
+      .addEventListener("click", function () {
+        Common.toggleModal("desk-modal", "desk-modal-card");
+      });
+    document
+      .getElementById(`desk-modal-save`)
+      .addEventListener("click", async function () {
+        await deskHandler.saveDesk();
+      });
+    document
+      .getElementById(`desk-modal-save-desk`)
+      .addEventListener("click", async function () {
+        await deskHandler.saveDesk();
+        await new Promise((r) => setTimeout(r, 800));
+        deskHandler.newDesk(deskHandler.section);
+      });
+  }
+
+  mountModal(where) {
+    const mountpoint = where;
+    document.getElementById(mountpoint).innerHTML = /* HTML */ `
+      <div class="modal-background"></div>
+      <div class="modal-card" id="desk-modal-card">
+        <header class="modal-card-head">
+          <p class="modal-card-title">
+            Ajout/modification d'un bureau
+          </p>
+          <button
+            class="delete"
+            aria-label="close"
+            id="desk-modal-close"
+          ></button>
+        </header>
+        <section class="modal-card-body">
+          <div class="field">
+            <label>Id</label>
+            <div class="control">
+              <input class="input" type="number" id="desk-modal-id" disabled />
+            </div>
+          </div>
+          <div class="field">
+            <label>Nom</label>
+            <div class="control">
+              <input class="input" type="text" id="desk-modal-name" />
+            </div>
+          </div>
+          <div class="field">
+            <label>Subscribed</label>
+            <div class="control">
+              <input class="input" type="number" id="desk-modal-subscribed" />
+            </div>
+          </div>
+          <div class="field">
+            <div class="control">
+              <label class="checkbox">
+                <input class="input" type="checkbox" id="desk-modal-witness" />
+                Bureau témoin
+              </label>
+            </div>
+          </div>
+        </section>
+        <footer class="modal-card-foot">
+          <button id="desk-modal-save" class="button is-success">
+            Sauvegarder
+          </button>
+          <button id="desk-modal-save-desk" class="button is-success">
+            Sauvegarder (ajouter bureau)
+          </button>
+          <button id="desk-modal-cancel" class="button">Annuler</button>
+        </footer>
+      </div>
+    `;
+  }
+
+  async displayDesks() {
+    let deskHandler = this;
+    let desks = await this.updateDesks();
+    const markup = desks.map((section) => this.deskTemplate(section)).join("");
+    document.getElementById("desk-list").innerHTML = markup;
+    document.getElementById("desk-new").removeAttribute("disabled");
+    document.getElementById("desk-title").innerHTML =
+      "Bureaux de&nbsp;<em> " + this.section.Name + "</em>";
+
+    desks.map((desk) => {
+      document
+        .getElementById(`desks-desk-edit-${desk.ID}`)
+        .addEventListener("click", function () {
+          deskHandler.editSection(desk);
+        });
+      document
+        .getElementById(`desks-desk-delete-${desk.ID}`)
+        .addEventListener("click", function () {
+          new Delete(() => {
+            deskHandler.deleteDesk(desk);
+          });
+        });
+    });
+  }
+
+  emptyDesks() {
+    document.getElementById("desk-title").innerHTML =
+      "Bureaux";
+    this.section = null;
+    document.getElementById("desk-list").innerHTML = "Veuillez sélectionner une section";
+  }
+
+  deskTemplate(desk) {
+    return /* HTML */ `<div class="card card-list">
+      <div class="card-content">
+        <div class="content">
+          <nav class="level">
+            <div class="level-left">
+              ${desk.Name} (Inscrits : ${desk.Subscribed})
+            </div>
+            <div class="level-right">
+              <a
+                id="desks-desk-edit-${desk.ID}"
+                class="button is-link is-small"
+                title="Modifier"
+              >
+                <span class="icon is-small">
+                  <i class="fas fa-pen"></i>
+                </span>
+              </a>
+              <a
+                id="desks-desk-delete-${desk.ID}"
+                class="button is-danger is-small"
+                title="Supprimer"
+              >
+                <span class="icon is-small">
+                  <i class="fas fa-times"></i>
+                </span>
+              </a>
+            </div>
+          </nav>
+        </div>
+      </div>
+    </div>`;
+  }
+
+  newDesk(section) {
+    this.method = "POST";
+    this.section = section;
+    document.getElementById("desk-modal-id").value = null;
+    document.getElementById("desk-modal-name").value = section.Name;
+    document.getElementById("desk-modal-subscribed").value = section.Subscribed;
+    document.getElementById("desk-modal-witness").checked = section.WitnessDesk;
+    Common.toggleModal("desk-modal", "desk-modal-card");
+  }
+
+  editSection(section) {
+    this.method = "PUT";
+    document.getElementById("desk-modal-id").value = section.ID;
+    document.getElementById("desk-modal-name").value = section.Name;
+    document.getElementById("desk-modal-subscribed").value = section.Subscribed;
+    document.getElementById("desk-modal-witness").checked = section.WitnessDesk;
+    Common.toggleModal("desk-modal", "desk-modal-card");
+  }
+
+  async saveDesk() {
+    let desk;
+    if (this.method == "POST")
+      document.getElementById("desk-modal-id").value = null;
+
+    try {
+      const response = await fetch(
+        "/api/Desk/" + document.getElementById("desk-modal-id").value,
+        {
+          method: this.method,
+          headers: new Headers({
+            "XSRF-Token": current_user.xsrftoken,
+          }),
+          body: JSON.stringify({
+            ID: parseInt(document.getElementById("desk-modal-id").value),
+            SectionID: this.section.ID,
+            Name: document.getElementById("desk-modal-name").value,
+            Subscribed: parseInt(
+              document.getElementById("desk-modal-subscribed").value
+            ),
+            WitnessDesk: document.getElementById("desk-modal-witness").checked,
+          }),
+        }
+      );
+      if (response.status !== 200) {
+        throw new Error(
+          `Desk could not be updated or created (status ${response.status})`
+        );
+      }
+      desk = await response.json();
+      await this.displayDesks();
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+    Common.toggleModal("desk-modal", "desk-modal-card");
+  }
+
+  async updateDesks() {
+    let deskHandler = this;
+    try {
+      const response = await fetch("/api/Desk/", {
+        method: "GET",
+        headers: new Headers({
+          "XSRF-Token": current_user.xsrftoken,
+        }),
+      });
+      if (response.status !== 200) {
+        throw new Error(
+          `Desks could not be fetched (status ${response.status})`
+        );
+      }
+      let desks = await response.json();
+      return desks.filter(function (desk) {
+        return desk.SectionID == deskHandler.section.ID;
+      });
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+  }
+
+  async deleteDesk(desk) {
+    try {
+      const response = await fetch("/api/Desk/" + desk.ID, {
+        method: "delete",
+        headers: new Headers({
+          "XSRF-Token": current_user.xsrftoken,
+        }),
+      });
+      if (response.status !== 200) {
+        throw new Error(
+          `Desk could not be deleted (status ${response.status})`
+        );
+      }
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+    this.displayDesks();
+  }
+}
diff --git a/web/components/management/election.js b/web/components/management/election.js
index c7eaf2293d6c5d6f25de1df9b5223e3da6d271ce..a7b7f3e0a533eeeede5a4bdf29b26e4f4f26be14 100644
--- a/web/components/management/election.js
+++ b/web/components/management/election.js
@@ -1,24 +1,322 @@
 // 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 { Delete } from "/services/common/delete.js";
 
 // DOM elements
 
 // local variables
 let current_user;
 
-export async function mount(where) {
-  const roundComponent = new Election();
-  await roundComponent.mount(where);
+export async function mount(where, parent) {
+  const electionComponent = new Election(parent);
+  await electionComponent.mount(where);
+  return electionComponent;
 }
 
 class Election {
-  constructor() {}
+  constructor(parent) {
+    this.method = null;
+    this.parent = parent;
+  }
 
   async mount(where) {
     const mountpoint = where;
     document.getElementById(mountpoint).innerHTML = /* HTML */ `
-      Ceci est une élection
+      <header class="card-header">
+        <p class="card-header-title">
+          Elections
+        </p>
+        <button id="election-new" class="button is-success">
+          <span class="icon is-small">
+            <i class="fas fa-plus"></i>
+          </span>
+        </button>
+      </header>
+      <div class="card-content">
+        <div id="election-list" class="content">Liste des élections</div>
+      </div>
     `;
     current_user = await Auth.GetUser();
+    this.mountModal("election-modal");
+    this.handleDom();
+    this.displayElections();
+  }
+
+  handleDom() {
+    let electionHandler = this;
+    document
+      .getElementById(`election-new`)
+      .addEventListener("click", function () {
+        electionHandler.newElection();
+      });
+
+    document
+      .getElementById(`election-modal-close`)
+      .addEventListener("click", function () {
+        Common.toggleModal("election-modal", "election-modal-card");
+      });
+    document
+      .getElementById(`election-modal-cancel`)
+      .addEventListener("click", function () {
+        Common.toggleModal("election-modal", "election-modal-card");
+      });
+    document
+      .getElementById(`election-modal-save`)
+      .addEventListener("click", async function () {
+        await electionHandler.saveElection();
+      });
+    document
+      .getElementById(`election-modal-save-area`)
+      .addEventListener("click", async function () {
+        let election = await electionHandler.saveElection();
+        electionHandler.parent.areaHandler.newArea(election);
+      });
+  }
+
+  mountModal(where) {
+    const mountpoint = where;
+    document.getElementById(mountpoint).innerHTML = /* HTML */ `
+      <div class="modal-background"></div>
+      <div class="modal-card" id="election-modal-card">
+        <header class="modal-card-head">
+          <p class="modal-card-title">Ajout/modification d'une élection</p>
+          <button
+            class="delete"
+            aria-label="close"
+            id="election-modal-close"
+          ></button>
+        </header>
+        <section class="modal-card-body">
+          <div class="field">
+            <label>Id</label>
+            <div class="control">
+              <input
+                class="input"
+                type="number"
+                id="election-modal-id"
+                disabled
+              />
+            </div>
+          </div>
+          <div class="field">
+            <label>Nom</label>
+            <div class="control">
+              <input class="input" type="text" id="election-modal-name" />
+            </div>
+          </div>
+          <div class="field">
+            <label>Système de vote</label><br />
+            <div class="control select">
+              <select name="ballot-type" id="election-modal-ballot-type">
+                <option value="local-counsil-direct"
+                  >Conseil communautaire au suffrage direct</option
+                >
+                <option value="local-counsil-indirect"
+                  >Conseil communautaire au suffrage indirect</option
+                >
+              </select>
+            </div>
+          </div>
+        </section>
+        <footer class="modal-card-foot">
+          <button id="election-modal-save" class="button is-success">
+            Sauvegarder
+          </button>
+          <button id="election-modal-save-area" class="button is-success">
+            Sauvegarder (ajouter circonscription)
+          </button>
+          <button id="election-modal-cancel" class="button">Annuler</button>
+        </footer>
+      </div>
+    `;
+  }
+
+  async displayElections() {
+    let elections = await this.updateElections();
+    const markup = elections
+      .map((election) => this.electionTemplate(election))
+      .join("");
+    document.getElementById("election-list").innerHTML = markup;
+
+    let electionHandler = this;
+    elections.map((election) => {
+      document
+        .getElementById(`elections-election-edit-${election.ID}`)
+        .addEventListener("click", function () {
+          electionHandler.editElection(election);
+        });
+      document
+        .getElementById(`elections-election-delete-${election.ID}`)
+        .addEventListener("click", function () {
+          new Delete(() => {
+            electionHandler.deleteElection(election);
+          });
+        });
+      document
+        .getElementById(`elections-election-${election.ID}`)
+        .addEventListener("click", function () {
+          electionHandler.activateElection(election);
+          electionHandler.parent.areaHandler.election = election;
+          electionHandler.parent.areaHandler.displayAreas();
+          document.getElementById("desk-new").setAttribute("disabled", "true");
+          document
+            .getElementById("section-new")
+            .setAttribute("disabled", "true");
+          document.getElementById("area-new").setAttribute("disabled", "true");
+        });
+    });
+  }
+
+  electionTemplate(election) {
+    return /* HTML */ `<div class="card card-list">
+      <div id="elections-election-${election.ID}" class="card-content">
+        <div class="content">
+          <nav class="level">
+            <div class="level-left">
+              ${election.Name} (${election.BallotType})
+            </div>
+            <div class="level-right">
+              <a
+                id="elections-election-edit-${election.ID}"
+                class="button is-link is-small"
+                title="Modifier"
+              >
+                <span class="icon is-small">
+                  <i class="fas fa-pen"></i>
+                </span>
+              </a>
+              <a
+                id="elections-election-delete-${election.ID}"
+                class="button is-danger is-small"
+                title="Supprimer"
+              >
+                <span class="icon is-small">
+                  <i class="fas fa-times"></i>
+                </span>
+              </a>
+            </div>
+          </nav>
+        </div>
+      </div>
+    </div>`;
+  }
+
+  async activateElection(election) {
+    this.parent.areaHandler.emptyAreas();
+    this.parent.sectionHandler.emptySections();
+    this.parent.deskHandler.emptyDesks();
+    let elections = await this.updateElections();
+    elections.forEach((election) => {
+      document
+        .getElementById(`elections-election-${election.ID}`)
+        .classList.remove("active-card");
+    });
+    document
+      .getElementById(`elections-election-${election.ID}`)
+      .classList.add("active-card");
+  }
+
+  newElection() {
+    this.method = "POST";
+    document.getElementById("election-modal-id").value = null;
+    document.getElementById("election-modal-name").value = null;
+    document.getElementById("election-modal-ballot-type").value = null;
+    Common.toggleModal("election-modal", "election-modal-card");
+  }
+
+  editElection(election) {
+    this.method = "PUT";
+    document.getElementById("election-modal-id").value = election.ID;
+    document.getElementById("election-modal-name").value = election.Name;
+    document.getElementById("election-modal-ballot-type").value =
+      election.BallotType;
+    Common.toggleModal("election-modal", "election-modal-card");
+  }
+
+  async saveElection() {
+    let election;
+    if (this.method == "POST")
+      document.getElementById("election-modal-id").value = null;
+
+    try {
+      const response = await fetch(
+        "/api/Election/" + document.getElementById("election-modal-id").value,
+        {
+          method: this.method,
+          headers: new Headers({
+            "XSRF-Token": current_user.xsrftoken,
+          }),
+          body: JSON.stringify({
+            ID: parseInt(document.getElementById("election-modal-id").value),
+            Name: document.getElementById("election-modal-name").value,
+            BallotType: document.getElementById("election-modal-ballot-type")
+              .value,
+          }),
+        }
+      );
+      if (response.status !== 200) {
+        throw new Error(
+          `Election could not be updated or created (status ${response.status})`
+        );
+      }
+      election = await response.json();
+      this.displayElections();
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+    Common.toggleModal("election-modal", "election-modal-card");
+    this.activateElection(election);
+    this.parent.areaHandler.election = election;
+    this.parent.areaHandler.displayAreas();
+    return election;
+  }
+
+  async updateElections() {
+    try {
+      const response = await fetch("/api/Election/", {
+        method: "GET",
+        headers: new Headers({
+          "XSRF-Token": current_user.xsrftoken,
+        }),
+      });
+      if (response.status !== 200) {
+        throw new Error(
+          `Elections could not be fetched (status ${response.status})`
+        );
+      }
+      return await response.json();
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+  }
+
+  async deleteElection(election) {
+    try {
+      const response = await fetch("/api/Election/" + election.ID, {
+        method: "delete",
+        headers: new Headers({
+          "XSRF-Token": current_user.xsrftoken,
+        }),
+      });
+      if (response.status !== 200) {
+        throw new Error(
+          `Election could not be deleted (status ${response.status})`
+        );
+      }
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+    this.displayElections();
+    this.parent.areaHandler.emptyAreas();
+    this.parent.sectionHandler.emptySections();
+    this.parent.deskHandler.emptyDesks();
+    document.getElementById("desk-new").setAttribute("disabled", "true");
+    document.getElementById("section-new").setAttribute("disabled", "true");
+    document.getElementById("area-new").setAttribute("disabled", "true");
   }
 }
diff --git a/web/components/management/genericElection.js b/web/components/management/genericElection.js
new file mode 100644
index 0000000000000000000000000000000000000000..21b09fa18c83c588763311dfd79d836e6fe72287
--- /dev/null
+++ b/web/components/management/genericElection.js
@@ -0,0 +1,50 @@
+// Imports
+import * as Auth from "/services/auth/auth.js";
+import * as Election from "/components/management/election.js";
+import * as Areas from "/components/management/area.js";
+import * as Sections from "/components/management/section.js";
+import * as Desks from "/components/management/desk.js";
+
+// DOM elements
+
+// local variables
+let current_user;
+
+export async function mount(where) {
+  const genericElectionComponent = new GenericElection();
+  await genericElectionComponent.mount(where);
+}
+
+class GenericElection {
+  constructor() {}
+
+  async mount(where) {
+    const mountpoint = where;
+    document.getElementById(mountpoint).innerHTML = /* HTML */ `
+      <div class="columns">
+        <div class="column">
+          <div id="election" class="card"></div>
+        </div>
+        <div class="column">
+          <div id="areas" class="card"></div>
+        </div>
+        <div class="column">
+          <div id="sections" class="card"></div>
+        </div>
+        <div class="column">
+          <div id="desks" class="card"></div>
+        </div>
+      </div>
+
+      <div class="modal" id="election-modal"></div>
+      <div class="modal" id="area-modal"></div>
+      <div class="modal" id="section-modal"></div>
+      <div class="modal" id="desk-modal"></div>
+    `;
+    current_user = await Auth.GetUser();
+    this.electionHandler = await Election.mount("election", this);
+    this.areaHandler = await Areas.mount("areas", this);
+    this.sectionHandler = await Sections.mount("sections", this);
+    this.deskHandler = await Desks.mount("desks", this);
+  }
+}
diff --git a/web/components/management/management.js b/web/components/management/management.js
index ab678413f85c45ee4ccff2593d62730d8aec9ffa..6a6fadeaf0d4405beadfe2af03c066e373ea5254 100644
--- a/web/components/management/management.js
+++ b/web/components/management/management.js
@@ -1,6 +1,6 @@
 // Imports
 import * as Auth from "/services/auth/auth.js";
-import * as Election from "/components/management/election.js";
+import * as Election from "/components/management/genericElection.js";
 import * as Round from "/components/management/round.js";
 
 // DOM elements
@@ -21,7 +21,7 @@ class Management {
     document.getElementById(mountpoint).innerHTML = /* HTML */ `
       <div class="tabs is-boxed is-toggle is-fullwidth">
         <ul>
-          <li id="election" class="is-active">
+          <li id="elections" class="is-active">
             <a>
               <span class="icon is-small"
                 ><i class="fas fa-vote-yea" aria-hidden="true"></i
@@ -29,7 +29,7 @@ class Management {
               <span>Election</span>
             </a>
           </li>
-          <li id="round">
+          <li id="rounds">
             <a>
               <span class="icon is-small"
                 ><i class="fas fa-calendar" aria-hidden="true"></i
@@ -43,20 +43,20 @@ class Management {
     `;
     current_user = await Auth.GetUser();
     this.handleDom();
-    document.getElementById("election").click()
+    document.getElementById("elections").click()
 
   }
 
   handleDom(){
-      document.getElementById("election").addEventListener("click", async function (){
+      document.getElementById("elections").addEventListener("click", async function (){
         await Election.mount("management-section");
-        document.getElementById("election").setAttribute("class", "is-active")
-        document.getElementById("round").setAttribute("class", "")
+        document.getElementById("elections").setAttribute("class", "is-active")
+        document.getElementById("rounds").setAttribute("class", "")
     });
-    document.getElementById("round").addEventListener("click", async function (){
+    document.getElementById("rounds").addEventListener("click", async function (){
         await Round.mount("management-section");
-        document.getElementById("election").setAttribute("class", "")
-        document.getElementById("round").setAttribute("class", "is-active")
+        document.getElementById("elections").setAttribute("class", "")
+        document.getElementById("rounds").setAttribute("class", "is-active")
       });
   }
 }
diff --git a/web/components/management/section.js b/web/components/management/section.js
new file mode 100644
index 0000000000000000000000000000000000000000..c6a08c3c4d7268a6b8e81cc6ddfc1797a7822123
--- /dev/null
+++ b/web/components/management/section.js
@@ -0,0 +1,326 @@
+// 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 { Delete } from "/services/common/delete.js";
+
+// DOM elements
+
+// local variables
+let current_user;
+
+export async function mount(where, parent) {
+  const sectionComponent = new Section(parent);
+  await sectionComponent.mount(where);
+  return sectionComponent;
+}
+
+class Section {
+  constructor(parent) {
+    this.parent = parent;
+  }
+
+  async mount(where) {
+    const mountpoint = where;
+    document.getElementById(mountpoint).innerHTML = /* HTML */ `
+      <header class="card-header">
+        <p class="card-header-title" id="section-title">
+          Sections
+        </p>
+        <button id="section-new" class="button is-success" disabled>
+          <span class="icon is-small">
+            <i class="fas fa-plus"></i>
+          </span>
+        </button>
+      </header>
+      <div class="card-content">
+        <div id="section-list" class="content">
+          Sélectionner une circonscription.
+        </div>
+      </div>
+    `;
+    current_user = await Auth.GetUser();
+    this.mountModal("section-modal");
+    this.handleDom();
+  }
+
+  handleDom() {
+    let sectionHandler = this;
+    document
+      .getElementById(`section-new`)
+      .addEventListener("click", function () {
+        sectionHandler.newSection(sectionHandler.area);
+      });
+
+    document
+      .getElementById(`section-modal-close`)
+      .addEventListener("click", function () {
+        Common.toggleModal("section-modal", "section-modal-card");
+      });
+    document
+      .getElementById(`section-modal-cancel`)
+      .addEventListener("click", function () {
+        Common.toggleModal("section-modal", "section-modal-card");
+      });
+    document
+      .getElementById(`section-modal-save`)
+      .addEventListener("click", async function () {
+        await sectionHandler.saveSection();
+      });
+    document
+      .getElementById(`section-modal-save-section`)
+      .addEventListener("click", async function () {
+        await sectionHandler.saveSection();
+        await new Promise((r) => setTimeout(r, 800));
+        sectionHandler.newSection(sectionHandler.area);
+      });
+    document
+      .getElementById(`section-modal-save-desk`)
+      .addEventListener("click", async function () {
+        let section = await sectionHandler.saveSection();
+        await new Promise((r) => setTimeout(r, 800));
+        sectionHandler.parent.deskHandler.section = section;
+        sectionHandler.parent.deskHandler.newDesk(section);
+      });
+  }
+
+  mountModal(where) {
+    const mountpoint = where;
+    document.getElementById(mountpoint).innerHTML = /* HTML */ `
+      <div class="modal-background"></div>
+      <div class="modal-card" id="section-modal-card">
+        <header class="modal-card-head">
+          <p class="modal-card-title">
+            Ajout/modification d'une section
+          </p>
+          <button
+            class="delete"
+            aria-label="close"
+            id="section-modal-close"
+          ></button>
+        </header>
+        <section class="modal-card-body">
+          <div class="field">
+            <label>Id</label>
+            <div class="control">
+              <input
+                class="input"
+                type="number"
+                id="section-modal-id"
+                disabled
+              />
+            </div>
+          </div>
+          <div class="field">
+            <label>Nom</label>
+            <div class="control">
+              <input class="input" type="text" id="section-modal-name" />
+            </div>
+          </div>
+        </section>
+        <footer class="modal-card-foot">
+          <button id="section-modal-save" class="button is-success">
+            Sauvegarder
+          </button>
+          <button id="section-modal-save-section" class="button is-success">
+            Sauvegarder <br />
+            (ajouter section)
+          </button>
+          <button id="section-modal-save-desk" class="button is-success">
+            Sauvegarder <br />
+            (ajouter bureau)
+          </button>
+          <button id="section-modal-cancel" class="button">Annuler</button>
+        </footer>
+      </div>
+    `;
+  }
+
+  async displaySections() {
+    let sectionHandler = this;
+    let sections = await this.updateSections();
+    const markup = sections
+      .map((section) => this.sectionTemplate(section))
+      .join("");
+    document.getElementById("section-list").innerHTML = markup;
+    document.getElementById("section-new").removeAttribute("disabled");
+    document.getElementById("section-title").innerHTML =
+      "Sections de&nbsp;<em> " + this.area.Name + "</em>";
+
+    sections.map((section) => {
+      document
+        .getElementById(`sections-section-edit-${section.ID}`)
+        .addEventListener("click", function () {
+          sectionHandler.editSection(section);
+        });
+      document
+        .getElementById(`sections-section-delete-${section.ID}`)
+        .addEventListener("click", function () {
+          new Delete(() => {
+            sectionHandler.deleteSection(section);
+          });
+        });
+      document
+        .getElementById(`sections-section-${section.ID}`)
+        .addEventListener("click", function () {
+          sectionHandler.activateSection(section);
+          sectionHandler.parent.deskHandler.section = section;
+          sectionHandler.parent.deskHandler.displayDesks();
+          document.getElementById("desk-new").setAttribute("disabled", "true");
+        });
+    });
+  }
+
+  emptySections() {
+    this.area = null;
+    document.getElementById("section-title").innerHTML = "Sections";
+    document.getElementById("section-list").innerHTML =
+      "Veuillez sélectionner une circonscription";
+  }
+
+  sectionTemplate(section) {
+    return /* HTML */ `<div class="card card-list">
+      <div id="sections-section-${section.ID}" class="card-content">
+        <div class="content">
+          <nav class="level">
+            <div class="level-left">
+              ${section.Name}
+            </div>
+            <div class="level-right">
+              <a
+                id="sections-section-edit-${section.ID}"
+                class="button is-link is-small"
+                title="Modifier"
+              >
+                <span class="icon is-small">
+                  <i class="fas fa-pen"></i>
+                </span>
+              </a>
+              <a
+                id="sections-section-delete-${section.ID}"
+                class="button is-danger is-small"
+                title="Supprimer"
+              >
+                <span class="icon is-small">
+                  <i class="fas fa-times"></i>
+                </span>
+              </a>
+            </div>
+          </nav>
+        </div>
+      </div>
+    </div>`;
+  }
+
+  async activateSection(section) {
+    this.parent.deskHandler.emptyDesks();
+    let sections = await this.updateSections();
+    sections.forEach((section) => {
+      document
+        .getElementById(`sections-section-${section.ID}`)
+        .classList.remove("active-card");
+    });
+    document
+      .getElementById(`sections-section-${section.ID}`)
+      .classList.add("active-card");
+  }
+
+  newSection(area) {
+    this.method = "POST";
+    this.area = area;
+    document.getElementById("section-modal-id").value = null;
+    document.getElementById("section-modal-name").value = area.Name;
+    Common.toggleModal("section-modal", "section-modal-card");
+  }
+
+  editSection(section) {
+    this.method = "PUT";
+    document.getElementById("section-modal-id").value = section.ID;
+    document.getElementById("section-modal-name").value = section.Name;
+    Common.toggleModal("section-modal", "section-modal-card");
+  }
+
+  async saveSection() {
+    let section;
+    if (this.method == "POST")
+      document.getElementById("section-modal-id").value = null;
+
+    try {
+      const response = await fetch(
+        "/api/Section/" + document.getElementById("section-modal-id").value,
+        {
+          method: this.method,
+          headers: new Headers({
+            "XSRF-Token": current_user.xsrftoken,
+          }),
+          body: JSON.stringify({
+            ID: parseInt(document.getElementById("section-modal-id").value),
+            AreaID: this.area.ID,
+            Name: document.getElementById("section-modal-name").value,
+          }),
+        }
+      );
+      if (response.status !== 200) {
+        throw new Error(
+          `Section could not be updated or created (status ${response.status})`
+        );
+      }
+      section = await response.json();
+      await this.displaySections();
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+    Common.toggleModal("section-modal", "section-modal-card");
+    this.activateSection(section);
+    this.parent.deskHandler.section = section;
+    this.parent.deskHandler.displayDesks();
+    return section;
+  }
+
+  async updateSections() {
+    let sectionHandler = this;
+    try {
+      const response = await fetch("/api/Section/", {
+        method: "GET",
+        headers: new Headers({
+          "XSRF-Token": current_user.xsrftoken,
+        }),
+      });
+      if (response.status !== 200) {
+        throw new Error(
+          `Sections could not be fetched (status ${response.status})`
+        );
+      }
+      let sections = await response.json();
+      return sections.filter(function (section) {
+        return section.AreaID == sectionHandler.area.ID;
+      });
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+  }
+
+  async deleteSection(section) {
+    try {
+      const response = await fetch("/api/Section/" + section.ID, {
+        method: "delete",
+        headers: new Headers({
+          "XSRF-Token": current_user.xsrftoken,
+        }),
+      });
+      if (response.status !== 200) {
+        throw new Error(
+          `Section could not be deleted (status ${response.status})`
+        );
+      }
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+    this.displaySections();
+    this.parent.deskHandler.emptyDesks();
+    document.getElementById("desk-new").setAttribute("disabled", "true");
+  }
+}
diff --git a/web/components/users/handleUser.js b/web/components/users/handleUser.js
index 3626f1ace1f08a224b4d5304b3a8f4abb35a342a..1778178cefa549b16ae04fd8b8f5bf482085ec8d 100644
--- a/web/components/users/handleUser.js
+++ b/web/components/users/handleUser.js
@@ -2,7 +2,7 @@
 import { RandomString } from "/services/common/common.js";
 import * as Messages from "/services/messages/messages.js";
 import * as Auth from "/services/auth/auth.js";
-import * as Users from "/components/users/users.js";
+import * as Common from "/services/common/common.js";
 
 // DOM elements
 let id_field;
@@ -104,12 +104,12 @@ class HandleUser {
     document
       .getElementById(`users-modal-close`)
       .addEventListener("click", function () {
-        Users.toggleModal("users-modal", "users-modal-card");
+        Common.toggleModal("users-modal", "users-modal-card");
       });
     document
       .getElementById(`users-modal-cancel`)
       .addEventListener("click", function () {
-        Users.toggleModal("users-modal", "users-modal-card");
+        Common.toggleModal("users-modal", "users-modal-card");
       });
     let userHandler = this;
     document
@@ -129,7 +129,7 @@ class HandleUser {
     password_field.value = RandomString(48);
     name_field.value = "";
     role_field.value = "";
-    Users.toggleModal("users-modal", "users-modal-card");
+    Common.toggleModal("users-modal", "users-modal-card");
   }
 
   async deleteUser(user) {
@@ -165,7 +165,7 @@ class HandleUser {
     password_field.value = "";
     name_field.value = user.name;
     role_field.value = user.role;
-    Users.toggleModal("users-modal", "users-modal-card");
+    Common.toggleModal("users-modal", "users-modal-card");
   }
 
   async updateUsers() {
@@ -227,7 +227,7 @@ class HandleUser {
       Messages.Show("is-warning", e.message);
       console.error(e);
     }
-    Users.toggleModal("users-modal", "users-modal-card");
+    Common.toggleModal("users-modal", "users-modal-card");
   }
 
   async postCapturer(user, method) {
diff --git a/web/components/users/users.js b/web/components/users/users.js
index 7be58a02d5f22dd40fe6a7d0b5be277089763436..246c2ae3cd7789221d73b1f4d85b220e54a47793 100644
--- a/web/components/users/users.js
+++ b/web/components/users/users.js
@@ -1,5 +1,4 @@
 // Imports
-import { AnimateCSS } from "/services/common/common.js";
 import * as Auth from "/services/auth/auth.js";
 import { Delete } from "/services/common/delete.js";
 import * as HandleUser from "/components/users/handleUser.js";
@@ -99,19 +98,4 @@ class Users {
       </tr>
     `;
   }
-}
-
-export function toggleModal(modalID, cardID) {
-  const modal = document.getElementById(modalID);
-  const card = document.getElementById(cardID);
-  if (modal.classList.contains("is-active")) {
-    AnimateCSS(modal, "fadeOut");
-    AnimateCSS(card, "zoomOut", function () {
-      modal.classList.remove("is-active");
-    });
-  } else {
-    modal.classList.add("is-active");
-    AnimateCSS(modal, "fadeIn");
-    AnimateCSS(card, "zoomIn");
-  }
-}
+}
\ No newline at end of file
diff --git a/web/services/common/common.js b/web/services/common/common.js
index 7a6b5cbca13b4ae3cc5745f463140be10aafd258..658c53b513515ce6ea3be14b30895d5b5c7499cd 100644
--- a/web/services/common/common.js
+++ b/web/services/common/common.js
@@ -19,4 +19,19 @@ export function RandomString(length) {
     text += possible.charAt(Math.floor(Math.random() * possible.length));
   }
   return text;
-}
\ No newline at end of file
+}
+
+export function toggleModal(modalID, cardID) {
+  const modal = document.getElementById(modalID);
+  const card = document.getElementById(cardID);
+  if (modal.classList.contains("is-active")) {
+    AnimateCSS(modal, "fadeOut");
+    AnimateCSS(card, "zoomOut", function () {
+      modal.classList.remove("is-active");
+    });
+  } else {
+    modal.classList.add("is-active");
+    AnimateCSS(modal, "fadeIn");
+    AnimateCSS(card, "zoomIn");
+  }
+}
diff --git a/web/style.css b/web/style.css
index e3fd68954006a09aa10e5af3e75e14fbddec4980..2267274a1b80fa2ba7c498da1e460938909f241c 100644
--- a/web/style.css
+++ b/web/style.css
@@ -90,4 +90,17 @@ img {
 
 .select, select{
   width :100%;
+}
+
+.card-list{
+  border: solid lightgray;
+  border-width: 0.5px;
+  border-radius: 2px;
+  margin:6px;
+}
+
+.active-card{
+  background-color: rgba(55,122,195,.95);
+  font-weight: bold;
+  color: white;
 }
\ No newline at end of file