Browse Source

implement inscription page

tripeur 4 years ago
parent
commit
7161ab9bd4
6 changed files with 219 additions and 0 deletions
  1. 199 0
      src/Inscription.vue
  2. 1 0
      src/components/Footer.vue
  3. 5 0
      src/inscription.ts
  4. 3 0
      src/models/Competence.ts
  5. 6 0
      src/views/Evenement.vue
  6. 5 0
      vue.config.js

+ 199 - 0
src/Inscription.vue

@@ -0,0 +1,199 @@
+<template>
+  <c-header title="BDLG Inscription Benevole" />
+  <div style="display: flex; justify-content: center">
+    <dots v-if="status == 'Loading'" />
+    <h2 v-if="status.startsWith('Error')">{{ status }}</h2>
+    <div v-if="status == 'Loaded'" class="inscription-container">
+      <h2>Formulaire d'inscription en tant que bénévole pour {{ evtName }}</h2>
+      <div class="persona">
+        <styled-input class="s6" label="Prénom" id="last_name" type="text" v-model="name" />
+        <styled-input class="s6" label="Nom" id="family_name" type="text" v-model="surname" />
+        <styled-input class="s6" label="Email" id="email" type="email" v-model="email" />
+        <styled-input class="s6" label="Téléphone" id="phone" type="text" v-model="phone" />
+        <styled-input label="Commentaire" id="comment" type="textarea" v-model="comment" />
+      </div>
+      <div>
+        <h3>Fanfares</h3>
+        <check-box
+          v-for="f in fanfares"
+          :help="f.description"
+          :id="f.id"
+          :label="f.name"
+          :key="f.id"
+          @input="toggle($event, f.id)"
+        />
+      </div>
+      <div>
+        <h3>Preference</h3>
+        <check-box
+          v-for="f in preferences"
+          :help="f.description"
+          :id="f.id"
+          :label="f.name"
+          :key="f.id"
+          @input="toggle($event, f.id)"
+        />
+      </div>
+      <div>
+        <h3>Competences & contrainte</h3>
+        <check-box
+          v-for="f in contraintes"
+          :help="f.description"
+          :id="f.id"
+          :label="f.name"
+          :key="f.id"
+          @input="toggle($event, f.id)"
+        />
+      </div>
+      <button class="btn success small" @click="saveBenevole">
+        <i class="material-icons">send</i>S'inscrire
+      </button>
+    </div>
+  </div>
+  <c-footer />
+</template>
+
+<script lang="ts">
+import { defineComponent } from "vue";
+import { validate as validateUuid } from "uuid";
+import cHeader from "@/components/Header.vue";
+import cFooter from "@/components/Footer.vue";
+import styledInput from "@/components/input.vue";
+import checkBox from "@/components/checkBox.vue";
+
+import dots from "@/components/Dots.vue";
+
+import { StateJSON } from "@/store/State";
+import Benevole, { BenevoleJSON } from "@/models/Benevole";
+import Toast from "./utils/Toast";
+import Competence, { ICompetence } from "@/models/Competence";
+
+const API_URL = process.env.VUE_APP_API_URL;
+
+export default defineComponent({
+  components: { cHeader, cFooter, styledInput, checkBox, dots },
+  data() {
+    return {
+      uuid: location.pathname.split("/").pop(),
+      status: "Loading",
+      data: null as StateJSON | null,
+      registration: [] as Array<Benevole>,
+      name: "",
+      surname: "",
+      phone: "",
+      email: "",
+      comment: "",
+      competenceIdList: [] as Array<number>,
+      competences: [] as Array<Competence>,
+    };
+  },
+  computed: {
+    evtName(): string {
+      return this.data?.evenement.name ?? "";
+    },
+    fanfares(): Array<ICompetence> {
+      return this.competences.filter((o) => o.isFanfare);
+    },
+    preferences(): Array<ICompetence> {
+      return this.competences.filter((o) => !o.isFanfare && o.isPreference);
+    },
+    contraintes(): Array<ICompetence> {
+      return this.competences.filter((o) => !o.isFanfare && !o.isPreference);
+    },
+  },
+  methods: {
+    toggle(value: boolean, id: number) {
+      if (value) {
+        this.competenceIdList.push(id);
+      } else {
+        this.competenceIdList = this.competenceIdList.filter((o) => o != id);
+      }
+    },
+    addBenevoles(data: Array<BenevoleJSON>) {
+      this.registration.push(...data.map((o) => Benevole.fromJSON(o)));
+    },
+    saveBenevole() {
+      const benevole: BenevoleJSON = {
+        name: this.name,
+        surname: this.surname,
+        phone: this.phone,
+        email: this.email,
+        comment: this.comment,
+        competenceIdList: this.competenceIdList,
+      };
+      fetch(`${API_URL}api/inscription/${this.uuid}`, {
+        method: "PUT",
+        body: JSON.stringify(benevole),
+        headers: { "Content-Type": "application/json" },
+      })
+        .then((res) => {
+          if (res.status == 200) {
+            return res.json();
+          } else {
+            if (res.status == 409) {
+              Toast({
+                html: "Cette addresse mail à déjà été utiliser pour une autre inscription",
+                classes: "error",
+              });
+            }
+            throw new Error(res.statusText);
+          }
+        })
+        .then((data: BenevoleJSON) => {
+          this.registration.push(Benevole.fromJSON(data));
+        });
+    },
+  },
+  mounted() {
+    // Get event data
+    const uuid = this.uuid;
+    if (uuid && validateUuid(uuid)) {
+      fetch(`${API_URL}api/evenements/${uuid}`)
+        .then((res) => {
+          if (res.status == 200) {
+            this.status = "Loaded";
+            return res.json();
+          } else {
+            this.status = "Error 404";
+            throw new Error(res.statusText);
+          }
+        })
+        .then((data: StateJSON) => {
+          this.data = data;
+          this.competences = data.competences.map((o) => Competence.fromJSON(o));
+          this.addBenevoles(data.benevoles);
+        });
+      // Get existing registration
+      fetch(`${API_URL}api/inscription/${uuid}`)
+        .then((res) => {
+          if (res.status == 200) {
+            return res.json();
+          } else {
+            throw new Error(res.statusText);
+          }
+        })
+        .then((data: Array<BenevoleJSON>) => this.addBenevoles(data));
+    } else {
+      this.status = "Error 404";
+    }
+  },
+});
+</script>
+
+<style scoped>
+.inscription-container {
+  max-width: 600px;
+  padding: 8px;
+}
+.persona {
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: space-between;
+}
+.s6 {
+  width: calc(50% - 8px);
+}
+#comment {
+  width: 100%;
+}
+</style>

+ 1 - 0
src/components/Footer.vue

@@ -10,6 +10,7 @@
 import { defineComponent } from "vue";
 const API_URL = process.env.VUE_APP_API_URL;
 export default defineComponent({
+  props: { protected: { type: Boolean, default: true } },
   data() {
     return {
       roles: [] as Array<string>,

+ 5 - 0
src/inscription.ts

@@ -0,0 +1,5 @@
+import { createApp } from "vue";
+import Inscription from "./Inscription.vue";
+
+const app = createApp(Inscription);
+app.mount("#app");

+ 3 - 0
src/models/Competence.ts

@@ -59,6 +59,9 @@ export default class Competence {
   get fullname(): string {
     return this.name + (this.isPreference ? " (P)" : " (C)");
   }
+  get isFanfare(): boolean {
+    return this.name.startsWith("Fanfare");
+  }
   static fromObject(obj: ICompetence): Competence {
     let id: number;
     if (obj.id && !isNaN(obj.id)) {

+ 6 - 0
src/views/Evenement.vue

@@ -58,6 +58,9 @@
         <button class="btn primary small" @click="copyLink">
           <i class="material-icons">content_copy</i>Lien pour les bénévoles
         </button>
+        <a v-if="inscription" class="btn primary small" :href="inscription">
+          <i class="material-icons">launch</i>Page pour l'inscription
+        </a>
       </div>
     </div>
     <div v-if="showModal" class="modal" @click="toggleModal">
@@ -153,6 +156,9 @@ export default defineComponent({
     planningVersions(): Array<EvenementVersion> {
       return this.$store.state.history;
     },
+    inscription(): string {
+      return this.planningVersions.length > 0 ? `/inscription/${this.evenement.uuid}` : "";
+    },
   },
   methods: {
     copyLink() {

+ 5 - 0
vue.config.js

@@ -22,6 +22,11 @@ module.exports = {
       title: "BDLG planner - Admninistration",
       filename: "admin/index.html",
     },
+    inscription: {
+      entry: "./src/inscription.ts",
+      title: "BDLG inscription bénévole",
+      filename: "inscription/index.html",
+    },
   },
   outputDir:
     process.env.NODE_ENV === "production"