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>