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>