github.com/benoitkugler/goacve@v0.0.0-20201217100549-151ce6e55dc8/server/frontend/directeurs/src/views/Equipiers.vue (about)

     1  <template>
     2    <v-container fluid>
     3      <v-dialog
     4        v-model="showAddEquipier"
     5        max-width="1200px"
     6        @keydown.esc="showAddEquipier = false"
     7      >
     8        <add-equipier @ajoute-equipier="ajouteEquipier"></add-equipier>
     9      </v-dialog>
    10  
    11      <v-dialog v-model="showEditDialog" max-width="1200px" persistent>
    12        <form-equipier
    13          :equipier="editEquipier"
    14          withButtons
    15          withDetails
    16          @reject="showEditDialog = false"
    17          @accept="updateEquipier"
    18        ></form-equipier>
    19      </v-dialog>
    20  
    21      <v-dialog v-model="confirmeSupprime" max-width="400px">
    22        <v-card v-if="equipierSupprime != null">
    23          <v-card-title class="headline">Suppression d'un équipier</v-card-title>
    24          <v-card-text>
    25            Etes vous sur de retirer
    26            <b>{{ equipierSupprime.prenom }} {{ equipierSupprime.nom }}</b> de
    27            votre équipe ?
    28          </v-card-text>
    29          <v-card-actions>
    30            <v-btn @click="confirmeSupprime = false">Annuler</v-btn>
    31            <v-spacer></v-spacer>
    32            <v-btn @click="supprimeEquipier" class="error--text">
    33              Retirer de l'équipe
    34            </v-btn>
    35          </v-card-actions>
    36        </v-card>
    37      </v-dialog>
    38  
    39      <v-dialog v-model="showDocuments" eager>
    40        <documents ref="documents"></documents>
    41      </v-dialog>
    42  
    43      <v-dialog v-model="showInviteFormulaires">
    44        <formulaires v-model="items"></formulaires>
    45      </v-dialog>
    46  
    47      <v-toolbar dense>
    48        <v-menu open-on-hover bottom offset-y>
    49          <template v-slot:activator="{ on }">
    50            <v-btn v-on="on" icon>
    51              <v-icon>{{ $icons["mdi-information-outline"] }}</v-icon>
    52            </v-btn>
    53          </template>
    54          <v-card>
    55            <v-card-text>
    56              <b>{{ nbMembres }}</b> équipier(s)
    57              <br />
    58              <b>{{ nbAnims }}</b> animateur(s)
    59            </v-card-text>
    60          </v-card>
    61        </v-menu>
    62        <v-toolbar-title>Liste des équipiers </v-toolbar-title>
    63        <v-spacer></v-spacer>
    64        <v-toolbar-items>
    65          <tooltip-btn
    66            tooltip="Rechercher et déclarer un nouvel équipier"
    67            @click="showAddEquipier = true"
    68            text
    69            small
    70          >
    71            <v-icon class="mr-1" color="success">{{ $icons["mdi-plus"] }}</v-icon
    72            >Ajouter un équipier
    73          </tooltip-btn>
    74          <v-divider vertical></v-divider>
    75          <tooltip-btn
    76            tooltip="Inviter les équipiers à remplir leur formulaire..."
    77            @click="showInviteFormulaires = true"
    78            text
    79            small
    80          >
    81            <v-icon class="mr-1">{{ $icons["mdi-account-details"] }}</v-icon
    82            >Formulaires
    83          </tooltip-btn>
    84          <!-- Export rapides des mails -->
    85          <v-menu>
    86            <template v-slot:activator="{ on: menu }">
    87              <v-tooltip bottom>
    88                <template v-slot:activator="{ on: tooltip }">
    89                  <v-btn v-on="{ ...tooltip, ...menu }" depressed>Mails</v-btn>
    90                </template>
    91                Envoyer un mail à l'équipe...
    92              </v-tooltip>
    93            </template>
    94            <v-list>
    95              <v-list-item>
    96                <v-list-item-content>
    97                  <a :href="mailtoEquipe"> Mail à toute l'équipe</a>
    98                </v-list-item-content>
    99                <v-list-item-action>
   100                  <tooltip-btn
   101                    tooltip="Copier les adresses"
   102                    @click="copyMailsToClipboard(false)"
   103                    icon
   104                  >
   105                    <v-icon>{{ $icons["mdi-content-copy"] }} </v-icon>
   106                  </tooltip-btn>
   107                </v-list-item-action>
   108              </v-list-item>
   109              <v-list-item>
   110                <v-list-item-content>
   111                  <a :href="mailtoAnims">
   112                    Mail à l'équipe d'animation
   113                  </a>
   114                </v-list-item-content>
   115                <v-list-item-action>
   116                  <tooltip-btn
   117                    tooltip="Copier les adresses"
   118                    @click="copyMailsToClipboard(true)"
   119                    icon
   120                  >
   121                    <v-icon>{{ $icons["mdi-content-copy"] }} </v-icon>
   122                  </tooltip-btn>
   123                </v-list-item-action>
   124              </v-list-item>
   125            </v-list>
   126          </v-menu>
   127          <v-divider vertical></v-divider>
   128          <tooltip-btn
   129            tooltip="Télécharger une liste au format Excel"
   130            @click="exportListe()"
   131            text
   132            small
   133          >
   134            <v-icon class="mr-1">{{ $icons["mdi-download"] }}</v-icon
   135            >Exporter
   136          </tooltip-btn>
   137          <tooltip-btn
   138            tooltip="Afficher les pièces justificatives des membres de l'équipe"
   139            text
   140            small
   141            @click="loadAndShowDocuments"
   142          >
   143            <v-icon class="mr-1">{{ $icons["mdi-folder"] }}</v-icon
   144            >Documents
   145          </tooltip-btn>
   146        </v-toolbar-items>
   147      </v-toolbar>
   148      <v-data-table
   149        :headers="header"
   150        :items="items"
   151        hide-default-footer
   152        class="mt-2"
   153        fixed-header
   154        height="72vh"
   155        dense
   156        :items-per-page="9999"
   157        id="equipiers"
   158        @click:row="
   159          item => {
   160            editEquipier = item;
   161            showEditDialog = true;
   162          }
   163        "
   164      >
   165        <template v-slot:no-data>
   166          <v-alert :value="true" type="warning">
   167            Aucun membre de l'équipe n'est déclaré pour le moment.
   168            <br />
   169            <i>(Vous pouvez ajouter un équipier avec le bouton "Ajouter".)</i>
   170          </v-alert>
   171        </template>
   172  
   173        <template v-slot:[`item.delete`]="{ item }">
   174          <tooltip-btn
   175            :tooltip="'Enlever ' + item.prenom + ' ' + item.nom + ` de l'équipe`"
   176            icon
   177            small
   178            class="mr-2"
   179            color="red"
   180            @click.stop="
   181              () => {
   182                equipierSupprime = item;
   183                confirmeSupprime = true;
   184              }
   185            "
   186          >
   187            <v-icon>
   188              {{ $icons["mdi-delete"] }}
   189            </v-icon>
   190          </tooltip-btn>
   191        </template>
   192        <template v-slot:[`item.nom`]="{ item }">
   193          <div style="width: 100px;">
   194            {{ item.nom }}
   195          </div>
   196        </template>
   197        <template v-slot:[`item.prenom`]="{ item }">
   198          <div style="width: 100px;">
   199            {{ item.prenom }}
   200          </div>
   201        </template>
   202        <template v-slot:[`item.date_naissance`]="{ item }">
   203          <div style="width: 120px;">
   204            {{ fmt.date(item.date_naissance) }}
   205          </div>
   206        </template>
   207        <template v-slot:[`item.roles`]="{ item }">
   208          {{ fmt.roles(item.roles) }}
   209        </template>
   210        <template v-slot:[`item.diplome`]="{ item }">
   211          {{ fmt.diplome(item.diplome) }}
   212        </template>
   213        <template v-slot:[`item.appro`]="{ item }">
   214          {{ fmt.approfondissement(item.appro) }}
   215        </template>
   216        <template v-slot:[`item.sexe`]="{ item }">
   217          {{ fmt.sexe(item.sexe) }}
   218        </template>
   219        <template v-slot:[`item.ville`]="{ item }">
   220          <div style="width: 150px;">
   221            {{ item.ville }}
   222          </div>
   223        </template>
   224        <template v-slot:[`item.departement_naissance`]="{ item }">
   225          <div style="width: 120px;">
   226            {{ fmt.departement(item.departement_naissance) }}
   227          </div>
   228        </template>
   229        <template v-slot:[`item.tels`]="{ item }">
   230          {{ fmt.telephones(item.tels) }}
   231        </template>
   232        <template v-slot:[`item.etudiant`]="{ item }">
   233          {{ fmt.bool(item.etudiant) }}
   234        </template>
   235        <template v-slot:[`item.fonctionnaire`]="{ item }">
   236          {{ fmt.bool(item.fonctionnaire) }}
   237        </template>
   238      </v-data-table>
   239    </v-container>
   240  </template>
   241  
   242  <script lang="ts">
   243  import Vue from "vue";
   244  import Component from "vue-class-component";
   245  import AddEquipier from "@/components/equipiers/AddEquipier.vue";
   246  import { C } from "../logic/controller";
   247  import { CreateEquipierIn, EquipierDirecteur, Role } from "../logic/types";
   248  import FormEquipier from "../components/equipiers/FormEquipier.vue";
   249  import { Formatter } from "@/logic/formatter";
   250  import Documents from "../components/equipiers/Documents.vue";
   251  import Formulaires from "../components/equipiers/Formulaires.vue";
   252  import TooltipBtn from "@/components/TooltipBtn.vue";
   253  
   254  const EquipiersProps = Vue.extend({
   255    props: {}
   256  });
   257  
   258  @Component({
   259    components: { AddEquipier, FormEquipier, Documents, Formulaires, TooltipBtn }
   260  })
   261  export default class Equipiers extends EquipiersProps {
   262    showAddEquipier = false;
   263    items: EquipierDirecteur[] = [];
   264  
   265    confirmeSupprime = false;
   266    equipierSupprime: EquipierDirecteur | null = null;
   267    showEditDialog = false;
   268    editEquipier: EquipierDirecteur | null = null;
   269    showDocuments = false;
   270    showInviteFormulaires = false;
   271    header = [
   272      { text: "", value: "delete", sortable: false },
   273      { text: "Nom", value: "nom", align: "center", sortable: true },
   274      {
   275        text: "Prénom",
   276        value: "prenom",
   277        align: "center",
   278        sortable: true
   279      },
   280      { text: "Rôle", value: "roles", sortable: true },
   281      { text: "Diplôme", value: "diplome", sortable: true, width: "180px" },
   282      { text: "Approfondissement", value: "appro", sortable: true },
   283      {
   284        text: "Sexe",
   285        value: "sexe",
   286        sortable: true
   287      },
   288      {
   289        text: "Nom de jeune fille",
   290        value: "nom_jeune_fille",
   291        sortable: true
   292      },
   293      {
   294        text: "Date de naissance",
   295        value: "date_naissance",
   296        sortable: true,
   297        align: "center",
   298        width: "120px"
   299      },
   300      {
   301        text: "Département de naissance",
   302        value: "departement_naissance",
   303        sortable: true,
   304        width: "40%"
   305      },
   306      {
   307        text: "Ville de naissance",
   308        value: "ville_naissance",
   309        sortable: true,
   310        width: "180px"
   311      },
   312      { text: "Mail", value: "mail", sortable: true },
   313      { text: "Téléphone(s)", value: "tels", sortable: true },
   314      {
   315        text: "Adresse postale",
   316        value: "adresse",
   317        sortable: true,
   318        width: "200px"
   319      },
   320      { text: "Code postal", value: "code_postal", sortable: true },
   321      { text: "Ville", value: "ville", sortable: true },
   322      {
   323        text: "Sécurité sociale",
   324        value: "securite_sociale",
   325        sortable: true,
   326        width: "180px"
   327      },
   328      { text: "Profession", value: "profession", sortable: true, width: "180px" },
   329      { text: "Etudiant", value: "etudiant", sortable: true },
   330      {
   331        text: "Fonctionnaire",
   332        value: "fonctionnaire",
   333        sortable: true
   334      }
   335    ];
   336  
   337    fmt = Formatter;
   338  
   339    $refs!: {
   340      documents: Documents;
   341    };
   342  
   343    get nbMembres() {
   344      return this.items.length;
   345    }
   346    get nbAnims() {
   347      return this.items.filter(r => {
   348        return (
   349          (r.roles || []).includes(Role.RAnimation) ||
   350          (r.roles || []).includes(Role.RAideAnimation)
   351        );
   352      }).length;
   353    }
   354  
   355    private getMails(restrictToAnims: boolean) {
   356      const filtered = restrictToAnims
   357        ? this.items.filter(eq => {
   358            const roles = eq.roles || [];
   359            return (
   360              roles.includes(Role.RDirecteur) ||
   361              roles.includes(Role.RAdjoint) ||
   362              roles.includes(Role.RAnimation) ||
   363              roles.includes(Role.RAideAnimation)
   364            );
   365          })
   366        : this.items;
   367      return filtered
   368        .map(eq => eq.mail.trim())
   369        .filter(m => m != "")
   370        .join(",");
   371    }
   372  
   373    get mailtoEquipe() {
   374      return "mailto:" + this.getMails(false);
   375    }
   376  
   377    get mailtoAnims() {
   378      return "mailto:" + this.getMails(true);
   379    }
   380  
   381    async copyMailsToClipboard(restrictToAnims: boolean) {
   382      C.exportMailsToClipboard(this.getMails(restrictToAnims));
   383    }
   384  
   385    async created() {
   386      const data = await C.getEquipiers();
   387      if (data == undefined) return;
   388      this.items = data.equipe || [];
   389      C.notifications.success = "Equipe chargée";
   390    }
   391  
   392    async ajouteEquipier(params: CreateEquipierIn) {
   393      const data = await C.ajouteEquier(params);
   394      if (data == undefined) return;
   395      this.items = data.equipe || [];
   396      C.notifications.success = "Equipier ajouté avec succès.";
   397    }
   398  
   399    async updateEquipier(item: EquipierDirecteur) {
   400      this.showEditDialog = false;
   401      const data = await C.updateEquipier(item);
   402      if (data == undefined) return;
   403      this.items = data.equipe || [];
   404      C.notifications.success = "Equipier modifié avec succès.";
   405    }
   406  
   407    async supprimeEquipier() {
   408      if (this.equipierSupprime == null) return;
   409      // confirmation déjà demandée
   410      this.confirmeSupprime = false;
   411      const data = await C.deleteEquipier(this.equipierSupprime.id);
   412      if (data == undefined) return;
   413      this.items = data.equipe || [];
   414      C.notifications.success = "Equipier supprimé avec succès.";
   415    }
   416  
   417    async exportListe() {
   418      const fn = await C.export("equipe", {});
   419      if (fn == undefined) return;
   420      C.notifications.success = "Liste des équipiers téléchargée avec succès.";
   421    }
   422  
   423    loadAndShowDocuments() {
   424      this.showDocuments = true;
   425      this.$refs.documents.refresh(false);
   426    }
   427  }
   428  </script>
   429  
   430  <style>
   431  #equipiers tr:hover {
   432    cursor: pointer;
   433  }
   434  </style>