github.com/benoitkugler/goacve@v0.0.0-20201217100549-151ce6e55dc8/server/frontend/directeurs/src/components/inscrits/AnPetitGroupe.vue (about) 1 <template> 2 <div 3 class="overflow-y-auto" 4 dense 5 @dragover="onDragOver" 6 @dragenter="onDragOver" 7 @drop="onDrop" 8 @dragleave="isDraggedOver = false" 9 :style="style" 10 > 11 <v-list> 12 <v-subheader class="px-1"> 13 <v-row no-gutters> 14 <v-col> 15 <span v-if="animateur == null">Sans animateurs</span> 16 <span v-else>{{ fmt.prenomN(animateur) }}</span> 17 </v-col> 18 <v-col class="align-self-center text-right" 19 ><v-chip color="secondary" small pill>{{ 20 inscrits.length 21 }}</v-chip></v-col 22 > 23 </v-row> 24 </v-subheader> 25 <v-list-item-group color="accent" multiple v-model="selectedInscrits"> 26 <v-list-item 27 v-for="inscrit in inscrits" 28 :key="inscrit.id" 29 draggable 30 @dragstart="onDragStart($event, inscrit)" 31 :value="inscrit.id" 32 class="px-1" 33 > 34 <v-row no-gutters> 35 <v-col 36 ><v-chip 37 small 38 pill 39 :color="sexeColor(inscrit.sexe)" 40 class="mr-1 px-2" 41 >{{ shortSexe(inscrit.sexe) }}</v-chip 42 > 43 {{ fmt.prenomN(inscrit) }}</v-col 44 > 45 <v-col class="text-right" cols="2"> 46 {{ inscrit.age_debut_camp }} 47 </v-col> 48 </v-row> 49 </v-list-item> 50 </v-list-item-group> 51 </v-list> 52 </div> 53 </template> 54 55 <script lang="ts"> 56 import Vue from "vue"; 57 import Component from "vue-class-component"; 58 import { Inscrit, EquipierDirecteur, Sexe } from "@/logic/types"; 59 import { Formatter } from "@/logic/formatter"; 60 61 const AnPetitGroupeProps = Vue.extend({ 62 props: { 63 /** si null, signifie liste sans animateur */ 64 animateur: Object as () => EquipierDirecteur | null, 65 /** inscrit du petit groupe */ 66 inscrits: Array as () => Inscrit[] 67 } 68 }); 69 70 @Component({}) 71 export default class AnPetitGroupe extends AnPetitGroupeProps { 72 isDraggedOver = false; 73 74 selectedInscrits: number[] = []; 75 76 fmt = Formatter; 77 78 get style() { 79 const baseStyle = { 80 borderRadius: "10px", 81 minHeight: "50vh", 82 maxHeight: "63vh", 83 border: "" 84 }; 85 if (this.isDraggedOver) { 86 baseStyle["border"] = "1px dotted green"; 87 } else { 88 baseStyle["border"] = "1px solid transparent"; 89 } 90 return baseStyle; 91 } 92 93 shortSexe(sexe: Sexe) { 94 if (sexe == Sexe.SHomme) { 95 return "H"; 96 } else if (sexe == Sexe.SFemme) { 97 return "F"; 98 } 99 return ""; 100 } 101 102 sexeColor(sexe: Sexe) { 103 if (sexe == Sexe.SHomme) { 104 return "blue"; 105 } else if (sexe == Sexe.SFemme) { 106 return "pink"; 107 } 108 return ""; 109 } 110 111 onDragStart(event: DragEvent, inscrit: Inscrit) { 112 if (event.dataTransfer === null) return; 113 // si l'inscrit est dans la sélection actuelle, on prend toute la sélection 114 // sinon on prend uniquement l'inscrit 115 let inscrits = this.selectedInscrits; 116 if (!this.selectedInscrits.includes(inscrit.id)) { 117 inscrits = [inscrit.id]; 118 } 119 120 event.dataTransfer.setData( 121 "application/update-inscrits", 122 JSON.stringify(inscrits) 123 ); 124 event.dataTransfer.setData( 125 "application/animateur-origin", 126 String(this.idAnimateur) 127 ); 128 event.dataTransfer.effectAllowed = "move"; 129 } 130 131 get idAnimateur() { 132 return this.animateur ? this.animateur.id : null; 133 } 134 135 onDragOver(event: DragEvent) { 136 if (event.dataTransfer === null) return; 137 if (event.dataTransfer.types.includes("application/update-inscrits")) { 138 event.preventDefault(); 139 this.isDraggedOver = true; 140 event.dataTransfer.dropEffect = "move"; 141 } 142 } 143 144 onDrop(event: DragEvent) { 145 this.isDraggedOver = false; 146 if (event.dataTransfer === null) return; 147 const originS = event.dataTransfer.getData("application/animateur-origin"); 148 const origin = originS == "null" ? null : Number(originS); 149 if (origin == this.idAnimateur) { 150 return; // on évite une requête inutile 151 } 152 const inscrits = JSON.parse( 153 event.dataTransfer.getData("application/update-inscrits") 154 ); 155 this.$emit("updateInscrits", inscrits); 156 } 157 } 158 </script> 159 160 <style scoped></style>