github.com/benoitkugler/goacve@v0.0.0-20201217100549-151ce6e55dc8/server/frontend/bv/src/pages/vote/personne/App.vue (about)

     1  <template>
     2    <base-app :title="title">
     3      <success v-if="output" :output="output"></success>
     4      <error v-if="output" :output="output"></error>
     5  
     6      <b-container class="my-2 mb-3 mx-auto">
     7        <b-card body-class="py-3 px-3">
     8          <b-card-title>
     9            <b-row>
    10              <b-col>
    11                Votes en cours
    12                <b-badge variant="fushia" v-if="votesCourants > 0">
    13                  {{ votesCourants }}
    14                </b-badge>
    15              </b-col>
    16              <b-col class="text-right">
    17                <b-button
    18                  :href="urlExportVotes"
    19                  target="_blank"
    20                  variant="info"
    21                  title="Télécharger au format PDF"
    22                >
    23                  <b-icon-download></b-icon-download>
    24                  Capture
    25                </b-button>
    26                <b-button
    27                  @click="refresh"
    28                  variant="light"
    29                  class="ml-2"
    30                  v-b-tooltip
    31                  title="Rafraichir les données"
    32                >
    33                  <b-icon-arrow-repeat></b-icon-arrow-repeat>
    34                </b-button>
    35              </b-col>
    36            </b-row>
    37          </b-card-title>
    38          <b-overlay :show="loading">
    39            <b-card-text>
    40              <b-card v-for="(vote, i) in votes" :key="i" class="my-2">
    41                <b-card-title>
    42                  {{ vote.nom }}
    43                  <b-badge variant="warning" v-if="vote.is_locked"
    44                    >Vote cloturé</b-badge
    45                  >
    46                </b-card-title>
    47                <b-card-sub-title class="mb-2">
    48                  {{ vote.description }}</b-card-sub-title
    49                >
    50                <b-card-text>
    51                  <div class="border rounded border-secondary px-2 pt-2">
    52                    <b-form-group>
    53                      <template v-slot:label>
    54                        Mon vote
    55                        <b-badge v-if="hasVoted(vote)">
    56                          dernier vote : {{ formatDateTime(vote.time) }}
    57                        </b-badge>
    58                      </template>
    59                      <b-form-checkbox-group
    60                        v-if="vote.is_qcm"
    61                        :checked="vote.choix || []"
    62                        @change="onCheckboxInputVote(vote, $event)"
    63                        :options="getItems(vote)"
    64                        :disabled="vote.is_locked"
    65                      >
    66                      </b-form-checkbox-group>
    67                      <b-form-radio-group
    68                        v-else
    69                        :options="getItems(vote)"
    70                        :checked="radioChecked(vote.choix)"
    71                        @change="onRadioInputVote(vote, $event)"
    72                        :disabled="vote.is_locked"
    73                      >
    74                      </b-form-radio-group>
    75                    </b-form-group>
    76                  </div>
    77                </b-card-text>
    78                <b-row>
    79                  <b-col>
    80                    <b-button
    81                      :variant="isVoteDeletable(vote) ? 'danger' : 'light'"
    82                      :disabled="!isVoteDeletable(vote)"
    83                      @click="resetVote(vote)"
    84                      >Effacer mon vote</b-button
    85                    >
    86                  </b-col>
    87                  <b-col class="text-right">
    88                    <b-button
    89                      :variant="isVoteDoable(vote) ? 'success' : 'light'"
    90                      @click="save(vote)"
    91                      :disabled="!isVoteDoable(vote)"
    92                      >Enregistrer mon vote</b-button
    93                    >
    94                  </b-col>
    95                </b-row>
    96              </b-card>
    97            </b-card-text>
    98          </b-overlay>
    99        </b-card>
   100      </b-container>
   101    </base-app>
   102  </template>
   103  
   104  <script lang="ts">
   105  import Vue from "vue";
   106  import Component from "vue-class-component";
   107  import BaseApp from "@/BaseApp.vue";
   108  import Success from "@/shared/notifications/Success.vue";
   109  import Error from "@/shared/notifications/Error.vue";
   110  import { C, BASE_URL } from "./controller";
   111  import { VotePersonneComplet, Ids, MetaPersonne } from "@/shared/logic/types";
   112  import {
   113    formatDateTime,
   114    decodeServerPayload,
   115    isNullDateString
   116  } from "../../../shared/logic/utils";
   117  
   118  type DirtyVote = VotePersonneComplet & { isDirty?: boolean };
   119  
   120  @Component({
   121    components: { BaseApp, Success, Error }
   122  })
   123  export default class App extends Vue {
   124    personne = decodeServerPayload<MetaPersonne>();
   125  
   126    output = C.notifications;
   127    loading = false;
   128    votes: DirtyVote[] = [];
   129  
   130    formatDateTime = formatDateTime;
   131  
   132    urlExportVotes = BASE_URL + "/export";
   133  
   134    created() {
   135      this.refresh();
   136    }
   137  
   138    async refresh() {
   139      this.loading = true;
   140      const data = await C.getVotes();
   141      this.loading = false;
   142      if (data == undefined) return;
   143      this.votes = data || [];
   144      C.notifications.success = {
   145        title: "Propositions",
   146        message: "Propositions chargées"
   147      };
   148    }
   149  
   150    get title() {
   151      if (this.personne == null) return "";
   152      return "Page de vote de " + this.personne.prenom_nom;
   153    }
   154  
   155    get votesCourants() {
   156      return this.votes.filter(v => isNullDateString(v.time)).length;
   157    }
   158  
   159    getItems(vote: VotePersonneComplet) {
   160      return (vote.candidats || []).map(cd => {
   161        return { value: cd.id, text: cd.label };
   162      });
   163    }
   164  
   165    hasVoted(vote: VotePersonneComplet) {
   166      return !isNullDateString(vote.time);
   167    }
   168  
   169    isVoteDeletable(vote: VotePersonneComplet) {
   170      return !vote.is_locked && this.hasVoted(vote);
   171    }
   172  
   173    isVoteDoable(vote: DirtyVote) {
   174      return !vote.is_locked && vote.isDirty;
   175    }
   176  
   177    onCheckboxInputVote(vote: DirtyVote, choix: number[]) {
   178      vote.choix = choix;
   179      vote.isDirty = true;
   180    }
   181  
   182    radioChecked(choix: Ids) {
   183      choix = choix || [];
   184      if (choix.length > 0) {
   185        return choix[0];
   186      }
   187      return null;
   188    }
   189  
   190    onRadioInputVote(vote: DirtyVote, choix: number | null) {
   191      vote.choix = choix == null ? [] : [choix];
   192      vote.isDirty = true;
   193    }
   194  
   195    async save(vote: VotePersonneComplet) {
   196      this.loading = true;
   197      const data = await C.doVote(vote);
   198      this.loading = false;
   199      if (data == undefined) return;
   200      this.votes = data || [];
   201      C.notifications.success = {
   202        title: "Vote",
   203        message: "Votre vote a bien été enregistré. Merci !"
   204      };
   205    }
   206  
   207    async resetVote(vote: VotePersonneComplet) {
   208      this.loading = true;
   209      const data = await C.resetVote(vote.id);
   210      this.loading = false;
   211      if (data == undefined) return;
   212      this.votes = data || [];
   213      C.notifications.success = {
   214        title: "Suppression",
   215        message: "Votre vote a bien été effacé."
   216      };
   217    }
   218  }
   219  </script>
   220  
   221  <style></style>