Procházet zdrojové kódy

implement inscriptions import in planning

tripeur před 4 roky
rodič
revize
a78f4cd158
2 změnil soubory, kde provedl 178 přidání a 1 odebrání
  1. 164 0
      src/components/ManageRegistration.vue
  2. 14 1
      src/views/BenevoleManager.vue

+ 164 - 0
src/components/ManageRegistration.vue

@@ -0,0 +1,164 @@
+<template>
+  <dots v-if="loading" />
+  <div v-else>
+    <h3>Liste de demande d'inscription des bénévoles</h3>
+    <div class="actions">
+      <button class="btn small primary" @click="importSelected">
+        <i class="material-icons">input</i>Importer la selection
+      </button>
+      <button class="btn small error" @click="deleteSelected">
+        <i class="material-icons">delete_forever</i>Supprimer la selection
+      </button>
+    </div>
+
+    <table>
+      <thead>
+        <tr>
+          <th @click="selectAll">
+            <i class="material-icons">{{ topBox }}</i>
+          </th>
+          <th>Nom</th>
+          <th>Email</th>
+        </tr>
+      </thead>
+      <tbody>
+        <tr v-for="b in inscriptions" :key="b.id">
+          <td @click="toggle(b.id)">
+            <i class="material-icons">{{ checkbox(b.id) }}</i>
+          </td>
+          <td>{{ b.name }}, {{ b.surname }}</td>
+          <td>{{ b.email }}</td>
+        </tr>
+      </tbody>
+    </table>
+  </div>
+</template>
+
+<script lang="ts">
+import Benevole, { BenevoleJSON } from "@/models/Benevole";
+import { defineComponent } from "vue";
+
+import dots from "@/components/Dots.vue";
+import { MutationTypes } from "@/store/Mutations";
+
+const API_URL = process.env.VUE_APP_API_URL;
+
+export default defineComponent({
+  components: { dots },
+  data() {
+    return {
+      inscriptions: [] as Array<BenevoleJSON>,
+      loading: true,
+      selected: [] as Array<number>,
+    };
+  },
+  methods: {
+    toggle(id: number) {
+      if (this.selected.includes(id)) {
+        this.selected = this.selected.filter((o) => o != id);
+      } else {
+        this.selected.push(id);
+      }
+    },
+    checkbox(id: number) {
+      return this.selected.includes(id) ? "check_box" : "check_box_outline_blank";
+    },
+    selectAll() {
+      this.selected =
+        this.selected.length == this.inscriptions.length
+          ? []
+          : (this.inscriptions.map((b) => b.id) as Array<number>);
+    },
+    importSelected() {
+      for (const benevole of this.selectedInscriptions) {
+        this.$store.commit(
+          MutationTypes.addBenevole,
+          Benevole.fromJSON({ ...benevole, id: undefined })
+        );
+      }
+      this.deleteSelected();
+    },
+    deleteSelected() {
+      for (const benevole of this.selectedInscriptions) {
+        fetch(`${API_URL}api/inscription/${this.uuid}/${benevole.id}`, { method: "DELETE" }).then(
+          (res) => {
+            if (res.status == 200) {
+              return res.json();
+            } else {
+              throw new Error(res.statusText);
+            }
+          }
+        );
+      }
+      this.inscriptions = this.inscriptions.filter((b) => b.id && !this.selected.includes(b.id));
+      this.selected = [];
+    },
+  },
+  computed: {
+    uuid(): string {
+      return this.$store.state.evenement.uuid;
+    },
+    selectedInscriptions(): Array<BenevoleJSON> {
+      return this.inscriptions.filter((b) => b.id && this.selected.includes(b.id));
+    },
+    topBox(): string {
+      if (this.selected.length == 0) {
+        return "check_box_outline_blank";
+      } else {
+        if (this.selected.length == this.inscriptions.length) {
+          return "check_box";
+        } else {
+          return "indeterminate_check_box";
+        }
+      }
+    },
+  },
+  mounted() {
+    fetch(`${API_URL}api/inscription/${this.uuid}`)
+      .then((res) => {
+        if (res.status == 200) {
+          return res.json();
+        } else {
+          throw new Error(res.statusText);
+        }
+      })
+      .then((data: Array<BenevoleJSON>) => {
+        this.inscriptions = data;
+        this.loading = false;
+      });
+  },
+});
+</script>
+
+<style scoped>
+.actions {
+  display: inline-flex;
+  justify-content: left;
+  margin-bottom: 12px;
+}
+.actions > .btn {
+  margin-right: 4px;
+}
+table {
+  max-width: 800px;
+  width: 90vw;
+  border-collapse: collapse;
+}
+td,
+th {
+  padding: 0.5rem;
+  width: calc(50% - 24px - 1rem);
+}
+tr > *:first-child {
+  width: calc(24px + 1rem);
+}
+tr {
+  border-bottom: 1px solid #ddd;
+}
+thead > tr {
+  border-bottom-width: 2px;
+}
+tr:nth-child(even) {
+  background-color: #eeeeee;
+}
+</style>

+ 14 - 1
src/views/BenevoleManager.vue

@@ -18,11 +18,17 @@
     />
     <input type="file" ref="loadcsv" @change="importBenevoleTemplate" style="display: none" />
   </div>
+  <div v-if="showModal" class="modal" @click="closeModal">
+    <div class="modal-content" ref="modal">
+      <manage-registration />
+    </div>
+  </div>
 </template>
 
 <script lang="ts">
 import Competence from "@/models/Competence";
 import EditeurBenevole from "@/components/EditeurBenevole.vue";
+import ManageRegistration from "@/components/ManageRegistration.vue";
 import DataTable, {
   CustomButton,
   DataTableData,
@@ -38,8 +44,9 @@ import Toast from "@/utils/Toast";
 const csvDefaultcolumn = "id,prenom,nom,telephone,email,commentaire";
 export default defineComponent({
   name: "EditeurCreneau",
-  components: { DataTable, EditeurBenevole },
+  components: { DataTable, EditeurBenevole, ManageRegistration },
   data: () => ({
+    showModal: false,
     columns: [
       {
         label: "Id",
@@ -112,6 +119,11 @@ export default defineComponent({
     },
   },
   methods: {
+    closeModal(event: MouseEvent) {
+      if (!(this.$refs.modal as HTMLElement).contains(event.target as HTMLElement)) {
+        this.showModal = false;
+      }
+    },
     getFanfareForBenevole(benevole: Benevole): string {
       if (benevole.competenceIdList.length == 0) {
         return "Exte";
@@ -237,6 +249,7 @@ export default defineComponent({
   },
   mounted() {
     this.loading = false;
+    this.customButton.push({ icon: "list", hide: false, onclick: () => (this.showModal = true) });
     this.customButton.push({ icon: "file_download", hide: false, onclick: this.getImportTemplate });
     this.customButton.push({
       icon: "file_upload",