440 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			440 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
<template>
 | 
						|
  <div class="page-container">
 | 
						|
    <h1 class="title">Virtuelt lotteri registrering</h1>
 | 
						|
    <br />
 | 
						|
    <div class="draw-winner-container" v-if="attendees.length > 0">
 | 
						|
      <div v-if="drawingWinner">
 | 
						|
        <span>
 | 
						|
          Trekker {{ currentWinners }} av {{ numberOfWinners }} vinnere.
 | 
						|
          {{ secondsLeft }} sekunder av {{ drawTime }} igjen
 | 
						|
        </span>
 | 
						|
        <button class="vin-button no-margin" @click="stopDraw">Stopp trekning</button>
 | 
						|
      </div>
 | 
						|
      <div class="draw-container" v-if="!drawingWinner">
 | 
						|
        <button class="vin-button no-margin" @click="drawWinner">Trekk vinnere</button>
 | 
						|
        <input type="number" v-model="numberOfWinners" />
 | 
						|
      </div>
 | 
						|
    </div>
 | 
						|
    <h2 v-if="winners.length > 0">Vinnere</h2>
 | 
						|
    <div class="winners" v-if="winners.length > 0">
 | 
						|
      <div class="winner" v-for="(winner, index) in winners" :key="index">
 | 
						|
        <div :class="winner.color + '-raffle'" class="raffle-element">
 | 
						|
          <span>{{ winner.name }}</span>
 | 
						|
          <span>{{ winner.phoneNumber }}</span>
 | 
						|
          <span>Rød: {{ winner.red }}</span>
 | 
						|
          <span>Blå: {{ winner.blue }}</span>
 | 
						|
          <span>Grønn: {{ winner.green }}</span>
 | 
						|
          <span>Gul: {{ winner.yellow }}</span>
 | 
						|
        </div>
 | 
						|
      </div>
 | 
						|
    </div>
 | 
						|
    <div class="delete-buttons" v-if="attendees.length > 0 || winners.length > 0">
 | 
						|
      <button
 | 
						|
        class="vin-button"
 | 
						|
        v-if="winners.length > 0"
 | 
						|
        @click="deleteAllWinners"
 | 
						|
      >Slett virtuelle vinnere</button>
 | 
						|
      <button
 | 
						|
        class="vin-button"
 | 
						|
        v-if="attendees.length > 0"
 | 
						|
        @click="deleteAllAttendees"
 | 
						|
      >Slett virtuelle deltakere</button>
 | 
						|
    </div>
 | 
						|
    <div class="attendees" v-if="attendees.length > 0">
 | 
						|
      <h2>Deltakere ({{ attendees.length }})</h2>
 | 
						|
      <div class="attendee" v-for="(attendee, index) in attendees" :key="index">
 | 
						|
        <div class="name-and-phone">
 | 
						|
          <span class="name">{{ attendee.name }}</span>
 | 
						|
          <span class="phoneNumber">{{ attendee.phoneNumber }}</span>
 | 
						|
        </div>
 | 
						|
        <div class="raffles-container">
 | 
						|
          <div class="red-raffle raffle-element small">{{ attendee.red }}</div>
 | 
						|
          <div class="blue-raffle raffle-element small">{{ attendee.blue }}</div>
 | 
						|
          <div class="green-raffle raffle-element small">{{ attendee.green }}</div>
 | 
						|
          <div class="yellow-raffle raffle-element small">{{ attendee.yellow }}</div>
 | 
						|
        </div>
 | 
						|
      </div>
 | 
						|
    </div>
 | 
						|
    <div class="attendee-registration-container">
 | 
						|
      <h2>Legg til deltaker</h2>
 | 
						|
      <div class="label-div">
 | 
						|
        <label for="name">Navn</label>
 | 
						|
        <input id="name" type="text" placeholder="Navn" v-model="name" />
 | 
						|
      </div>
 | 
						|
      <br />
 | 
						|
      <div class="label-div">
 | 
						|
        <label for="phoneNumber">Telefonnummer</label>
 | 
						|
        <input id="phoneNumber" type="text" placeholder="Telefonnummer" v-model="phoneNumber" />
 | 
						|
      </div>
 | 
						|
      <br />
 | 
						|
      <br />
 | 
						|
      <div class="label-div">
 | 
						|
        <label for="randomColors">Tilfeldig farger?</label>
 | 
						|
        <input
 | 
						|
          id="randomColors"
 | 
						|
          type="checkbox"
 | 
						|
          placeholder="Tilfeldig farger"
 | 
						|
          v-model="randomColors"
 | 
						|
        />
 | 
						|
      </div>
 | 
						|
      <div v-if="!randomColors">
 | 
						|
        <br />
 | 
						|
        <br />
 | 
						|
        <div class="label-div">
 | 
						|
          <label for="red">Rød</label>
 | 
						|
          <input id="red" type="number" placeholder="Rød" v-model="red" />
 | 
						|
        </div>
 | 
						|
        <br />
 | 
						|
        <div class="label-div">
 | 
						|
          <label for="blue">Blå</label>
 | 
						|
          <input id="blue" type="number" placeholder="Blå" v-model="blue" />
 | 
						|
        </div>
 | 
						|
        <br />
 | 
						|
        <div class="label-div">
 | 
						|
          <label for="green">Grønn</label>
 | 
						|
          <input id="green" type="number" placeholder="Grønn" v-model="green" />
 | 
						|
        </div>
 | 
						|
        <br />
 | 
						|
        <div class="label-div">
 | 
						|
          <label for="yellow">Gul</label>
 | 
						|
          <input id="yellow" type="number" placeholder="Gul" v-model="yellow" />
 | 
						|
        </div>
 | 
						|
      </div>
 | 
						|
      <div v-else>
 | 
						|
        <RaffleGenerator @colors="setWithRandomColors" :generateOnInit="true" />
 | 
						|
      </div>
 | 
						|
    </div>
 | 
						|
    <br />
 | 
						|
    <button class="vin-button" @click="sendAttendee">Send deltaker</button>
 | 
						|
 | 
						|
    <TextToast v-if="showToast" :text="toastText" v-on:closeToast="showToast = false" />
 | 
						|
  </div>
 | 
						|
</template>
 | 
						|
 | 
						|
<script>
 | 
						|
import io from "socket.io-client";
 | 
						|
import {
 | 
						|
  addAttendee,
 | 
						|
  getVirtualWinner,
 | 
						|
  attendeesSecure,
 | 
						|
  attendees,
 | 
						|
  winnersSecure,
 | 
						|
  deleteWinners,
 | 
						|
  deleteAttendees,
 | 
						|
  finishedDraw,
 | 
						|
  prelottery
 | 
						|
} from "@/api";
 | 
						|
import TextToast from "@/ui/TextToast";
 | 
						|
import RaffleGenerator from "@/ui/RaffleGenerator";
 | 
						|
 | 
						|
export default {
 | 
						|
  components: {
 | 
						|
    RaffleGenerator,
 | 
						|
    TextToast
 | 
						|
  },
 | 
						|
  data() {
 | 
						|
    return {
 | 
						|
      name: null,
 | 
						|
      phoneNumber: null,
 | 
						|
      red: 0,
 | 
						|
      blue: 0,
 | 
						|
      green: 0,
 | 
						|
      yellow: 0,
 | 
						|
      raffles: 0,
 | 
						|
      randomColors: false,
 | 
						|
      attendees: [],
 | 
						|
      winners: [],
 | 
						|
      drawingWinner: false,
 | 
						|
      secondsLeft: 20,
 | 
						|
      drawTime: 20,
 | 
						|
      currentWinners: 1,
 | 
						|
      numberOfWinners: 4,
 | 
						|
      socket: null,
 | 
						|
      toastText: undefined,
 | 
						|
      showToast: false
 | 
						|
    };
 | 
						|
  },
 | 
						|
  mounted() {
 | 
						|
    this.getAttendees();
 | 
						|
    this.getWinners();
 | 
						|
 | 
						|
    this.socket = io(`${window.location.hostname}:${window.location.port}`);
 | 
						|
 | 
						|
    this.socket.on("winner", async msg => {
 | 
						|
      this.getWinners();
 | 
						|
      this.getAttendees();
 | 
						|
    });
 | 
						|
 | 
						|
    this.socket.on("refresh_data", async msg => {
 | 
						|
      this.getAttendees();
 | 
						|
      this.getWinners();
 | 
						|
    });
 | 
						|
 | 
						|
    this.socket.on("new_attendee", async msg => {
 | 
						|
      this.getAttendees();
 | 
						|
    });
 | 
						|
 | 
						|
    window.finishedDraw = finishedDraw;
 | 
						|
  },
 | 
						|
  methods: {
 | 
						|
    setWithRandomColors(colors) {
 | 
						|
      Object.keys(colors).forEach(color => (this[color] = colors[color]));
 | 
						|
    },
 | 
						|
    sendAttendee: async function() {
 | 
						|
      if (this.red == 0 && this.blue == 0 && this.green == 0 && this.yellow == 0) {
 | 
						|
        alert('Ingen farger valgt!')
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      if (this.name == 0 && this.phoneNumber) {
 | 
						|
        alert('Ingen navn eller tlf satt!')
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      let response = await addAttendee({
 | 
						|
        name: this.name,
 | 
						|
        phoneNumber: this.phoneNumber,
 | 
						|
        red: this.red,
 | 
						|
        blue: this.blue,
 | 
						|
        green: this.green,
 | 
						|
        yellow: this.yellow,
 | 
						|
        raffles: this.raffles
 | 
						|
      });
 | 
						|
 | 
						|
      if (response == true) {
 | 
						|
        this.toastText = `Sendt inn deltaker: ${this.name}`;
 | 
						|
        this.showToast = true;
 | 
						|
 | 
						|
        this.name = null;
 | 
						|
        this.phoneNumber = null;
 | 
						|
        this.yellow = 0;
 | 
						|
        this.green = 0;
 | 
						|
        this.red = 0;
 | 
						|
        this.blue = 0;
 | 
						|
 | 
						|
        this.getAttendees();
 | 
						|
      } else {
 | 
						|
        alert("Klarte ikke sende inn.. Er du logget inn?");
 | 
						|
      }
 | 
						|
    },
 | 
						|
    getAttendees: async function() {
 | 
						|
      let response = await attendeesSecure();
 | 
						|
      this.attendees = response;
 | 
						|
    },
 | 
						|
    stopDraw: function() {
 | 
						|
      this.drawingWinner = false;
 | 
						|
      this.secondsLeft = this.drawTime;
 | 
						|
    },
 | 
						|
    drawWinner: async function() {
 | 
						|
      if (window.confirm("Er du sikker på at du vil trekke vinnere?")) {
 | 
						|
        this.drawingWinner = true;
 | 
						|
        let response = await getVirtualWinner();
 | 
						|
 | 
						|
        if (response.success) {
 | 
						|
          console.log("Winner:", response.winner);
 | 
						|
          if (this.currentWinners < this.numberOfWinners) {
 | 
						|
            this.countdown();
 | 
						|
          } else {
 | 
						|
            this.drawingWinner = false;
 | 
						|
            let finished = await finishedDraw();
 | 
						|
            if(finished) {
 | 
						|
              alert("SMS'er er sendt ut!");
 | 
						|
            } else {
 | 
						|
              alert("Noe gikk galt under SMS utsendelser.. Sjekk logg og database for id'er.");
 | 
						|
            }
 | 
						|
          }
 | 
						|
          this.getWinners();
 | 
						|
          this.getAttendees();
 | 
						|
        } else {
 | 
						|
          this.drawingWinner = false;
 | 
						|
          alert("Noe gikk galt under trekningen..! " + response["message"]);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    },
 | 
						|
    countdown: function() {
 | 
						|
      this.secondsLeft -= 1;
 | 
						|
      if (!this.drawingWinner) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      if (this.secondsLeft <= 0) {
 | 
						|
        this.secondsLeft = this.drawTime;
 | 
						|
        this.currentWinners += 1;
 | 
						|
        if (this.currentWinners <= this.numberOfWinners) {
 | 
						|
          this.drawWinner();
 | 
						|
        } else {
 | 
						|
          this.drawingWinner = false;
 | 
						|
        }
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      setTimeout(() => {
 | 
						|
        this.countdown();
 | 
						|
      }, 1000);
 | 
						|
    },
 | 
						|
    deleteAllWinners: async function() {
 | 
						|
      if (window.confirm("Er du sikker på at du vil slette vinnere?")) {
 | 
						|
        let response = await deleteWinners();
 | 
						|
        if (response) {
 | 
						|
          this.getWinners();
 | 
						|
        } else {
 | 
						|
          alert("Klarte ikke hente ut vinnere");
 | 
						|
        }
 | 
						|
      }
 | 
						|
    },
 | 
						|
    deleteAllAttendees: async function() {
 | 
						|
      if (window.confirm("Er du sikker på at du vil slette alle deltakere?")) {
 | 
						|
        let response = await deleteAttendees();
 | 
						|
        if (response) {
 | 
						|
          this.getAttendees();
 | 
						|
        } else {
 | 
						|
          alert("Klarte ikke hente ut vinnere");
 | 
						|
        }
 | 
						|
      }
 | 
						|
    },
 | 
						|
    getWinners: async function() {
 | 
						|
      let response = await winnersSecure();
 | 
						|
      if (response) {
 | 
						|
        this.winners = response;
 | 
						|
      } else {
 | 
						|
        alert("Klarte ikke hente ut vinnere");
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
};
 | 
						|
</script>
 | 
						|
 | 
						|
<style lang="scss" scoped>
 | 
						|
@import "../styles/global.scss";
 | 
						|
@import "../styles/media-queries.scss";
 | 
						|
 | 
						|
.draw-container {
 | 
						|
  display: flex;
 | 
						|
  justify-content: space-around;
 | 
						|
}
 | 
						|
 | 
						|
.draw-winner-container,
 | 
						|
.delete-buttons {
 | 
						|
  margin-bottom: 20px;
 | 
						|
}
 | 
						|
 | 
						|
.delete-buttons {
 | 
						|
  display: flex;
 | 
						|
}
 | 
						|
 | 
						|
h1 {
 | 
						|
  width: 100%;
 | 
						|
  text-align: center;
 | 
						|
  font-family: knowit, Arial;
 | 
						|
}
 | 
						|
 | 
						|
h2 {
 | 
						|
  width: 100%;
 | 
						|
  text-align: center;
 | 
						|
  font-size: 1.6rem;
 | 
						|
  font-family: knowit, Arial;
 | 
						|
}
 | 
						|
 | 
						|
hr {
 | 
						|
  width: 90%;
 | 
						|
  margin: 2rem auto;
 | 
						|
  color: grey;
 | 
						|
}
 | 
						|
 | 
						|
.page-container {
 | 
						|
  padding: 0 1.5rem 3rem;
 | 
						|
 | 
						|
  @include desktop {
 | 
						|
    max-width: 60vw;
 | 
						|
    margin: 0 auto;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
#randomColors {
 | 
						|
  width: 40px;
 | 
						|
  height: 40px;
 | 
						|
  &:checked {
 | 
						|
    background: green;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
.raffle-element {
 | 
						|
  width: 140px;
 | 
						|
  height: 150px;
 | 
						|
  margin: 20px 0;
 | 
						|
  -webkit-mask-image: url(/public/assets/images/lodd.svg);
 | 
						|
  background-repeat: no-repeat;
 | 
						|
  mask-image: url(/public/assets/images/lodd.svg);
 | 
						|
  -webkit-mask-repeat: no-repeat;
 | 
						|
  mask-repeat: no-repeat;
 | 
						|
  color: #333333;
 | 
						|
  font-size: 0.75rem;
 | 
						|
  font-weight: bold;
 | 
						|
  display: flex;
 | 
						|
  justify-content: center;
 | 
						|
  align-items: center;
 | 
						|
  text-align: center;
 | 
						|
  flex-direction: column;
 | 
						|
 | 
						|
  &.small {
 | 
						|
    width: 45px;
 | 
						|
    height: 45px;
 | 
						|
    font-size: 1rem;
 | 
						|
  }
 | 
						|
 | 
						|
  &.green-raffle {
 | 
						|
    background-color: $light-green;
 | 
						|
  }
 | 
						|
 | 
						|
  &.blue-raffle {
 | 
						|
    background-color: $light-blue;
 | 
						|
  }
 | 
						|
 | 
						|
  &.yellow-raffle {
 | 
						|
    background-color: $light-yellow;
 | 
						|
  }
 | 
						|
 | 
						|
  &.red-raffle {
 | 
						|
    background-color: $light-red;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
button {
 | 
						|
  display: flex !important;
 | 
						|
  margin: auto !important;
 | 
						|
}
 | 
						|
 | 
						|
.winners {
 | 
						|
  display: flex;
 | 
						|
  justify-content: space-around;
 | 
						|
  align-items: center;
 | 
						|
}
 | 
						|
 | 
						|
.attendees {
 | 
						|
  display: flex;
 | 
						|
  flex-direction: column;
 | 
						|
  justify-content: center;
 | 
						|
  align-items: center;
 | 
						|
}
 | 
						|
 | 
						|
.attendee {
 | 
						|
  display: flex;
 | 
						|
  flex-direction: row;
 | 
						|
  justify-content: space-between;
 | 
						|
  align-items: center;
 | 
						|
  width: 50%;
 | 
						|
  margin: 0 auto;
 | 
						|
 | 
						|
  & .name-and-phone,
 | 
						|
  & .raffles-container {
 | 
						|
    display: flex;
 | 
						|
    justify-content: center;
 | 
						|
  }
 | 
						|
 | 
						|
  & .name-and-phone {
 | 
						|
    flex-direction: column;
 | 
						|
  }
 | 
						|
 | 
						|
  & .raffles-container {
 | 
						|
    flex-direction: row;
 | 
						|
  }
 | 
						|
}
 | 
						|
</style>
 |