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

     1  <template>
     2    <v-card v-if="groupe != null" :disabled="locked">
     3      <v-dialog v-model="showSelectAddAnimateurs" max-width="600px">
     4        <v-card>
     5          <v-card-title>Ajouter des animateurs</v-card-title>
     6          <v-card-text>
     7            <v-list class="overflow-y-auto" max-height="63vh">
     8              <v-list-item-group multiple v-model="animateursToAdd">
     9                <v-list-item
    10                  v-for="equipier in optionsAnimateurs"
    11                  :key="equipier.value"
    12                  :value="equipier.value"
    13                >
    14                  <template v-slot:default="{ active }">
    15                    <v-list-item-action>
    16                      <v-checkbox
    17                        :input-value="active"
    18                        color="primary"
    19                      ></v-checkbox>
    20                    </v-list-item-action>
    21                    <v-list-item-content>
    22                      {{ equipier.text }}
    23                    </v-list-item-content>
    24                  </template>
    25                </v-list-item>
    26              </v-list-item-group>
    27            </v-list>
    28          </v-card-text>
    29          <v-card-actions>
    30            <v-spacer></v-spacer>
    31            <v-btn
    32              color="success"
    33              :disabled="animateursToAdd.length == 0"
    34              @click="addAnimateurs"
    35              >Ajouter</v-btn
    36            >
    37          </v-card-actions>
    38        </v-card>
    39      </v-dialog>
    40  
    41      <v-card-title> Animateurs du groupe {{ groupe.nom }} </v-card-title>
    42      <v-card-text class="pt-1 pb-1">
    43        <v-row>
    44          <v-col cols="2" class="align-self-center">Animateurs</v-col>
    45          <v-col
    46            ><v-chip
    47              v-for="idAnimateur in animateurs"
    48              :key="idAnimateur"
    49              close
    50              @click:close="deleteAnimateur(idAnimateur)"
    51            >
    52              {{ fmtAnimateur(idAnimateur) }}
    53            </v-chip></v-col
    54          >
    55          <v-col cols="4" class="align-self-center text-right">
    56            <v-btn
    57              color="success"
    58              @click="showSelectAddAnimateurs = true"
    59              class="mr-2"
    60              ><v-icon>{{ $icons["mdi-plus"] }}</v-icon> Ajouter</v-btn
    61            >
    62            <tooltip-btn
    63              color="secondary"
    64              tooltip="Répartir automatiquement les inscrits restant"
    65              :disabled="animateurs.length == 0 || groupeInscrits.length == 0"
    66              @click="autoRepartit"
    67              >Répartir</tooltip-btn
    68            >
    69          </v-col>
    70        </v-row>
    71        <v-row>
    72          <v-col>
    73            <an-petit-groupe
    74              :inscrits="groupeInscrits"
    75              :animateur="null"
    76              @updateInscrits="updateInscritsAnimateur($event, null)"
    77            ></an-petit-groupe>
    78          </v-col>
    79          <v-col v-for="idAnimateur in animateurs" :key="idAnimateur">
    80            <an-petit-groupe
    81              :inscrits="getListeAnimateur(idAnimateur)"
    82              :animateur="getAnimateur(idAnimateur)"
    83              @updateInscrits="updateInscritsAnimateur($event, idAnimateur)"
    84            ></an-petit-groupe>
    85          </v-col>
    86        </v-row>
    87      </v-card-text>
    88    </v-card>
    89  </template>
    90  
    91  <script lang="ts">
    92  import Vue from "vue";
    93  import Component from "vue-class-component";
    94  import {
    95    Groupe,
    96    EquipierDirecteur,
    97    Role,
    98    ParticipantEquipiers,
    99    LoadGroupeAnimateursOut,
   100    Inscrit,
   101    Ids
   102  } from "@/logic/types.ts";
   103  import { C } from "@/logic/controller";
   104  import Equipiers from "@/views/Equipiers.vue";
   105  import { Formatter, nullId, optionnalId } from "@/logic/formatter";
   106  import { Watch } from "vue-property-decorator";
   107  import AnPetitGroupe from "./AnPetitGroupe.vue";
   108  import TooltipBtn from "../TooltipBtn.vue";
   109  
   110  const AnimateursProps = Vue.extend({
   111    props: {
   112      groupe: Object as () => Groupe
   113    }
   114  });
   115  
   116  @Component({
   117    components: { AnPetitGroupe, TooltipBtn }
   118  })
   119  export default class Animateurs extends AnimateursProps {
   120    equipiers: EquipierDirecteur[] = [];
   121    animateursToAdd: number[] = [];
   122  
   123    animateurs: number[] = [];
   124    animateurs_enfants: NonNullable<ParticipantEquipiers> = [];
   125    C = C;
   126  
   127    showSelectAddAnimateurs = false;
   128  
   129    idAnimateurOver: number | null = null;
   130    selectedInscrits: number[] = [];
   131  
   132    fmt = Formatter;
   133  
   134    /** on enlève les animateurs déjà présents */
   135    get optionsAnimateurs() {
   136      return this.equipiers
   137        .filter(eq => !this.animateurs.includes(eq.id))
   138        .filter(
   139          eq =>
   140            (eq.roles || []).includes(Role.RAideAnimation) ||
   141            (eq.roles || []).includes(Role.RAnimation)
   142        )
   143        .sort((a, b) => a.prenom.localeCompare(b.prenom))
   144        .map(eq => ({
   145          value: eq.id,
   146          text: Formatter.nomPrenom(eq)
   147        }));
   148    }
   149  
   150    /** on enlève les inscrits déjà attribués */
   151    get groupeInscrits() {
   152      const attribues = this.animateurs_enfants.map(pe => pe.id_participant);
   153      return C.inscrits
   154        .filter(
   155          insc => insc.id_groupe.Valid && insc.id_groupe.Int64 == this.groupe.id
   156        )
   157        .filter(insc => !attribues.includes(insc.id));
   158    }
   159  
   160    get locked() {
   161      return C.notifications.progress;
   162    }
   163  
   164    getAnimateur(id: number) {
   165      return this.equipiers.find(eq => eq.id === id);
   166    }
   167  
   168    fmtAnimateur(id: number) {
   169      const equi = this.getAnimateur(id);
   170      return equi ? Formatter.prenomN(equi) : "";
   171    }
   172  
   173    getListeAnimateur(idAnimateur: number) {
   174      const mapEnfants: { [key: number]: boolean } = {};
   175      this.animateurs_enfants
   176        .filter(pe => pe.id_equipier == idAnimateur)
   177        .forEach(pe => {
   178          mapEnfants[pe.id_participant] = true;
   179        });
   180      return C.inscrits
   181        .filter(insc => mapEnfants[insc.id])
   182        .sort((a, b) => b.age_debut_camp - a.age_debut_camp);
   183    }
   184  
   185    getNbGroupeAnimateur(idAnimateur: number) {
   186      return this.getListeAnimateur(idAnimateur).length;
   187    }
   188  
   189    async created() {
   190      const data = await C.getEquipiers();
   191      if (data === undefined) return;
   192      this.equipiers = data.equipe || [];
   193      C.notifications.progress = false;
   194      this.loadAnimateurs();
   195    }
   196  
   197    @Watch("groupe.id")
   198    private async loadAnimateurs() {
   199      const dataAnims = await C.getGroupeAnimateurs(this.groupe.id);
   200      if (dataAnims === undefined) return;
   201      this.applyRemoteData(dataAnims);
   202    }
   203  
   204    private applyRemoteData(data: LoadGroupeAnimateursOut) {
   205      this.animateurs = (data.groupe_equipiers || []).map(ge => ge.id_equipier);
   206      this.animateurs_enfants = data.participant_equipiers || [];
   207    }
   208  
   209    async addAnimateurs() {
   210      this.showSelectAddAnimateurs = false;
   211      const data = await C.addGroupeAnimateurs(
   212        this.groupe.id,
   213        this.animateursToAdd
   214      );
   215      if (data == undefined) return;
   216      this.applyRemoteData(data);
   217    }
   218  
   219    async deleteAnimateur(id: number) {
   220      const data = await C.deleteGroupeAnimateur(this.groupe.id, id);
   221      if (data == undefined) return;
   222      this.applyRemoteData(data);
   223    }
   224  
   225    async updateInscritsAnimateur(inscrits: Ids, idAnimateur: number | null) {
   226      const idAnimateurOpt =
   227        idAnimateur === null ? nullId() : optionnalId(idAnimateur);
   228      const animateurs_enfants = await C.updateInscritsAnimateur({
   229        id_groupe: this.groupe.id,
   230        id_animateur: idAnimateurOpt,
   231        id_inscrits: inscrits
   232      });
   233      if (animateurs_enfants === undefined) return;
   234      this.animateurs_enfants = animateurs_enfants || [];
   235    }
   236  
   237    async autoRepartit() {
   238      const animateurs_enfants = await C.autoRepartitInscritAnimateur(
   239        this.groupe.id
   240      );
   241      if (animateurs_enfants === undefined) return;
   242      this.animateurs_enfants = animateurs_enfants || [];
   243    }
   244  }
   245  </script>
   246  
   247  <style scoped></style>